feat: agregar sincronización de ventas de catálogo a Tryton

- Agregar método sendCatalogSalesToTryton() en django-api.js y api.js
- Crear página sincronizar_catalog_sales_tryton.vue para exportar catalog_sales
- Agregar botón 'Sincronizar a Tryton' en CatalogSalesManagement header
- Reorganizar menú admin en NavBar con sección 'Sincronización Tryton'
- Separar opciones de importación (download) y exportación (upload) a Tryton
- Endpoint: /don_confiao/api/enviar_catalog_sales_a_tryton
- Mostrar resultados exitosos/fallidos similar a sincronización de ventas normales
This commit is contained in:
2026-05-30 20:57:50 -05:00
parent 897cbb3efc
commit 5e86595831
5 changed files with 153 additions and 10 deletions

View File

@@ -0,0 +1,120 @@
<template>
<v-container v-if="authStore.isAdmin" class="fill-height">
<v-row v-if="!result && !loading" justify="center">
<v-col cols="12" md="8">
<v-card class="pa-6" elevation="4">
<v-card-title class="text-h5 font-weight-bold text-center">
🔄 Sincronización de Ventas de Catálogo
</v-card-title>
<v-card-text>
<p>
Esta acción sincronizará las <strong>ventas de catálogo</strong> desde el sistema
<strong>Tryton</strong> hacia la plataforma.
</p>
<v-alert type="warning" dense border="start" border-color="warning" class="mt-4">
<strong>Advertencia:</strong> Este proceso podría tardar varios minutos
y reemplazar datos existentes en la plataforma.
Asegúrese de que la información en Tryton esté actualizada antes de
continuar.
</v-alert>
</v-card-text>
<v-card-actions class="justify-center">
<v-btn color="primary" @click="startSync">
Iniciar Sincronización
</v-btn>
<v-btn text @click="$router.push('/')">
Cancelar
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
<v-row v-else-if="loading" justify="center" align="center">
<v-col cols="12" class="text-center">
<v-progress-circular indeterminate color="primary" size="64"></v-progress-circular>
<p class="mt-4 text-h6">Sincronizando ventas de catálogo...</p>
</v-col>
</v-row>
<v-row v-else>
<v-col cols="12">
<v-alert type="success" variant="tonal" class="mb-4">
<strong>Sincronización completada</strong>
</v-alert>
</v-col>
<v-col cols="12" md="6">
<v-card elevation="2">
<v-card-title class="bg-error text-white"> Fallidos ({{ result.failed?.length || 0 }})</v-card-title>
<v-card-text>
<v-data-table
:items="formatItems(result.failed)"
density="compact"
:headers="[{ title: 'ID', key: 'id' }]"
></v-data-table>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12" md="6">
<v-card elevation="2">
<v-card-title class="bg-success text-white"> Exitosos ({{ result.successful?.length || 0 }})</v-card-title>
<v-card-text>
<v-data-table
:items="formatItems(result.successful)"
density="compact"
:headers="[{ title: 'ID', key: 'id' }]"
></v-data-table>
</v-card-text>
</v-card>
</v-col>
<v-col cols="12" class="text-center mt-4">
<v-btn color="primary" @click="$router.push('/')">
Volver al inicio
</v-btn>
</v-col>
</v-row>
</v-container>
</template>
<script>
import { useAuthStore } from '@/stores/auth';
import { inject } from 'vue';
export default {
name: 'CatalogSalesToTryton',
setup() {
const authStore = useAuthStore();
return { authStore };
},
data() {
return {
api: inject('api'),
loading: false,
result: null,
}
},
methods: {
formatItems(ids) {
if (!ids || ids.length === 0) return [];
return ids.map(id => ({ id }));
},
startSync() {
this.loading = true;
this.api.sendCatalogSalesToTryton()
.then(response => {
this.result = response;
this.loading = false;
})
.catch(error => {
console.error('Error al sincronizar ventas de catálogo:', error);
this.loading = false;
});
}
}
}
</script>