feature/validaciones-pedimento

This commit is contained in:
2026-04-27 11:38:52 -06:00
parent 88ab6b45df
commit 8ac744d770
2 changed files with 74 additions and 111 deletions

View File

@@ -503,7 +503,7 @@
>
<!-- Año -->
<div class="space-y-2">
<Label for="year">Año <span class="text-red-500">*</span></Label>
<Label for="year">Año</Label>
<Input
id="year"
bind:value={formData.year}
@@ -612,12 +612,7 @@
<!-- Tipo de Cambio -->
<div class="space-y-2">
<Label for="exchange_rate">
Tipo de Cambio
{#if !(formData.pedimento_type === 'consolidated' && getEffectiveExchangeDate() > getCurrentLocalDate())}
<span class="text-red-500">*</span>
{/if}
</Label>
<Label for="exchange_rate">Tipo de Cambio</Label>
<Input
id="exchange_rate"
type="text"
@@ -843,7 +838,7 @@
<!-- Destino -->
<div class="space-y-2">
<Label for="destino">Destino <span class="text-red-500">*</span></Label>
<Label for="destino">Destino</Label>
<Select.Root
type="single"
value={formData.pedimento_transport_means.destination
@@ -1025,13 +1020,11 @@
<Input id="entry_date" type="date" bind:value={formData.entry_date} />
</div>
<!-- Fecha Fin (Solo Consolidado) -->
{#if formData.pedimento_type === 'consolidated'}
<div class="space-y-2">
<Label for="end_date">Fecha Fin <span class="text-red-500">*</span></Label>
<Input id="end_date" type="date" bind:value={formData.end_date} />
</div>
{/if}
<!-- Fecha Fin -->
<div class="space-y-2">
<Label for="end_date">Fecha Final <span class="text-red-500">*</span></Label>
<Input id="end_date" type="date" bind:value={formData.end_date} />
</div>
<!-- Fecha de Pago -->
<div class="space-y-2">

View File

@@ -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<boolean> {
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<string, string> = {
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;
}