Merge pull request 'Ajustando menú por rol de usuario #29' (#32) from adjust_menu_by_rol_#29 into main
Reviewed-on: #32
This commit is contained in:
49
AGENTS.md
49
AGENTS.md
@@ -13,14 +13,19 @@
|
|||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── assets/ # Imágenes, iconos estáticos
|
├── assets/ # Imágenes, iconos estáticos
|
||||||
├── components/ # Componentes Vue reutilizables
|
├── components/ # Componentes Vue reutilizables
|
||||||
├── layouts/ # Layouts de página
|
├── layouts/ # Layouts de página
|
||||||
├── pages/ # Vistas (auto-routed desde文件名)
|
├── pages/ # Vistas (auto-routed desde文件名)
|
||||||
├── plugins/ # Configuración de Vuetify, etc.
|
├── plugins/ # Configuración de Vuetify, etc.
|
||||||
├── router/ # Configuración de rutas
|
├── router/ # Configuración de rutas
|
||||||
├── services/ # API services (auth.js, etc.)
|
├── services/ # API services (auth.js, etc.)
|
||||||
├── stores/ # Pinia stores
|
│ ├── api.js # Clase wrapper que делегат methods
|
||||||
└── styles/ # SCSS settings
|
│ ├── 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
|
## Important Conventions
|
||||||
@@ -51,6 +56,7 @@ import MiComponente from '@/components/MiComponente.vue';
|
|||||||
- Ubicación: `src/services/`
|
- Ubicación: `src/services/`
|
||||||
- Usar Axios para HTTP requests
|
- Usar Axios para HTTP requests
|
||||||
- JWT tokens en localStorage (`access_token`, `refresh_token`)
|
- 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
|
### Routing
|
||||||
- Rutas automáticas basadas en archivos en `src/pages/`
|
- Rutas automáticas basadas en archivos en `src/pages/`
|
||||||
@@ -73,9 +79,36 @@ npm run lint # ESLint fix
|
|||||||
|
|
||||||
## Git Commits
|
## Git Commits
|
||||||
**Antes de hacer commit:**
|
**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
|
2. Mostrar resumen de los cambios que se incluirán
|
||||||
|
|
||||||
**Formato de mensajes:**
|
**Formato de mensajes:**
|
||||||
- Usar prefijo `#<numero>` para referenciar el issue (ej: `#28 feat: add login` donde #28 es el número del issue en GitHub/GitLab)
|
- Usar prefijo `#<numero>` 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`
|
- 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 <token>`)
|
||||||
|
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
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-dialog v-model="dialog" persistent>
|
|
||||||
<v-card>
|
|
||||||
<v-card-title>
|
|
||||||
Ingrese el código
|
|
||||||
</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<v-form id="code-form" @submit.prevent="verifyCode">
|
|
||||||
<v-text-field v-model="code" label="Código" type="password" autocomplete="off" />
|
|
||||||
</v-form>
|
|
||||||
</v-card-text>
|
|
||||||
<v-card-actions>
|
|
||||||
<v-btn type="submit" form="code-form" color="green">Aceptar</v-btn>
|
|
||||||
<v-btn :to="{ path: '/' }" color="red">Cancelar</v-btn>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { inject } from 'vue';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
api: inject('api'),
|
|
||||||
dialog: true,
|
|
||||||
code: '',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
verifyCode() {
|
|
||||||
this.api.isValidAdminCode(this.code)
|
|
||||||
.then(data => {
|
|
||||||
if (data['validCode']) {
|
|
||||||
this.$emit('code-verified', true);
|
|
||||||
this.dialog = false;
|
|
||||||
} else {
|
|
||||||
alert('Código incorrecto');
|
|
||||||
this.$emit('code-verified', false);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
alert('Error al validar el código');
|
|
||||||
this.$emit('code-verified', false);
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -13,11 +13,37 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
v-else
|
v-else
|
||||||
prepend-icon="mdi-logout"
|
|
||||||
variant="text"
|
variant="text"
|
||||||
@click="logout"
|
|
||||||
>
|
>
|
||||||
Logout
|
<v-menu activator="parent">
|
||||||
|
<v-list>
|
||||||
|
<v-list-item>
|
||||||
|
<v-list-item-title class="font-weight-bold">{{ user?.username }}</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>{{ user?.email }}</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
|
<v-divider></v-divider>
|
||||||
|
<v-list-item v-if="user?.first_name || user?.last_name">
|
||||||
|
<v-list-item-title>{{ user?.first_name }} {{ user?.last_name }}</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item>
|
||||||
|
<v-chip
|
||||||
|
:color="user?.role === 'administrator' ? 'error' : 'primary'"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{{ user?.role === 'administrator' ? 'Administrador' : 'Usuario' }}
|
||||||
|
</v-chip>
|
||||||
|
</v-list-item>
|
||||||
|
<v-divider></v-divider>
|
||||||
|
<v-list-item @click="logout">
|
||||||
|
<v-list-item-title>
|
||||||
|
<v-icon start>mdi-logout</v-icon>
|
||||||
|
Cerrar sesión
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
|
<v-icon start>mdi-account</v-icon>
|
||||||
|
{{ user?.username }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
<v-navigation-drawer v-model="drawer"
|
<v-navigation-drawer v-model="drawer"
|
||||||
@@ -34,9 +60,9 @@
|
|||||||
:prepend-icon="item.icon"
|
:prepend-icon="item.icon"
|
||||||
@click="navigate(item.route)"
|
@click="navigate(item.route)"
|
||||||
></v-list-item>
|
></v-list-item>
|
||||||
<v-list-item prepend-icon="mdi-cog" title="Administracion" @click="toggleAdminMenu()"></v-list-item>
|
<v-list-item prepend-icon="mdi-cog" title="Administracion" @click="toggleAdminMenu()" v-if="isAuthenticated && isAdmin"></v-list-item>
|
||||||
<v-list-item>
|
<v-list-item v-if="isAuthenticated && isAdmin && showAdminMenu">
|
||||||
<v-list v-if="showAdminMenu">
|
<v-list>
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="item in menuAdminItems"
|
v-for="item in menuAdminItems"
|
||||||
:key="item.title"
|
:key="item.title"
|
||||||
@@ -53,13 +79,21 @@
|
|||||||
<script>
|
<script>
|
||||||
import trytonIcon from '../assets/icons/tryton-icon.svg';
|
import trytonIcon from '../assets/icons/tryton-icon.svg';
|
||||||
import AuthService from '@/services/auth';
|
import AuthService from '@/services/auth';
|
||||||
|
import { useAuthStore } from '@/stores/auth';
|
||||||
|
import { inject } from 'vue';
|
||||||
export default {
|
export default {
|
||||||
name: 'NavBar',
|
name: 'NavBar',
|
||||||
|
setup() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
return { authStore };
|
||||||
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
drawer: false,
|
drawer: false,
|
||||||
group: null,
|
group: null,
|
||||||
showAdminMenu: false,
|
showAdminMenu: false,
|
||||||
isAuthenticated: false,
|
isAuthenticated: false,
|
||||||
|
user: null,
|
||||||
|
api: inject('api'),
|
||||||
menuItems: [
|
menuItems: [
|
||||||
{ title: 'Inicio', route: '/', icon: 'mdi-home'},
|
{ title: 'Inicio', route: '/', icon: 'mdi-home'},
|
||||||
{ title: 'Comprar', route:'/comprar', icon: 'mdi-cart'},
|
{ title: 'Comprar', route:'/comprar', icon: 'mdi-cart'},
|
||||||
@@ -73,22 +107,41 @@
|
|||||||
{ title: 'Actualizar Clientes De Tryton', route: '/sincronizar_clientes_tryton', icon: 'trytonIcon'},
|
{ title: 'Actualizar Clientes De Tryton', route: '/sincronizar_clientes_tryton', icon: 'trytonIcon'},
|
||||||
{ title: 'Actualizar Ventas Tryton', route: '/sincronizar_ventas_tryton', icon: 'trytonIcon'}
|
{ title: 'Actualizar Ventas Tryton', route: '/sincronizar_ventas_tryton', icon: 'trytonIcon'}
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
mounted() {
|
computed: {
|
||||||
|
isAdmin() {
|
||||||
|
return this.user?.role === 'administrator';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
this.checkAuth();
|
this.checkAuth();
|
||||||
|
if (this.isAuthenticated) {
|
||||||
|
this.fetchUser();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
group () {
|
group () {
|
||||||
this.drawer = false
|
this.drawer = false
|
||||||
},
|
},
|
||||||
$route() {
|
$route() {
|
||||||
this.checkAuth();
|
this.checkAuth();
|
||||||
},
|
if (this.isAuthenticated && !this.user) {
|
||||||
},
|
this.fetchUser();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkAuth() {
|
checkAuth() {
|
||||||
this.isAuthenticated = AuthService.isAuthenticated();
|
this.isAuthenticated = AuthService.isAuthenticated();
|
||||||
},
|
},
|
||||||
|
async fetchUser() {
|
||||||
|
try {
|
||||||
|
this.user = await this.api.getCurrentUser();
|
||||||
|
this.authStore.setUser(this.user);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching user:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
navigate(route) {
|
navigate(route) {
|
||||||
this.$router.push(route);
|
this.$router.push(route);
|
||||||
},
|
},
|
||||||
@@ -100,10 +153,12 @@
|
|||||||
this.showAdminMenu = !this.showAdminMenu;
|
this.showAdminMenu = !this.showAdminMenu;
|
||||||
},
|
},
|
||||||
logout() {
|
logout() {
|
||||||
AuthService.logout();
|
AuthService.logout();
|
||||||
this.isAuthenticated = false;
|
this.isAuthenticated = false;
|
||||||
this.$router.push('/');
|
this.user = null;
|
||||||
},
|
this.authStore.clearUser();
|
||||||
|
this.$router.push('/');
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<AdminPurchase v-if="authStore.isAdmin"/>
|
||||||
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
|
|
||||||
</div>
|
|
||||||
<AdminPurchase v-if="showComponent"/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script >
|
<script >
|
||||||
import CodeDialog from '../components/CodeDialog.vue'
|
import { useAuthStore } from '@/stores/auth';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
setup() {
|
||||||
return {
|
const authStore = useAuthStore();
|
||||||
showComponent: false,
|
return { authStore };
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.authStore.isAdmin) {
|
||||||
|
this.$router.push('/');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: { CodeDialog },
|
|
||||||
methods: {},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<ReconciliationJar v-if="authStore.isAdmin" />
|
||||||
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
|
|
||||||
</div>
|
|
||||||
<ReconciliationJar v-if="showComponent" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script >
|
<script >
|
||||||
import CodeDialog from '../components/CodeDialog.vue'
|
import { useAuthStore } from '@/stores/auth';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
setup() {
|
||||||
return {
|
const authStore = useAuthStore();
|
||||||
showComponent: false,
|
return { authStore };
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.authStore.isAdmin) {
|
||||||
|
this.$router.push('/');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: { CodeDialog },
|
|
||||||
methods: {},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<ReconciliationJarIndex v-if="authStore.isAdmin" />
|
||||||
<CodeDialog @code-verified="(verified) => showComponent = verified" />
|
|
||||||
</div>
|
|
||||||
<ReconciliationJarIndex v-if="showComponent" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CodeDialog from '../components/CodeDialog.vue'
|
import { useAuthStore } from '@/stores/auth';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
setup() {
|
||||||
return {
|
const authStore = useAuthStore();
|
||||||
showComponent: false,
|
return { authStore };
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.authStore.isAdmin) {
|
||||||
|
this.$router.push('/');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: { CodeDialog },
|
|
||||||
methods: {},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<v-container v-if="authStore.isAdmin" class="fill-height d-flex align-center justify-center">
|
||||||
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
|
|
||||||
</div>
|
|
||||||
<v-container class="fill-height d-flex align-center justify-center">
|
|
||||||
<v-card class="pa-6" max-width="600" elevation="4">
|
<v-card class="pa-6" max-width="600" elevation="4">
|
||||||
<v-card-title class="text-h5 font-weight-bold text-center">
|
<v-card-title class="text-h5 font-weight-bold text-center">
|
||||||
🔄 Sincronización de Clientes
|
🔄 Sincronización de Clientes
|
||||||
@@ -44,11 +41,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CodeDialog from '../components/CodeDialog.vue'
|
import { useAuthStore } from '@/stores/auth';
|
||||||
import { inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CustomersFromTryton',
|
name: 'CustomersFromTryton',
|
||||||
|
setup() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
return { authStore };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
api: inject('api'),
|
api: inject('api'),
|
||||||
@@ -59,21 +60,24 @@
|
|||||||
updated_customers: [],
|
updated_customers: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.authStore.isAdmin) {
|
||||||
|
this.$router.push('/');
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startSync() {
|
startSync() {
|
||||||
this.api.getCustomersFromTryton()
|
this.api.getCustomersFromTryton()
|
||||||
.then(response => {
|
.then(response => {
|
||||||
// Manejar la respuesta exitosa
|
|
||||||
this.checked_tryton_parties = response.checked_tryton_parties.map(id => ({ id }));
|
this.checked_tryton_parties = response.checked_tryton_parties.map(id => ({ id }));
|
||||||
this.created_customers = response.created_customers.map(id => ({ id }));
|
this.created_customers = response.created_customers.map(id => ({ id }));
|
||||||
this.failed_parties = response.failed_parties.map(id => ({ id }));
|
this.failed_parties = response.failed_parties.map(id => ({ id }));
|
||||||
this.untouched_customers = response.untouched_customers.map(id => ({ id }));
|
this.untouched_customers = response.untouched_customers.map(id => ({ id }));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
// Manejar el error
|
|
||||||
console.error("Error al sincronizar clientes:", error);
|
console.error("Error al sincronizar clientes:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<v-container v-if="authStore.isAdmin" class="fill-height d-flex align-center justify-center">
|
||||||
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
|
|
||||||
</div>
|
|
||||||
<v-container class="fill-height d-flex align-center justify-center">
|
|
||||||
<v-card class="pa-6" max-width="600" elevation="4">
|
<v-card class="pa-6" max-width="600" elevation="4">
|
||||||
<v-card-title class="text-h5 font-weight-bold text-center">
|
<v-card-title class="text-h5 font-weight-bold text-center">
|
||||||
🔄 Sincronización de Productos
|
🔄 Sincronización de Productos
|
||||||
@@ -39,16 +36,24 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CodeDialog from '../components/CodeDialog.vue'
|
import { useAuthStore } from '@/stores/auth';
|
||||||
import { inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ProductsFromTryton',
|
name: 'ProductsFromTryton',
|
||||||
|
setup() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
return { authStore };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
api: inject('api'),
|
api: inject('api'),
|
||||||
productos_tryton: [{}],
|
productos_tryton: [{}],
|
||||||
showComponent: false,
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.authStore.isAdmin) {
|
||||||
|
this.$router.push('/');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -57,4 +62,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<v-container v-if="authStore.isAdmin" class="fill-height d-flex align-center justify-center">
|
||||||
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
|
|
||||||
</div>
|
|
||||||
<v-container class="fill-height d-flex align-center justify-center">
|
|
||||||
<v-card class="pa-6" max-width="600" elevation="4">
|
<v-card class="pa-6" max-width="600" elevation="4">
|
||||||
<v-card-title class="text-h5 font-weight-bold text-center">
|
<v-card-title class="text-h5 font-weight-bold text-center">
|
||||||
🔄 Sincronización de Ventas
|
🔄 Sincronización de Ventas
|
||||||
@@ -35,16 +32,24 @@
|
|||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import CodeDialog from '../components/CodeDialog.vue';
|
import { useAuthStore } from '@/stores/auth';
|
||||||
import { inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SalesToTryton',
|
name: 'SalesToTryton',
|
||||||
|
setup() {
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
return { authStore };
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
api: inject('api'),
|
api: inject('api'),
|
||||||
ventas_tryton: [],
|
ventas_tryton: [],
|
||||||
showComponent: false,
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.authStore.isAdmin) {
|
||||||
|
this.$router.push('/');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<ExportPurchasesForTryton v-if="authStore.isAdmin" />
|
||||||
<CodeDialog @code-verified="(verified) => showComponent = verified"/>
|
|
||||||
</div>
|
|
||||||
<ExportPurchasesForTryton v-if="showComponent" />
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import CodeDialog from '../components/CodeDialog.vue'
|
import { useAuthStore } from '@/stores/auth';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
setup() {
|
||||||
return {
|
const authStore = useAuthStore();
|
||||||
showComponent: false,
|
return { authStore };
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.authStore.isAdmin) {
|
||||||
|
this.$router.push('/');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: { CodeDialog },
|
|
||||||
methods: {},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ class Api {
|
|||||||
return this.apiImplementation.getReconciliation(reconciliationId);
|
return this.apiImplementation.getReconciliation(reconciliationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidAdminCode(code) {
|
|
||||||
return this.apiImplementation.isValidAdminCode(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
createPurchase(purchase) {
|
createPurchase(purchase) {
|
||||||
return this.apiImplementation.createPurchase(purchase);
|
return this.apiImplementation.createPurchase(purchase);
|
||||||
}
|
}
|
||||||
@@ -62,6 +58,10 @@ class Api {
|
|||||||
sendSalesToTryton(){
|
sendSalesToTryton(){
|
||||||
return this.apiImplementation.sendSalesToTryton();
|
return this.apiImplementation.sendSalesToTryton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrentUser() {
|
||||||
|
return this.apiImplementation.getCurrentUser();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Api;
|
export default Api;
|
||||||
|
|||||||
@@ -49,11 +49,6 @@ class DjangoApi {
|
|||||||
return this.getRequest(url);
|
return this.getRequest(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidAdminCode(code) {
|
|
||||||
const url = this.base + `/don_confiao/api/admin_code/validate/${code}`
|
|
||||||
return this.getRequest(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
createPurchase(purchase) {
|
createPurchase(purchase) {
|
||||||
const url = this.base + '/don_confiao/api/sales/';
|
const url = this.base + '/don_confiao/api/sales/';
|
||||||
return this.postRequest(url, purchase);
|
return this.postRequest(url, purchase);
|
||||||
@@ -88,6 +83,11 @@ class DjangoApi {
|
|||||||
const url = this.base + '/don_confiao/api/enviar_ventas_a_tryton';
|
const url = this.base + '/don_confiao/api/enviar_ventas_a_tryton';
|
||||||
return this.postRequest(url, {});
|
return this.postRequest(url, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrentUser() {
|
||||||
|
const url = this.base + '/api/users/me/';
|
||||||
|
return this.getRequest(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DjangoApi;
|
export default DjangoApi;
|
||||||
|
|||||||
19
src/stores/auth.js
Normal file
19
src/stores/auth.js
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user