From 71294af7fac0102d31b327acc21513d599e9d83d Mon Sep 17 00:00:00 2001 From: mono Date: Sat, 14 Mar 2026 22:24:34 -0500 Subject: [PATCH 1/8] #29 docs: add project analysis to AGENTS.md --- AGENTS.md | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 78fb193..1c43663 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,14 +13,19 @@ ``` src/ ├── assets/ # Imágenes, iconos estáticos -├── components/ # Componentes Vue reutilizables +├── components/ # Componentes Vue reutilizables ├── layouts/ # Layouts de página -├── pages/ # Vistas (auto-routed desde文件名) -├── plugins/ # Configuración de Vuetify, etc. -├── router/ # Configuración de rutas -├── services/ # API services (auth.js, etc.) -├── stores/ # Pinia stores -└── styles/ # SCSS settings +├── pages/ # Vistas (auto-routed desde文件名) +├── plugins/ # Configuración de Vuetify, etc. +├── router/ # Configuración de rutas +├── services/ # API services (auth.js, etc.) +│ ├── api.js # Clase wrapper que делегат methods +│ ├── api-implementation.js # Factory que selecciona implementación +│ ├── auth.js # Manejo de auth (login, tokens JWT) +│ ├── django-api.js # Implementación de API para Django +│ └── http.js # Axios instance con interceptors +├── stores/ # Pinia stores +└── styles/ # SCSS settings ``` ## Important Conventions @@ -51,6 +56,7 @@ import MiComponente from '@/components/MiComponente.vue'; - Ubicación: `src/services/` - Usar Axios para HTTP requests - JWT tokens en localStorage (`access_token`, `refresh_token`) +- La API se inyecta globalmente via `app.provide('api', api)` y se usa con `inject('api')` ### Routing - Rutas automáticas basadas en archivos en `src/pages/` @@ -79,3 +85,30 @@ npm run lint # ESLint fix **Formato de mensajes:** - Usar prefijo `#` para referenciar el issue (ej: `#28 feat: add login` donde #28 es el número del issue en GitHub/GitLab) - Prefijos válidos: `feat`, `fix`, `chore`, `docs`, `refactor`, `style` + +## Análisis del Proyecto + +### Flujo de Autenticación +1. **Login:** `AuthService.login(credentials)` → obtiene JWT tokens → guarda en localStorage +2. **Token:** Se envía en headers via interceptor en `http.js` (`Authorization: Bearer `) +3. **Refresh:** El interceptor renueva automáticamente el token si expira (401) +4. **Logout:** `AuthService.logout()` → limpia localStorage + +### Estructura de API +- `api.js`: Interfaz genérica con métodos como `getCustomers()`, `getProducts()`, etc. +- `api-implementation.js`: Factory que selecciona implementación (actualmente solo Django) +- `django-api.js`: Implementación concreta con endpoints de Django + +### Componentes Principales +- **NavBar.vue**: Barra de navegación con menú de usuario +- **LoginDialog.vue**: Diálogo de inicio de sesión +- **Purchase.vue / AdminPurchase.vue**: Componentes de compra +- **Cart.vue**: Carrito de compras +- **SummaryPurchase.vue**: Resumen de compra + +### Endpoints Django Comunes +- `/api/token/` - Autenticación (login/refresh) +- `/users/me/` - Usuario actual +- `/don_confiao/api/customers/` - Clientes +- `/don_confiao/api/products/` - Productos +- `/don_confiao/api/sales/` - Ventas -- 2.49.1 From 0c31d2121259dba682ed8d955eb425e1c55e5f53 Mon Sep 17 00:00:00 2001 From: mono Date: Sat, 14 Mar 2026 22:24:38 -0500 Subject: [PATCH 2/8] #29 feat: add user profile menu in navbar --- src/components/NavBar.vue | 56 ++++++++++++++++++++++++++++++++------ src/services/api.js | 4 +++ src/services/django-api.js | 5 ++++ 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 0f2f5ef..63169fe 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -13,11 +13,37 @@ - Logout + + + + {{ user?.username }} + {{ user?.email }} + + + + {{ user?.first_name }} {{ user?.last_name }} + + + + {{ user?.is_staff ? 'Administrador' : 'Usuario' }} + + + + + + mdi-logout + Cerrar sesión + + + + + mdi-account + {{ user?.username }} import trytonIcon from '../assets/icons/tryton-icon.svg'; import AuthService from '@/services/auth'; + import { inject } from 'vue'; export default { name: 'NavBar', data: () => ({ @@ -60,6 +87,8 @@ group: null, showAdminMenu: false, isAuthenticated: false, + user: null, + api: inject('api'), menuItems: [ { title: 'Inicio', route: '/', icon: 'mdi-home'}, { title: 'Comprar', route:'/comprar', icon: 'mdi-cart'}, @@ -76,6 +105,9 @@ }), mounted() { this.checkAuth(); + if (this.isAuthenticated) { + this.fetchUser(); + } }, watch: { group () { @@ -89,6 +121,13 @@ checkAuth() { this.isAuthenticated = AuthService.isAuthenticated(); }, + async fetchUser() { + try { + this.user = await this.api.getCurrentUser(); + } catch (error) { + console.error('Error fetching user:', error); + } + }, navigate(route) { this.$router.push(route); }, @@ -99,11 +138,12 @@ toggleAdminMenu() { this.showAdminMenu = !this.showAdminMenu; }, - logout() { - AuthService.logout(); - this.isAuthenticated = false; - this.$router.push('/'); - }, + logout() { + AuthService.logout(); + this.isAuthenticated = false; + this.user = null; + this.$router.push('/'); + }, } } diff --git a/src/services/api.js b/src/services/api.js index 1bc6b51..d683e15 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -62,6 +62,10 @@ class Api { sendSalesToTryton(){ return this.apiImplementation.sendSalesToTryton(); } + + getCurrentUser() { + return this.apiImplementation.getCurrentUser(); + } } export default Api; diff --git a/src/services/django-api.js b/src/services/django-api.js index b302065..5fc4bb3 100644 --- a/src/services/django-api.js +++ b/src/services/django-api.js @@ -88,6 +88,11 @@ class DjangoApi { const url = this.base + '/don_confiao/api/enviar_ventas_a_tryton'; return this.postRequest(url, {}); } + + getCurrentUser() { + const url = this.base + '/users/me/'; + return this.getRequest(url); + } } export default DjangoApi; -- 2.49.1 From c9d019c9181933633f406457d887f45b12f5a49a Mon Sep 17 00:00:00 2001 From: mono Date: Sat, 14 Mar 2026 22:30:10 -0500 Subject: [PATCH 3/8] #29 fix: correct user endpoint to /api/users/me/ --- src/services/django-api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/django-api.js b/src/services/django-api.js index 5fc4bb3..d0536fd 100644 --- a/src/services/django-api.js +++ b/src/services/django-api.js @@ -90,7 +90,7 @@ class DjangoApi { } getCurrentUser() { - const url = this.base + '/users/me/'; + const url = this.base + '/api/users/me/'; return this.getRequest(url); } } -- 2.49.1 From 63bcfa67fe1f67e0ac48f22d4e7782f4e7c829f6 Mon Sep 17 00:00:00 2001 From: mono Date: Sat, 14 Mar 2026 22:30:50 -0500 Subject: [PATCH 4/8] #29 fix: use role field for user badge --- src/components/NavBar.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 63169fe..98c2559 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -27,10 +27,10 @@ - {{ user?.is_staff ? 'Administrador' : 'Usuario' }} + {{ user?.role === 'administrator' ? 'Administrador' : 'Usuario' }} -- 2.49.1 From 373ebb0ae4f221b988001d8ee66d05031106dba3 Mon Sep 17 00:00:00 2001 From: mono Date: Sat, 14 Mar 2026 22:33:21 -0500 Subject: [PATCH 5/8] docs: emphasize commit authorization requirement in AGENTS.md --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 1c43663..e551053 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -79,7 +79,7 @@ npm run lint # ESLint fix ## Git Commits **Antes de hacer commit:** -1. Pedir permiso al usuario +1. **SIEMPRE pedir permiso al usuario antes de hacer commit** 2. Mostrar resumen de los cambios que se incluirán **Formato de mensajes:** -- 2.49.1 From 974c84fdb2c08d3fc914d6b0641fdfefe7e2a106 Mon Sep 17 00:00:00 2001 From: mono Date: Sat, 14 Mar 2026 22:36:57 -0500 Subject: [PATCH 6/8] #29 fix: fetch user data on route change after login --- src/components/NavBar.vue | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 98c2559..94fa7e5 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -109,14 +109,17 @@ this.fetchUser(); } }, - watch: { - group () { - this.drawer = false - }, - $route() { - this.checkAuth(); - }, - }, + watch: { + group () { + this.drawer = false + }, + $route() { + this.checkAuth(); + if (this.isAuthenticated && !this.user) { + this.fetchUser(); + } + }, + }, methods: { checkAuth() { this.isAuthenticated = AuthService.isAuthenticated(); -- 2.49.1 From 2c9ea4b871ddc5b1444cc216219fd6844165bf60 Mon Sep 17 00:00:00 2001 From: mono Date: Sat, 14 Mar 2026 22:41:00 -0500 Subject: [PATCH 7/8] #29 feat: hide admin menu for non-admin users --- src/components/NavBar.vue | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 94fa7e5..a5abadc 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -60,9 +60,9 @@ :prepend-icon="item.icon" @click="navigate(item.route)" > - - - + + + Date: Sat, 14 Mar 2026 22:55:24 -0500 Subject: [PATCH 8/8] #29 refactor: replace admin code with role-based auth using Pinia --- src/components/CodeDialog.vue | 51 ---------------------- src/components/NavBar.vue | 23 ++++++---- src/pages/compra_admin.vue | 19 ++++---- src/pages/cuadrar_tarro.vue | 19 ++++---- src/pages/cuadres_de_tarro.vue | 19 ++++---- src/pages/sincronizar_clientes_tryton.vue | 20 +++++---- src/pages/sincronizar_productos_tryton.vue | 19 +++++--- src/pages/sincronizar_ventas_tryton.vue | 17 +++++--- src/pages/ventas_para_tryton.vue | 19 ++++---- src/services/api.js | 4 -- src/services/django-api.js | 5 --- src/stores/auth.js | 19 ++++++++ 12 files changed, 105 insertions(+), 129 deletions(-) delete mode 100644 src/components/CodeDialog.vue create mode 100644 src/stores/auth.js diff --git a/src/components/CodeDialog.vue b/src/components/CodeDialog.vue deleted file mode 100644 index 5158c11..0000000 --- a/src/components/CodeDialog.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index a5abadc..2ca0199 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -79,9 +79,14 @@ diff --git a/src/pages/cuadrar_tarro.vue b/src/pages/cuadrar_tarro.vue index fb60ff4..9035119 100644 --- a/src/pages/cuadrar_tarro.vue +++ b/src/pages/cuadrar_tarro.vue @@ -1,20 +1,19 @@ diff --git a/src/pages/cuadres_de_tarro.vue b/src/pages/cuadres_de_tarro.vue index 739a1e9..8678601 100644 --- a/src/pages/cuadres_de_tarro.vue +++ b/src/pages/cuadres_de_tarro.vue @@ -1,20 +1,19 @@ diff --git a/src/pages/sincronizar_clientes_tryton.vue b/src/pages/sincronizar_clientes_tryton.vue index 510f814..625c874 100644 --- a/src/pages/sincronizar_clientes_tryton.vue +++ b/src/pages/sincronizar_clientes_tryton.vue @@ -1,8 +1,5 @@ + diff --git a/src/pages/sincronizar_productos_tryton.vue b/src/pages/sincronizar_productos_tryton.vue index adec5f6..fcd74b0 100644 --- a/src/pages/sincronizar_productos_tryton.vue +++ b/src/pages/sincronizar_productos_tryton.vue @@ -1,8 +1,5 @@ + diff --git a/src/pages/sincronizar_ventas_tryton.vue b/src/pages/sincronizar_ventas_tryton.vue index a6359ed..35fc356 100644 --- a/src/pages/sincronizar_ventas_tryton.vue +++ b/src/pages/sincronizar_ventas_tryton.vue @@ -1,8 +1,5 @@ diff --git a/src/services/api.js b/src/services/api.js index d683e15..cd9c455 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -31,10 +31,6 @@ class Api { return this.apiImplementation.getReconciliation(reconciliationId); } - isValidAdminCode(code) { - return this.apiImplementation.isValidAdminCode(code); - } - createPurchase(purchase) { return this.apiImplementation.createPurchase(purchase); } diff --git a/src/services/django-api.js b/src/services/django-api.js index d0536fd..b44c5e3 100644 --- a/src/services/django-api.js +++ b/src/services/django-api.js @@ -49,11 +49,6 @@ class DjangoApi { return this.getRequest(url); } - isValidAdminCode(code) { - const url = this.base + `/don_confiao/api/admin_code/validate/${code}` - return this.getRequest(url) - } - createPurchase(purchase) { const url = this.base + '/don_confiao/api/sales/'; return this.postRequest(url, purchase); diff --git a/src/stores/auth.js b/src/stores/auth.js new file mode 100644 index 0000000..a9b373d --- /dev/null +++ b/src/stores/auth.js @@ -0,0 +1,19 @@ +import { defineStore } from 'pinia' + +export const useAuthStore = defineStore('auth', { + state: () => ({ + user: null + }), + getters: { + isAdmin: (state) => state.user?.role === 'administrator', + isAuthenticated: (state) => !!state.user + }, + actions: { + setUser(user) { + this.user = user + }, + clearUser() { + this.user = null + } + } +}) -- 2.49.1