From 314df4ffc1a4479b65f82923c929c9296d08dd1a Mon Sep 17 00:00:00 2001 From: "Kevin A. Rosales Marquez" Date: Fri, 12 Dec 2025 17:23:58 -0600 Subject: [PATCH] Modulo/Creacion de endpoint para las tablas de facturas, asi como sus creaciones --- backend/api/v1/modules/a76/invoices/routes.py | 1 + .../invoices/data-table-actions.svelte | 15 +- .../src/lib/components/sidebar/modules.ts | 18 +- .../exportacion}/+page.server.ts | 6 +- .../exportacion}/+page.svelte | 0 .../exportacion/reparacion/+page.server.ts | 114 +++++ .../exportacion/reparacion/+page.svelte | 382 +++++++++++++++++ .../cambio_regimen/+page.server.ts | 114 +++++ .../importacion/cambio_regimen/+page.svelte | 382 +++++++++++++++++ .../cambio_regimen/new/+page.svelte | 320 ++++++++++++++ .../compras_mexicanas/+page.server.ts | 114 +++++ .../compras_mexicanas/+page.svelte | 382 +++++++++++++++++ .../compras_mexicanas/new/+page.svelte | 320 ++++++++++++++ .../importacion/definitiva/+page.server.ts | 114 +++++ .../importacion/definitiva/+page.svelte | 390 ++++++++++++++++++ .../importacion/definitiva/new/+page.svelte | 320 ++++++++++++++ .../importacion/temporal/+page.server.ts | 114 +++++ .../importacion/temporal/+page.svelte | 382 +++++++++++++++++ .../importacion/temporal/new/+page.svelte | 320 ++++++++++++++ 19 files changed, 3794 insertions(+), 14 deletions(-) rename frontend/src/routes/dashboard/invoices/{ => exportacion/exportacion}/+page.server.ts (94%) rename frontend/src/routes/dashboard/invoices/{ => exportacion/exportacion}/+page.svelte (100%) create mode 100644 frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.server.ts create mode 100644 frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.server.ts create mode 100644 frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/new/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.server.ts create mode 100644 frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/new/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.server.ts create mode 100644 frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/definitiva/new/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/temporal/+page.server.ts create mode 100644 frontend/src/routes/dashboard/invoices/importacion/temporal/+page.svelte create mode 100644 frontend/src/routes/dashboard/invoices/importacion/temporal/new/+page.svelte diff --git a/backend/api/v1/modules/a76/invoices/routes.py b/backend/api/v1/modules/a76/invoices/routes.py index a2160a6b..e81706a1 100644 --- a/backend/api/v1/modules/a76/invoices/routes.py +++ b/backend/api/v1/modules/a76/invoices/routes.py @@ -150,6 +150,7 @@ def get_invoice_details( status_code=201, summary="Add sales detail to an invoice", ) + def create_invoice_detail( invoice_id: int = Path(..., description="Invoice ID"), detail_data: schemas.InvoiceSalesDetailsCreate = ..., diff --git a/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte b/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte index 13367343..4b5f2e65 100644 --- a/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte +++ b/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte @@ -3,6 +3,7 @@ import { Button } from '$lib/components/ui/button'; import * as DropdownMenu from '$lib/components/ui/dropdown-menu'; import { Ellipsis, Eye, Pencil, Trash2 } from 'lucide-svelte'; + import { goto } from '$app/navigation'; interface Props { invoice: Invoice; @@ -14,13 +15,14 @@ window.dispatchEvent(new CustomEvent('invoiceView', { detail: invoice })); } - function dispatchEdit() { - window.dispatchEvent(new CustomEvent('invoiceEdit', { detail: invoice })); - } - function dispatchDelete() { window.dispatchEvent(new CustomEvent('invoiceDelete', { detail: invoice })); } + + function dispatchEdit() { + window.dispatchEvent(new CustomEvent('invoiceEdit', { detail: invoice })); + } + @@ -35,18 +37,21 @@ Acciones + Ver Detalles + Editar + Eliminar - + \ No newline at end of file diff --git a/frontend/src/lib/components/sidebar/modules.ts b/frontend/src/lib/components/sidebar/modules.ts index cbc38c14..328f53dc 100644 --- a/frontend/src/lib/components/sidebar/modules.ts +++ b/frontend/src/lib/components/sidebar/modules.ts @@ -323,19 +323,23 @@ export function getSidebarData(): SidebarData { items: [ { title: m["sidebar.import_invoices.temporary"](), - url: "/dashboard/invoices?operation_type=imp&invoice_type=TEM", + //url: "/dashboard/invoices?operation_type=imp&invoice_type=TEM" + url: "/dashboard/invoices/importacion/temporal", }, { title: m["sidebar.import_invoices.definitive"](), - url: "/dashboard/invoices?operation_type=imp&invoice_type=DEF", + //url: "/dashboard/invoices?operation_type=imp&invoice_type=DEF", + url: "/dashboard/invoices/importacion/definitiva", }, { title: m["sidebar.import_invoices.mexican_purchases"](), - url: "/dashboard/invoices?operation_type=imp&invoice_type=MEX", + //url: "/dashboard/invoices?operation_type=imp&invoice_type=MEX", + url: "/dashboard/invoices/importacion/compras_mexicanas", }, { title: m["sidebar.import_invoices.regime_change"](), - url: "/dashboard/invoices?operation_type=imp&invoice_type=CR", + //url: "/dashboard/invoices?operation_type=imp&invoice_type=CR", + url: "/dashboard/invoices/importacion/cambio_regimen", } ], }, @@ -346,11 +350,13 @@ export function getSidebarData(): SidebarData { items: [ { title: m["sidebar.export_invoices.exportation"](), - url: "/dashboard/invoices?operation_type=exp", + //url: "/dashboard/invoices?operation_type=exp", + url: "/dashboard/invoices/exportacion/exportacion", }, { title: m["sidebar.export_invoices.repair"](), - url: "/dashboard/invoices?operation_type=exp&invoice_type=REPAR", + //url: "/dashboard/invoices?operation_type=exp&invoice_type=REPAR", + url: "/dashboard/invoices/exportacion/reparacion", }, ], }, diff --git a/frontend/src/routes/dashboard/invoices/+page.server.ts b/frontend/src/routes/dashboard/invoices/exportacion/exportacion/+page.server.ts similarity index 94% rename from frontend/src/routes/dashboard/invoices/+page.server.ts rename to frontend/src/routes/dashboard/invoices/exportacion/exportacion/+page.server.ts index 4e3b8795..54f3eb0b 100644 --- a/frontend/src/routes/dashboard/invoices/+page.server.ts +++ b/frontend/src/routes/dashboard/invoices/exportacion/exportacion/+page.server.ts @@ -1,4 +1,4 @@ -import type { PageServerLoad } from './$types'; +import type { PageServerLoad } from '../$types'; import { redirect } from '@sveltejs/kit'; import { getAuthTokens, @@ -43,8 +43,8 @@ export const load: PageServerLoad = async ({ fetch, cookies, url, parent }) => { } // Obtener filtro de tipo de operación - const operationType = url.searchParams.get('operation_type'); - const invoiceType = url.searchParams.get('invoice_type'); + const operationType = 'exp' + const invoiceType = 'exp' // Construir parámetros de consulta const params = new URLSearchParams({ diff --git a/frontend/src/routes/dashboard/invoices/+page.svelte b/frontend/src/routes/dashboard/invoices/exportacion/exportacion/+page.svelte similarity index 100% rename from frontend/src/routes/dashboard/invoices/+page.svelte rename to frontend/src/routes/dashboard/invoices/exportacion/exportacion/+page.svelte diff --git a/frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.server.ts b/frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.server.ts new file mode 100644 index 00000000..4feb09c2 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.server.ts @@ -0,0 +1,114 @@ +import type { PageServerLoad } from '../$types'; +import { redirect } from '@sveltejs/kit'; +import { + getAuthTokens, + authenticatedFetch +} from '$lib/server/api'; + +export const load: PageServerLoad = async ({ fetch, cookies, url, parent }) => { + // Esperar a que el layout padre valide/refresque el token + const parentData = await parent(); + + // Verificar autenticación + const { accessToken } = getAuthTokens(cookies); + + if (!accessToken) { + throw redirect(302, '/login'); + } + + try { + // Obtener company_id de múltiples fuentes (en orden de prioridad): + // 1. URL query param (permite cambiar vía navegación) + // 2. Cookie active_company_id (setted por el team-switcher) + // 3. Primera compañía del usuario (fallback) + const companyIdParam = url.searchParams.get('company_id'); + const cookieCompanyId = cookies.get('active_company_id'); + + const companyId = companyIdParam + ? parseInt(companyIdParam) + : cookieCompanyId + ? parseInt(cookieCompanyId) + : parentData.companies?.[0]?.id; + + // Si aún no hay companyId, mostrar error + if (!companyId) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'No se encontró una compañía seleccionada', + companies: parentData.companies || [] + }; + } + + // Obtener filtro de tipo de operación + const operationType = 'exp' + const invoiceType = 'REPAR' + + // Construir parámetros de consulta + const params = new URLSearchParams({ + company_id: companyId.toString(), + page: '1', + page_size: '50' + }); + + // Agregar filtro de tipo si existe y no es 'all' + if (operationType && operationType !== 'all') { + params.append('operation_type', operationType); + } + + // Agregar filtro de invoice_type si existe + if (invoiceType) { + params.append('invoice_type', invoiceType); + } + + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/a76/invoices?${params.toString()}`, + {}, + cookies, + fetch, + '/login' + ); + + if (!response.ok) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } + + const data = await response.json(); + + return { + items: data.items || [], + total: data.total || 0, + page: data.page || 1, + page_size: data.page_size || 50, + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } catch (error) { + console.error('Error loading invoices:', error); + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + operationType: 'all', + invoiceType: null + }; + } +}; diff --git a/frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.svelte b/frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.svelte new file mode 100644 index 00000000..0a837d10 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/exportacion/reparacion/+page.svelte @@ -0,0 +1,382 @@ + + +
+ +
+
+

Facturas

+

+ Gestiona las facturas de importación y exportación +

+
+ +
+ + + {#if error} + + + Error + {error} + + + {/if} + + + + +
+
+ Listado de Facturas + + Mostrando {allItems.length} de {totalItems} registros + {#if companyStore.activeCompany} + - Compañía: {companyStore.activeCompany.name} + {/if} + +
+
+ + + {selectedType === 'all' ? 'Todas' : selectedType === 'imp' ? 'Importación' : 'Exportación'} + + + Todas + Importación + Exportación + + + + {#if selectedType !== 'all' && availableInvoiceTypes.length > 0} + + + + {#if loadingInvoiceTypes} + Cargando... + {:else if selectedInvoiceType} + {(() => { + const found = availableInvoiceTypes.find(t => t.key === selectedInvoiceType); + return found ? `${found.key} - ${found.description}` : selectedInvoiceType; + })()} + {:else} + Todos los tipos + {/if} + + + + Todos los tipos + {#each availableInvoiceTypes as invType} + + + {invType.key} - {invType.description} + + + {/each} + + + {/if} + + +
+
+
+ + + +
+
+ + + + + + + diff --git a/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.server.ts b/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.server.ts new file mode 100644 index 00000000..fb3159d9 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.server.ts @@ -0,0 +1,114 @@ +import type { PageServerLoad } from '../../$types'; +import { redirect } from '@sveltejs/kit'; +import { + getAuthTokens, + authenticatedFetch +} from '$lib/server/api'; + +export const load: PageServerLoad = async ({ fetch, cookies, url, parent }) => { + // Esperar a que el layout padre valide/refresque el token + const parentData = await parent(); + + // Verificar autenticación + const { accessToken } = getAuthTokens(cookies); + + if (!accessToken) { + throw redirect(302, '/login'); + } + + try { + // Obtener company_id de múltiples fuentes (en orden de prioridad): + // 1. URL query param (permite cambiar vía navegación) + // 2. Cookie active_company_id (setted por el team-switcher) + // 3. Primera compañía del usuario (fallback) + const companyIdParam = url.searchParams.get('company_id'); + const cookieCompanyId = cookies.get('active_company_id'); + + const companyId = companyIdParam + ? parseInt(companyIdParam) + : cookieCompanyId + ? parseInt(cookieCompanyId) + : parentData.companies?.[0]?.id; + + // Si aún no hay companyId, mostrar error + if (!companyId) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'No se encontró una compañía seleccionada', + companies: parentData.companies || [] + }; + } + + // Obtener filtro de tipo de operación + const operationType = 'imp' + const invoiceType = 'CR' + + // Construir parámetros de consulta + const params = new URLSearchParams({ + company_id: companyId.toString(), + page: '1', + page_size: '50' + }); + + // Agregar filtro de tipo si existe y no es 'all' + if (operationType && operationType !== 'all') { + params.append('operation_type', operationType); + } + + // Agregar filtro de invoice_type si existe + if (invoiceType) { + params.append('invoice_type', invoiceType); + } + + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/a76/invoices?${params.toString()}`, + {}, + cookies, + fetch, + '/login' + ); + + if (!response.ok) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } + + const data = await response.json(); + + return { + items: data.items || [], + total: data.total || 0, + page: data.page || 1, + page_size: data.page_size || 50, + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } catch (error) { + console.error('Error loading invoices:', error); + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + operationType: 'all', + invoiceType: null + }; + } +}; diff --git a/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.svelte new file mode 100644 index 00000000..c0d0b0cf --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/+page.svelte @@ -0,0 +1,382 @@ + + +
+ +
+
+

Facturas

+

+ Gestiona las facturas de importación y exportación +

+
+ +
+ + + {#if error} + + + Error + {error} + + + {/if} + + + + +
+
+ Listado de Facturas + + Mostrando {allItems.length} de {totalItems} registros + {#if companyStore.activeCompany} + - Compañía: {companyStore.activeCompany.name} + {/if} + +
+
+ + + {selectedType === 'all' ? 'Todas' : selectedType === 'imp' ? 'Importación' : 'Exportación'} + + + Todas + Importación + Exportación + + + + {#if selectedType !== 'all' && availableInvoiceTypes.length > 0} + + + + {#if loadingInvoiceTypes} + Cargando... + {:else if selectedInvoiceType} + {(() => { + const found = availableInvoiceTypes.find(t => t.key === selectedInvoiceType); + return found ? `${found.key} - ${found.description}` : selectedInvoiceType; + })()} + {:else} + Todos los tipos + {/if} + + + + Todos los tipos + {#each availableInvoiceTypes as invType} + + + {invType.key} - {invType.description} + + + {/each} + + + {/if} + + +
+
+
+ + + +
+
+ + + + + + + diff --git a/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/new/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/new/+page.svelte new file mode 100644 index 00000000..76f88411 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/cambio_regimen/new/+page.svelte @@ -0,0 +1,320 @@ + + +
+ +
+ +
+

Nueva Factura Cambio Regimen

+

Ingresa los datos para registrar la importación.

+
+
+ + {#if error} +
+ ⚠️ {error} +
+ {/if} + +
+ + + + + + General + Cumplimiento + Financieros + + + +
+ +
+ +
Importación
+
+ +
+ +
CAMBIO REGIMEN (CR)
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ +
+ + + + + +
+
+
\ No newline at end of file diff --git a/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.server.ts b/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.server.ts new file mode 100644 index 00000000..a8794bcf --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.server.ts @@ -0,0 +1,114 @@ +import type { PageServerLoad } from '../../$types'; +import { redirect } from '@sveltejs/kit'; +import { + getAuthTokens, + authenticatedFetch +} from '$lib/server/api'; + +export const load: PageServerLoad = async ({ fetch, cookies, url, parent }) => { + // Esperar a que el layout padre valide/refresque el token + const parentData = await parent(); + + // Verificar autenticación + const { accessToken } = getAuthTokens(cookies); + + if (!accessToken) { + throw redirect(302, '/login'); + } + + try { + // Obtener company_id de múltiples fuentes (en orden de prioridad): + // 1. URL query param (permite cambiar vía navegación) + // 2. Cookie active_company_id (setted por el team-switcher) + // 3. Primera compañía del usuario (fallback) + const companyIdParam = url.searchParams.get('company_id'); + const cookieCompanyId = cookies.get('active_company_id'); + + const companyId = companyIdParam + ? parseInt(companyIdParam) + : cookieCompanyId + ? parseInt(cookieCompanyId) + : parentData.companies?.[0]?.id; + + // Si aún no hay companyId, mostrar error + if (!companyId) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'No se encontró una compañía seleccionada', + companies: parentData.companies || [] + }; + } + + // Obtener filtro de tipo de operación + const operationType = 'imp' + const invoiceType = 'MEX' + + // Construir parámetros de consulta + const params = new URLSearchParams({ + company_id: companyId.toString(), + page: '1', + page_size: '50' + }); + + // Agregar filtro de tipo si existe y no es 'all' + if (operationType && operationType !== 'all') { + params.append('operation_type', operationType); + } + + // Agregar filtro de invoice_type si existe + if (invoiceType) { + params.append('invoice_type', invoiceType); + } + + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/a76/invoices?${params.toString()}`, + {}, + cookies, + fetch, + '/login' + ); + + if (!response.ok) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } + + const data = await response.json(); + + return { + items: data.items || [], + total: data.total || 0, + page: data.page || 1, + page_size: data.page_size || 50, + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } catch (error) { + console.error('Error loading invoices:', error); + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + operationType: 'all', + invoiceType: null + }; + } +}; diff --git a/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.svelte new file mode 100644 index 00000000..87cdb207 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/+page.svelte @@ -0,0 +1,382 @@ + + +
+ +
+
+

Facturas

+

+ Gestiona las facturas de importación y exportación +

+
+ +
+ + + {#if error} + + + Error + {error} + + + {/if} + + + + +
+
+ Listado de Facturas + + Mostrando {allItems.length} de {totalItems} registros + {#if companyStore.activeCompany} + - Compañía: {companyStore.activeCompany.name} + {/if} + +
+
+ + + {selectedType === 'all' ? 'Todas' : selectedType === 'imp' ? 'Importación' : 'Exportación'} + + + Todas + Importación + Exportación + + + + {#if selectedType !== 'all' && availableInvoiceTypes.length > 0} + + + + {#if loadingInvoiceTypes} + Cargando... + {:else if selectedInvoiceType} + {(() => { + const found = availableInvoiceTypes.find(t => t.key === selectedInvoiceType); + return found ? `${found.key} - ${found.description}` : selectedInvoiceType; + })()} + {:else} + Todos los tipos + {/if} + + + + Todos los tipos + {#each availableInvoiceTypes as invType} + + + {invType.key} - {invType.description} + + + {/each} + + + {/if} + + +
+
+
+ + + +
+
+ + + + + + + diff --git a/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/new/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/new/+page.svelte new file mode 100644 index 00000000..488312d0 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/compras_mexicanas/new/+page.svelte @@ -0,0 +1,320 @@ + + +
+ +
+ +
+

Nueva Factura

+

Ingresa los datos para registrar la importación.

+
+
+ + {#if error} +
+ ⚠️ {error} +
+ {/if} + +
+ + + + + + General + Cumplimiento + Financieros + + + +
+ +
+ +
Importación
+
+ +
+ +
COMPRAS MEXICANAS (MEX)
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ +
+ + + + + +
+
+
\ No newline at end of file diff --git a/frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.server.ts b/frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.server.ts new file mode 100644 index 00000000..d00d94fe --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.server.ts @@ -0,0 +1,114 @@ +import type { PageServerLoad } from '../../$types'; +import { redirect } from '@sveltejs/kit'; +import { + getAuthTokens, + authenticatedFetch +} from '$lib/server/api'; + +export const load: PageServerLoad = async ({ fetch, cookies, url, parent }) => { + // Esperar a que el layout padre valide/refresque el token + const parentData = await parent(); + + // Verificar autenticación + const { accessToken } = getAuthTokens(cookies); + + if (!accessToken) { + throw redirect(302, '/login'); + } + + try { + // Obtener company_id de múltiples fuentes (en orden de prioridad): + // 1. URL query param (permite cambiar vía navegación) + // 2. Cookie active_company_id (setted por el team-switcher) + // 3. Primera compañía del usuario (fallback) + const companyIdParam = url.searchParams.get('company_id'); + const cookieCompanyId = cookies.get('active_company_id'); + + const companyId = companyIdParam + ? parseInt(companyIdParam) + : cookieCompanyId + ? parseInt(cookieCompanyId) + : parentData.companies?.[0]?.id; + + // Si aún no hay companyId, mostrar error + if (!companyId) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'No se encontró una compañía seleccionada', + companies: parentData.companies || [] + }; + } + + // Obtener filtro de tipo de operación + const operationType = 'imp' + const invoiceType = 'DEF' + + // Construir parámetros de consulta + const params = new URLSearchParams({ + company_id: companyId.toString(), + page: '1', + page_size: '50' + }); + + // Agregar filtro de tipo si existe y no es 'all' + if (operationType && operationType !== 'all') { + params.append('operation_type', operationType); + } + + // Agregar filtro de invoice_type si existe + if (invoiceType) { + params.append('invoice_type', invoiceType); + } + + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/a76/invoices?${params.toString()}`, + {}, + cookies, + fetch, + '/login' + ); + + if (!response.ok) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } + + const data = await response.json(); + + return { + items: data.items || [], + total: data.total || 0, + page: data.page || 1, + page_size: data.page_size || 50, + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } catch (error) { + console.error('Error loading invoices:', error); + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + operationType: 'all', + invoiceType: null + }; + } +}; diff --git a/frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.svelte new file mode 100644 index 00000000..17f52848 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/definitiva/+page.svelte @@ -0,0 +1,390 @@ + + +
+ +
+
+

Facturas

+

+ Gestiona las facturas de importación y exportación +

+
+ +
+ + + {#if error} + + + Error + {error} + + + {/if} + + + + +
+
+ Listado de Facturas + + Mostrando {allItems.length} de {totalItems} registros + {#if companyStore.activeCompany} + - Compañía: {companyStore.activeCompany.name} + {/if} + +
+
+ + + {selectedType === 'all' ? 'Todas' : selectedType === 'imp' ? 'Importación' : 'Exportación'} + + + Todas + Importación + Exportación + + + + {#if selectedType !== 'all' && availableInvoiceTypes.length > 0} + + + + {#if loadingInvoiceTypes} + Cargando... + {:else if selectedInvoiceType} + {(() => { + const found = availableInvoiceTypes.find(t => t.key === selectedInvoiceType); + return found ? `${found.key} - ${found.description}` : selectedInvoiceType; + })()} + {:else} + Todos los tipos + {/if} + + + + Todos los tipos + {#each availableInvoiceTypes as invType} + + + {invType.key} - {invType.description} + + + {/each} + + + {/if} + + +
+
+
+ + + +
+
+ + + + + + + diff --git a/frontend/src/routes/dashboard/invoices/importacion/definitiva/new/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/definitiva/new/+page.svelte new file mode 100644 index 00000000..57e4fc64 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/definitiva/new/+page.svelte @@ -0,0 +1,320 @@ + + +
+ +
+ +
+

Nueva Factura Definitiva

+

Ingresa los datos para registrar la importación.

+
+
+ + {#if error} +
+ ⚠️ {error} +
+ {/if} + +
+ + + + + + General + Cumplimiento + Financieros + + + +
+ +
+ +
Importación
+
+ +
+ +
Definitiva (DEF)
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ +
+ + + + + +
+
+
\ No newline at end of file diff --git a/frontend/src/routes/dashboard/invoices/importacion/temporal/+page.server.ts b/frontend/src/routes/dashboard/invoices/importacion/temporal/+page.server.ts new file mode 100644 index 00000000..83708beb --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/temporal/+page.server.ts @@ -0,0 +1,114 @@ +import type { PageServerLoad } from '../$types'; +import { redirect } from '@sveltejs/kit'; +import { + getAuthTokens, + authenticatedFetch +} from '$lib/server/api'; + +export const load: PageServerLoad = async ({ fetch, cookies, url, parent }) => { + // Esperar a que el layout padre valide/refresque el token + const parentData = await parent(); + + // Verificar autenticación + const { accessToken } = getAuthTokens(cookies); + + if (!accessToken) { + throw redirect(302, '/login'); + } + + try { + // Obtener company_id de múltiples fuentes (en orden de prioridad): + // 1. URL query param (permite cambiar vía navegación) + // 2. Cookie active_company_id (setted por el team-switcher) + // 3. Primera compañía del usuario (fallback) + const companyIdParam = url.searchParams.get('company_id'); + const cookieCompanyId = cookies.get('active_company_id'); + + const companyId = companyIdParam + ? parseInt(companyIdParam) + : cookieCompanyId + ? parseInt(cookieCompanyId) + : parentData.companies?.[0]?.id; + + // Si aún no hay companyId, mostrar error + if (!companyId) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'No se encontró una compañía seleccionada', + companies: parentData.companies || [] + }; + } + + // Obtener filtro de tipo de operación + const operationType = 'imp' + const invoiceType = 'TEM' + + // Construir parámetros de consulta + const params = new URLSearchParams({ + company_id: companyId.toString(), + page: '1', + page_size: '50' + }); + + // Agregar filtro de tipo si existe y no es 'all' + if (operationType && operationType !== 'all') { + params.append('operation_type', operationType); + } + + // Agregar filtro de invoice_type si existe + if (invoiceType) { + params.append('invoice_type', invoiceType); + } + + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/a76/invoices?${params.toString()}`, + {}, + cookies, + fetch, + '/login' + ); + + if (!response.ok) { + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } + + const data = await response.json(); + + return { + items: data.items || [], + total: data.total || 0, + page: data.page || 1, + page_size: data.page_size || 50, + companies: parentData.companies || [], + currentCompanyId: companyId, + operationType: operationType || 'all', + invoiceType: invoiceType || null + }; + } catch (error) { + console.error('Error loading invoices:', error); + return { + items: [], + total: 0, + page: 1, + page_size: 50, + error: 'Error al cargar facturas', + companies: parentData.companies || [], + operationType: 'all', + invoiceType: null + }; + } +}; diff --git a/frontend/src/routes/dashboard/invoices/importacion/temporal/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/temporal/+page.svelte new file mode 100644 index 00000000..d9a1ca87 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/temporal/+page.svelte @@ -0,0 +1,382 @@ + + +
+ +
+
+

Facturas

+

+ Gestiona las facturas de importación y exportación +

+
+ +
+ + + {#if error} + + + Error + {error} + + + {/if} + + + + +
+
+ Listado de Facturas + + Mostrando {allItems.length} de {totalItems} registros + {#if companyStore.activeCompany} + - Compañía: {companyStore.activeCompany.name} + {/if} + +
+
+ + + {selectedType === 'all' ? 'Todas' : selectedType === 'imp' ? 'Importación' : 'Exportación'} + + + Todas + Importación + Exportación + + + + {#if selectedType !== 'all' && availableInvoiceTypes.length > 0} + + + + {#if loadingInvoiceTypes} + Cargando... + {:else if selectedInvoiceType} + {(() => { + const found = availableInvoiceTypes.find(t => t.key === selectedInvoiceType); + return found ? `${found.key} - ${found.description}` : selectedInvoiceType; + })()} + {:else} + Todos los tipos + {/if} + + + + Todos los tipos + {#each availableInvoiceTypes as invType} + + + {invType.key} - {invType.description} + + + {/each} + + + {/if} + + +
+
+
+ + + +
+
+ + + + + + + diff --git a/frontend/src/routes/dashboard/invoices/importacion/temporal/new/+page.svelte b/frontend/src/routes/dashboard/invoices/importacion/temporal/new/+page.svelte new file mode 100644 index 00000000..fae289e8 --- /dev/null +++ b/frontend/src/routes/dashboard/invoices/importacion/temporal/new/+page.svelte @@ -0,0 +1,320 @@ + + +
+ +
+ +
+

Nueva Factura Temporal

+

Ingresa los datos para registrar la importación.

+
+
+ + {#if error} +
+ ⚠️ {error} +
+ {/if} + +
+ + + + + + General + Cumplimiento + Financieros + + + +
+ +
+ +
Importación
+
+ +
+ +
Temporal (TEM)
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ +
+ + + + + +
+
+
\ No newline at end of file