From 8ac744d7707530867dbc6b9e2bbe58a00905a1c6 Mon Sep 17 00:00:00 2001 From: hreyes Date: Mon, 27 Apr 2026 11:38:52 -0600 Subject: [PATCH] feature/validaciones-pedimento --- .../pedimentos/edit/general-tab-form.svelte | 23 +-- .../pedimentos/edit/[id]/+page.svelte | 162 +++++++----------- 2 files changed, 74 insertions(+), 111 deletions(-) diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte index 7ae354d7..052effca 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte @@ -503,7 +503,7 @@ >
- +
- +
- +
- - {#if formData.pedimento_type === 'consolidated'} -
- - -
- {/if} + +
+ + +
diff --git a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte index 21eb5399..0ca75b93 100644 --- a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte +++ b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte @@ -83,11 +83,8 @@ authenticated?: boolean; } - import { getExchangeRateByDate } from '$lib/api/dashboard/a76/exchange-rate'; - import ExchangeRateDialog from '$lib/components/dashboard/exchange_rate/create-edit-dialog.svelte'; import { companyStore } from '$lib/stores/company.svelte'; import PrerequisitesModal from '$lib/components/dashboard/PrerequisitesModal.svelte'; - import { getCurrentLocalDate } from '$lib/date-utils'; let { data }: { data: ExtendedPageData } = $props(); @@ -123,10 +120,6 @@ }) ); - // Dialog state lifted up - let showExchangeRateDialog = $state(false); - let missingExchangeRateDate = $state(''); - // Prerrequisitos: modal solo en creación cuando no hay agentes o clientes const agentsCount = $derived(data.customsBrokers?.length ?? 0); const clientsCount = $derived(data.clients?.length ?? 0); @@ -141,31 +134,58 @@ } }); - async function checkPaymentDateRate(date: string): Promise { - if (!date || !companyStore.activeCompany?.id) return true; - - try { - const rate = await getExchangeRateByDate(date, companyStore.activeCompany.id); - if (!rate) { - missingExchangeRateDate = date; - showExchangeRateDialog = true; - return false; - } - return true; - } catch (error) { - console.error('Error checking payment date rate:', error); - // Si falla, forzamos diálogo para seguridad - missingExchangeRateDate = date; - showExchangeRateDialog = true; - return false; - } + function normalizeDateValue(value: string | null | undefined): string | null { + if (!value) return null; + return value.includes('T') ? value.slice(0, 10) : value; } - function getExchangeDateForPedimento(formData: any): { date: string | null; label: string } { - return { - date: formData?.start_date || null, - label: 'fecha de inicio' - }; + function validateLegacyDateConsistency(formData: any): boolean { + const startDate = normalizeDateValue(formData?.start_date); + const endDate = normalizeDateValue(formData?.end_date); + const entryDate = normalizeDateValue(formData?.entry_date); + const paymentDate = normalizeDateValue(formData?.payment_date); + const referenceDate = paymentDate || entryDate; + const pedimentoType = formData?.pedimento_type; + const isConsolidated = pedimentoType === 'consolidated'; + const isIndividual = pedimentoType === 'normal'; + + if (!startDate || !endDate || !referenceDate) return true; + + // Legacy Clarion (CON): inicio <= fin <= fecha de referencia (pago / entrada) + if (isConsolidated) { + if (startDate > endDate) { + toast.error( + `La fecha inicio (${startDate}) no puede ser mayor que la fecha final (${endDate}).` + ); + activeTab = 'general'; + return false; + } + + if (startDate > referenceDate) { + toast.error( + `La fecha inicio (${startDate}) no puede ser mayor que la fecha de referencia (${referenceDate}).` + ); + activeTab = 'general'; + return false; + } + + if (endDate > referenceDate) { + toast.error( + `La fecha final (${endDate}) no puede ser mayor que la fecha de referencia (${referenceDate}).` + ); + activeTab = 'general'; + return false; + } + } + + // Legacy Clarion (IND): advertencia si las fechas no coinciden, sin bloqueo. + if (isIndividual && (startDate !== endDate || startDate !== referenceDate)) { + toast.warning( + 'Advertencia: en pedimento individual las fechas inicio/final/referencia son distintas.' + ); + } + + return true; } // ID del pedimento @@ -410,35 +430,19 @@ saving = true; try { - // Verificar tipo de cambio según catalogo de transporte (E/P) - if (generalTabInstance && generalFormData) { - const exchangeRef = getExchangeDateForPedimento(generalFormData); - const isConsolidated = generalFormData.pedimento_type === 'consolidated'; - const todayStr = getCurrentLocalDate(); - const isFutureDate = exchangeRef.date && exchangeRef.date > todayStr; - - // Solo verificar si NO es un consolidado con fecha futura - if (!(isConsolidated && isFutureDate)) { - const rateExists = await generalTabInstance.checkPaymentDateRate(exchangeRef.date || ''); - if (!rateExists) { - saving = false; - // Asegurar que se muestre el tab general - activeTab = 'general'; - return; - } - } - } - - // Validar campos requeridos para creación (client_id es opcional) - if (data.isCreate && generalFormData) { + // Validar campos requeridos para guardar (client_id es opcional) + if (generalFormData) { const requiredFields: Record = { - year: 'Año', customs_office: 'Aduana', license: 'Patente', pedimento_number: 'Número de Pedimento', - start_date: 'Fecha de Inicio', + operation_type: 'Tipo de Operación', + pedimento_type: 'Tipo de Pedimento', pedimento_code: 'Clave', - regime: 'Régimen' + regime: 'Régimen', + start_date: 'Fecha de Inicio', + end_date: 'Fecha Final', + entry_date: 'Fecha de Entrada' }; const missingFields: string[] = []; @@ -454,41 +458,9 @@ } } - // Validar tipo de cambio en create y update segun fecha efectiva del metodo de transporte - if (generalFormData) { - const exchangeRef = getExchangeDateForPedimento(generalFormData); - const rate = generalFormData.exchange_rate; - const isConsolidated = generalFormData.pedimento_type === 'consolidated'; - const todayStr = getCurrentLocalDate(); - const isFutureDate = exchangeRef.date && exchangeRef.date > todayStr; - - if ( - rate === null || - rate === undefined || - String(rate).trim() === '' || - Number(rate) <= 0 - ) { - // Si es consolidado y fecha futura, permitimos continuar con un warning - if (isConsolidated && isFutureDate) { - toast.warning( - `Aviso: No hay tipo de cambio para la ${exchangeRef.label} (${exchangeRef.date}), pero se permite continuar por ser pedimento consolidado.` - ); - } else { - saving = false; - activeTab = 'general'; - const date = exchangeRef.date || ''; - toast.error( - Number(rate) <= 0 && rate !== null && rate !== undefined - ? `El tipo de cambio debe ser mayor a 0. Registra el tipo de cambio para la ${exchangeRef.label}.` - : `No hay tipo de cambio registrado para la ${exchangeRef.label}. Por favor, regístralo antes de guardar.` - ); - if (date) { - missingExchangeRateDate = date; - showExchangeRateDialog = true; - } - return; - } - } + if (generalFormData && !validateLegacyDateConsistency(generalFormData)) { + saving = false; + return; } // Construir el payload unificado @@ -1063,13 +1035,11 @@ errorStr.includes('No existe un Tipo de Cambio registrado') || errorStr.includes('financials.exchange_rate') ) { - // Interceptar error de tipo de cambio - console.log('Interceptor: Exchange rate missing error caught (Pedimento).'); - - const missingDate = dateMatch ? dateMatch[0] : (generalFormData?.start_date || ''); - - missingExchangeRateDate = missingDate; - showExchangeRateDialog = true; + // Evitamos bloquear por validaciones locales de tipo de cambio, pero + // si backend lo rechaza informamos el motivo y mantenemos al usuario en General. + toast.error( + 'El backend rechazó el guardado por tipo de cambio faltante o inválido. Revisa la fecha de inicio/pago y registra el tipo de cambio requerido.' + ); activeTab = 'general'; return; }