pedimentos UI

This commit is contained in:
Galindo97
2025-12-23 14:15:05 -06:00
parent d3a0086188
commit 150efdfd99
61 changed files with 1033 additions and 256 deletions

View File

@@ -56,6 +56,7 @@
},
"dependencies": {
"keycloak-js": "^26.2.1",
"lucide-svelte": "^0.553.0"
"lucide-svelte": "^0.553.0",
"svelte-sonner": "^1.0.7"
}
}

View File

@@ -14,6 +14,9 @@ importers:
lucide-svelte:
specifier: ^0.553.0
version: 0.553.0(svelte@5.40.2)
svelte-sonner:
specifier: ^1.0.7
version: 1.0.7(svelte@5.40.2)
devDependencies:
'@eslint/compat':
specifier: ^1.4.0
@@ -1675,6 +1678,11 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
runed@0.28.0:
resolution: {integrity: sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ==}
peerDependencies:
svelte: ^5.7.0
runed@0.35.1:
resolution: {integrity: sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==}
peerDependencies:
@@ -1761,6 +1769,11 @@ packages:
svelte:
optional: true
svelte-sonner@1.0.7:
resolution: {integrity: sha512-1EUFYmd7q/xfs2qCHwJzGPh9n5VJ3X6QjBN10fof2vxgy8fYE7kVfZ7uGnd7i6fQaWIr5KvXcwYXE/cmTEjk5A==}
peerDependencies:
svelte: ^5.0.0
svelte-toolbelt@0.10.6:
resolution: {integrity: sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==}
engines: {node: '>=18', pnpm: '>=8.7.0'}
@@ -3379,6 +3392,11 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
runed@0.28.0(svelte@5.40.2):
dependencies:
esm-env: 1.2.2
svelte: 5.40.2
runed@0.35.1(@sveltejs/kit@2.47.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2):
dependencies:
dequal: 2.0.3
@@ -3460,6 +3478,11 @@ snapshots:
optionalDependencies:
svelte: 5.40.2
svelte-sonner@1.0.7(svelte@5.40.2):
dependencies:
runed: 0.28.0(svelte@5.40.2)
svelte: 5.40.2
svelte-toolbelt@0.10.6(@sveltejs/kit@2.47.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2)(vite@7.1.10(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)))(svelte@5.40.2):
dependencies:
clsx: 2.1.1

View File

@@ -1,3 +1,4 @@
import { deLocalizeUrl } from '$lib/paraglide/runtime';
import type { RequestEvent } from '@sveltejs/kit';
export const reroute = (request) => deLocalizeUrl(request.url).pathname;
export const reroute = (request: { url: string }) => deLocalizeUrl(request.url).pathname;

View File

@@ -26,23 +26,32 @@ export interface ExchangeRateListResponse {
*/
export async function getExchangeRateByDate(date: string, companyId: number): Promise<ExchangeRate | null> {
try {
console.log('📡 [API] Solicitando tipos de cambio para company_id:', companyId);
// Get all exchange rates and filter by date on client side
const response = await api.get<ExchangeRateListResponse>(`/v1/a76/exchange-rate/?company_id=${companyId}`);
console.log('📡 [API] Respuesta recibida:', response.data?.total, 'tipos de cambio');
if (response.data && response.data.items && response.data.items.length > 0) {
// Filter by date and find USD exchange rate
const dateOnly = date.split('T')[0]; // Get YYYY-MM-DD part
console.log('🔍 [API] Buscando fecha:', dateOnly, 'en', response.data.items.length, 'registros');
const matchingRates = response.data.items.filter(rate => {
const rateDate = rate.date.split('T')[0];
return rateDate === dateOnly && rate.foreign_currency === 'USD';
const matches = rateDate === dateOnly && rate.foreign_currency === 'USD';
console.log(' - Comparando:', rateDate, '===', dateOnly, '&& USD ===', rate.foreign_currency, '→', matches);
return matches;
});
console.log('✅ [API] Encontrados', matchingRates.length, 'tipos de cambio que coinciden');
return matchingRates.length > 0 ? matchingRates[0] : null;
}
console.log('⚠️ [API] No hay datos en la respuesta');
return null;
} catch (error) {
console.error('Error fetching exchange rate:', error);
console.error('❌ [API] Error fetching exchange rate:', error);
return null;
}
}

View File

@@ -85,6 +85,69 @@ export interface PedimentoConfigAdditional {
add_remove_norms?: number | null;
}
export interface PedimentoConfigCalculations {
dta_type?: string | null;
dta_operation?: number | null;
dta_vehicle_count?: number | null;
dta_mixed_rate_8permil?: number | null;
pays_vat?: number | null;
pays_prevalidation?: number | null;
include_sagar_certificate_fee?: number | null;
fixed_vehicle_dta_fee?: number | null;
additional_fixed_fee?: number | null;
additional_fixed_fee_payment_method?: number | null;
}
export interface PedimentoConfigSurcharges {
surcharge_igi?: number | null;
surcharge_dta?: number | null;
surcharge_vat?: number | null;
surcharge_isan?: number | null;
surcharge_ieps?: number | null;
surcharge_cc?: number | null;
}
export interface PedimentoConfigParameters {
is_embassy?: number | null;
embassy_dta?: string | null;
rule_3121_section_ii?: number | null;
use_previous_tariff?: number | null;
use_payment_date_fi?: number | null;
add_state_supplier_record_505?: number | null;
customs_value_calculation?: number | null;
two_decimals_unit_value?: number | null;
customs_value_per_item?: number | null;
is_national_supplier?: number | null;
is_consolidated?: number | null;
}
export interface PedimentoConfigUpdates {
update_vat?: number | null;
update_advalorem?: number | null;
update_dta?: number | null;
update_cc?: number | null;
update_ieps?: number | null;
}
export interface PedimentoConfigUpdateRectification {
update_vat?: number | null;
update_advalorem?: number | null;
update_cc?: number | null;
update_ieps?: number | null;
calculate_surcharge?: number | null;
}
export interface Identificador {
id?: number;
pedimento_id?: number;
caso: string;
complemento1: string;
complemento2: string;
complemento3: string;
nodo: string;
observaciones: string;
}
export interface Pedimento {
id: number;
tenant_id: number;
@@ -102,7 +165,7 @@ export interface Pedimento {
paid_price?: number | null;
gross_weight?: number | null;
exchange_rate?: number | null;
observaciones?: string | null;
observations?: string | null;
created_at: string;
// Sub-resources
pedimento_dates?: PedimentoDates | null;
@@ -113,6 +176,12 @@ export interface Pedimento {
pedimento_decrementables?: PedimentoDecrementables | null;
pedimento_indexes?: PedimentoIndexes | null;
pedimento_config_additional?: PedimentoConfigAdditional | null;
pedimento_config_calculations?: PedimentoConfigCalculations | null;
pedimento_config_surcharges?: PedimentoConfigSurcharges | null;
pedimento_config_parameters?: PedimentoConfigParameters | null;
pedimento_config_updates?: PedimentoConfigUpdates | null;
pedimento_config_update_rectification?: PedimentoConfigUpdateRectification | null;
identificadores?: Identificador[] | null;
}
export interface PedimentoListResponse {
@@ -137,7 +206,7 @@ export interface CreatePedimentoData {
paid_price?: number | null;
gross_weight?: number | null;
exchange_rate?: number | null;
observaciones?: string | null;
observations?: string | null;
// Sub-resources
pedimento_dates?: PedimentoDates | null;
pedimento_payments?: PedimentoPayments | null;
@@ -147,6 +216,12 @@ export interface CreatePedimentoData {
pedimento_decrementables?: PedimentoDecrementables | null;
pedimento_indexes?: PedimentoIndexes | null;
pedimento_config_additional?: PedimentoConfigAdditional | null;
pedimento_config_calculations?: PedimentoConfigCalculations | null;
pedimento_config_surcharges?: PedimentoConfigSurcharges | null;
pedimento_config_parameters?: PedimentoConfigParameters | null;
pedimento_config_updates?: PedimentoConfigUpdates | null;
pedimento_config_update_rectification?: PedimentoConfigUpdateRectification | null;
identificadores?: Identificador[] | null;
}
export interface UpdatePedimentoData {
@@ -164,7 +239,7 @@ export interface UpdatePedimentoData {
paid_price?: number | null;
gross_weight?: number | null;
exchange_rate?: number | null;
observaciones?: string | null;
observations?: string | null;
// Sub-resources
pedimento_dates?: PedimentoDates | null;
pedimento_payments?: PedimentoPayments | null;
@@ -174,6 +249,12 @@ export interface UpdatePedimentoData {
pedimento_decrementables?: PedimentoDecrementables | null;
pedimento_indexes?: PedimentoIndexes | null;
pedimento_config_additional?: PedimentoConfigAdditional | null;
pedimento_config_calculations?: PedimentoConfigCalculations | null;
pedimento_config_surcharges?: PedimentoConfigSurcharges | null;
pedimento_config_parameters?: PedimentoConfigParameters | null;
pedimento_config_updates?: PedimentoConfigUpdates | null;
pedimento_config_update_rectification?: PedimentoConfigUpdateRectification | null;
identificadores?: Identificador[] | null;
}
export interface PedimentoFilters {

View File

@@ -2,26 +2,7 @@ import type { ColumnDef } from "@tanstack/table-core";
import { renderComponent, renderSnippet } from "$lib/components/ui/data-table/index.js";
import { createRawSnippet } from "svelte";
import DataTableActions from "./data-table-actions.svelte";
export type Pedimento = {
id: number;
tenant_id: number;
year?: string | null;
customs_office?: string | null;
license?: string | null;
pedimento_number?: string | null;
client_id?: number | null;
operation_type?: number | null;
pedimento_type?: number | null;
pedimento_code?: string | null;
regime?: string | null;
status?: string | null;
usd_value?: number | null;
paid_price?: number | null;
gross_weight?: number | null;
exchange_rate?: number | null;
created_at: string;
};
import type { Pedimento } from "$lib/api/dashboard/a76/pedimentos";
/**
* Formatea un número como moneda

View File

@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
import { pedimentosApi, type Pedimento } from "$lib/api/dashboard/a76/pedimentos";
import { companyStore } from "$lib/stores/company.svelte";
import { EllipsisVertical, Pencil, LoaderCircle, Trash2 } from 'lucide-svelte';
let {
@@ -24,7 +25,8 @@
error = null;
try {
const response = await pedimentosApi.delete(item.id);
const companyId = companyStore.activeCompany?.id;
const response = await pedimentosApi.delete(item.id, companyId);
if (response.error) {
if (response.status === 401) {

View File

@@ -19,7 +19,7 @@
DialogTitle,
DialogFooter
} from '$lib/components/ui/dialog';
import Checkbox from '$lib/components/ui/checkbox/checkbox.svelte';
import { Checkbox } from '$lib/components/ui/checkbox';
import {
Plus,
Pencil,

View File

@@ -17,14 +17,18 @@
pedimentoNumber?: string;
} = $props();
// Inicializar formData
if (!formData) {
formData = {
observaciones: pedimento?.observaciones || ''
};
}
exists = !!pedimento?.observaciones;
// Asegurar que formData siempre tenga un valor por defecto
formData = formData || { observaciones: '' };
// Actualizar formData cuando el pedimento cambie
$effect(() => {
if (pedimento?.observations !== undefined) {
formData = {
observaciones: pedimento.observations || ''
};
exists = !!pedimento.observations;
}
});
// Mapear el tipo de pedimento a un nombre legible
const tipoPedimentoNombre = $derived.by(() => {

View File

@@ -11,10 +11,12 @@
import type { CustomsBroker } from '$lib/api/dashboard/a76/customs-brokers';
import type { ClientProvider } from '$lib/api/dashboard/a76/clients-providers';
import type { CodePedimentoRegimen } from '$lib/api/dashboard/refrence_data/code_pedimento_regimens';
import IdentificadoresTabForm from './identifiers-tab-form.svelte';
let {
pedimento,
formData = $bindable(),
identificadoresFormData = $bindable(),
pedimentoCodes = [],
customsSections = [],
customsBrokers = [],
@@ -23,6 +25,7 @@
}: {
pedimento: Pedimento | null;
formData?: any;
identificadoresFormData?: any;
pedimentoCodes?: PedimentoCode[];
customsSections?: CustomsSection[];
customsBrokers?: CustomsBroker[];
@@ -249,19 +252,23 @@
// Obtener automáticamente el tipo de cambio cuando cambie la fecha de entrada
$effect(() => {
if (formData && formData.entry_date && companyStore.activeCompany) {
console.log('Buscando tipo de cambio para fecha:', formData.entry_date);
console.log('🔍 [TIPO CAMBIO] Buscando para fecha:', formData.entry_date, 'Company ID:', companyStore.activeCompany.id);
getExchangeRateByDate(formData.entry_date, companyStore.activeCompany.id)
.then(usdRate => {
console.log('Tipo de cambio USD encontrado:', usdRate);
console.log('✅ [TIPO CAMBIO] Respuesta recibida:', usdRate);
if (usdRate && formData) {
formData.exchange_rate = usdRate.value;
console.log('Tipo de cambio actualizado a:', usdRate.value);
console.log('✅ [TIPO CAMBIO] Actualizado a:', usdRate.value);
} else {
console.warn('No se encontró tipo de cambio USD para la fecha:', formData.entry_date);
console.warn('⚠️ [TIPO CAMBIO] No encontrado para fecha:', formData.entry_date);
}
})
.catch(err => console.error('Error al obtener tipo de cambio:', err));
.catch(err => {
console.error('❌ [TIPO CAMBIO] Error:', err);
});
} else {
console.log('⏭️ [TIPO CAMBIO] Saltado - formData:', !!formData, 'entry_date:', formData?.entry_date, 'company:', !!companyStore.activeCompany);
}
});
@@ -417,10 +424,9 @@
<Label for="exchange_rate">Tipo de Cambio <span class="text-red-500">*</span></Label>
<Input
id="exchange_rate"
type="number"
step="0.0001"
bind:value={formData.exchange_rate}
placeholder="En fecha de entrada"
type="text"
value={formData.exchange_rate ? Number(formData.exchange_rate).toFixed(6) : ''}
placeholder="Se obtiene automáticamente de la fecha de entrada"
readonly
disabled
class="bg-muted cursor-not-allowed"
@@ -898,9 +904,7 @@
</div>
{:else if activeSection === 'identificadores'}
<!-- Identificadores -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<p class="text-muted-foreground col-span-full">Campos de Identificadores - Por configurar</p>
</div>
<IdentificadoresTabForm bind:formData={identificadoresFormData} />
{:else if activeSection === 'indices'}
<!-- Indices -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">

View File

@@ -0,0 +1,174 @@
<script lang="ts">
import { Card } from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { Textarea } from '$lib/components/ui/textarea';
import * as Table from '$lib/components/ui/table';
import * as Dialog from '$lib/components/ui/dialog';
interface Identificador {
caso: string;
complemento1: string;
complemento2: string;
complemento3: string;
nodo: string;
observaciones: string;
}
let {
formData = $bindable({
identificadores: []
})
}: {
formData: {
identificadores: Identificador[];
};
} = $props();
let isIdentificadorDialogOpen = $state(false);
let editingIdentificadorIndex = $state<number | null>(null);
let currentIdentificador = $state<Identificador>({
caso: '',
complemento1: '',
complemento2: '',
complemento3: '',
nodo: '',
observaciones: ''
});
function handleNuevoIdentificador() {
currentIdentificador = {
caso: '',
complemento1: '',
complemento2: '',
complemento3: '',
nodo: '',
observaciones: ''
};
editingIdentificadorIndex = null;
isIdentificadorDialogOpen = true;
}
function handleEditarIdentificador(index: number) {
currentIdentificador = { ...formData.identificadores[index] };
editingIdentificadorIndex = index;
isIdentificadorDialogOpen = true;
}
function handleBorrarIdentificador(index: number) {
formData.identificadores = formData.identificadores.filter((_, i) => i !== index);
}
function saveIdentificador() {
if (editingIdentificadorIndex !== null) {
formData.identificadores[editingIdentificadorIndex] = { ...currentIdentificador };
} else {
formData.identificadores = [...formData.identificadores, { ...currentIdentificador }];
}
isIdentificadorDialogOpen = false;
}
</script>
<Card class="p-6">
<div class="space-y-4">
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold">Identificadores</h3>
<Button size="sm" onclick={handleNuevoIdentificador}>
Nuevo
</Button>
</div>
{#if formData.identificadores.length === 0}
<p class="text-sm text-muted-foreground text-center py-8">
No hay identificadores registrados
</p>
{:else}
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head>Caso</Table.Head>
<Table.Head>Complemento 1</Table.Head>
<Table.Head>Complemento 2</Table.Head>
<Table.Head>Complemento 3</Table.Head>
<Table.Head>Nodo</Table.Head>
<Table.Head>Observaciones</Table.Head>
<Table.Head class="text-right">Acciones</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each formData.identificadores as identificador, index}
<Table.Row>
<Table.Cell>{identificador.caso}</Table.Cell>
<Table.Cell>{identificador.complemento1}</Table.Cell>
<Table.Cell>{identificador.complemento2}</Table.Cell>
<Table.Cell>{identificador.complemento3}</Table.Cell>
<Table.Cell>{identificador.nodo}</Table.Cell>
<Table.Cell class="max-w-xs truncate">{identificador.observaciones}</Table.Cell>
<Table.Cell class="text-right">
<div class="flex justify-end gap-2">
<Button size="sm" variant="outline" onclick={() => handleEditarIdentificador(index)}>
Editar
</Button>
<Button size="sm" variant="destructive" onclick={() => handleBorrarIdentificador(index)}>
Borrar
</Button>
</div>
</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
{/if}
</div>
</Card>
<!-- Dialog para agregar/editar identificador -->
<Dialog.Root bind:open={isIdentificadorDialogOpen}>
<Dialog.Content class="max-w-2xl">
<Dialog.Header>
<Dialog.Title>
{editingIdentificadorIndex !== null ? 'Editar' : 'Nuevo'} Identificador
</Dialog.Title>
</Dialog.Header>
<div class="grid grid-cols-2 gap-4">
<div class="space-y-2">
<Label for="caso">Caso</Label>
<Input id="caso" bind:value={currentIdentificador.caso} />
</div>
<div class="space-y-2">
<Label for="complemento1">Complemento 1</Label>
<Input id="complemento1" bind:value={currentIdentificador.complemento1} />
</div>
<div class="space-y-2">
<Label for="complemento2">Complemento 2</Label>
<Input id="complemento2" bind:value={currentIdentificador.complemento2} />
</div>
<div class="space-y-2">
<Label for="complemento3">Complemento 3</Label>
<Input id="complemento3" bind:value={currentIdentificador.complemento3} />
</div>
<div class="space-y-2">
<Label for="nodo">Nodo</Label>
<Input id="nodo" bind:value={currentIdentificador.nodo} />
</div>
<div class="space-y-2 col-span-2">
<Label for="observaciones">Observaciones</Label>
<Textarea id="observaciones" bind:value={currentIdentificador.observaciones} rows={3} />
</div>
</div>
<Dialog.Footer>
<Button variant="outline" onclick={() => (isIdentificadorDialogOpen = false)}>
Cancelar
</Button>
<Button onclick={saveIdentificador}>Aceptar</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>

View File

@@ -4,7 +4,7 @@
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import * as Select from '$lib/components/ui/select';
import Checkbox from '$lib/components/ui/checkbox/checkbox.svelte';
import { Checkbox } from '$lib/components/ui/checkbox';
import {
Table,
TableBody,
@@ -447,32 +447,7 @@
currentPartesIIPage = totalPartesIIPages - 1;
}
function goToNotasFirstPage() {
currentNotasPage = 0;
}
function goToNotasPreviousPage() {
if (currentNotasPage > 0) currentNotasPage--;
}
function goToNotasNextPage() {
if (currentNotasPage < totalNotasPages - 1) currentNotasPage++;
}
function goToNotasLastPage() {
currentNotasPage = totalNotasPages - 1;
}
function toggleSelectAll() {
if (selectedEmbarques.length === embarquesParciales.length) {
selectedEmbarques = [];
} else {
selectedEmbarques = embarquesParciales.map((_, i) => i);
}
}
function handleNuevoEmbarque() {
editingEmbarqueIndex = null;
currentEmbarque = {
numero: '',
peso: 0,
@@ -495,6 +470,14 @@
isEmbarqueDialogOpen = true;
}
function toggleSelectAll() {
if (selectedEmbarques.length === embarquesParciales.length) {
selectedEmbarques = [];
} else {
selectedEmbarques = embarquesParciales.map((_, i) => i);
}
}
function handleEditarEmbarque() {
alert('Editar Embarque no implementado');
}
@@ -654,6 +637,22 @@
}
}
function goToNotasFirstPage() {
currentNotasPage = 0;
}
function goToNotasPreviousPage() {
if (currentNotasPage > 0) currentNotasPage--;
}
function goToNotasNextPage() {
if (currentNotasPage < totalNotasPages - 1) currentNotasPage++;
}
function goToNotasLastPage() {
currentNotasPage = totalNotasPages - 1;
}
function handleSeleccionAutomatizada() {
showBitacora = false;
showPartesII = false;

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { goto, invalidateAll } from '$app/navigation';
import * as Tabs from '$lib/components/ui/tabs';
import * as Alert from '$lib/components/ui/alert';
import { Button } from '$lib/components/ui/button';
@@ -27,14 +27,14 @@
// Importar los componentes de cada pestaña (ahora sin botones de guardar propios)
import GeneralTabForm from '$lib/components/dashboard/pedimentos/edit/general-tab-form.svelte';
import DatesTabForm from '$lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte';
import FacturasTabForm from '$lib/components/dashboard/pedimentos/edit/facturas-tab-form.svelte';
import PartidasTabForm from '$lib/components/dashboard/pedimentos/edit/partidas-tab-form.svelte';
import BultosTransportesTabForm from '$lib/components/dashboard/pedimentos/edit/bultos-transportes-tab-form.svelte';
import DescargasTabForm from '$lib/components/dashboard/pedimentos/edit/descargas-tab-form.svelte';
import ContribucionesTabForm from '$lib/components/dashboard/pedimentos/edit/contribuciones-tab-form.svelte';
import CuentasCompensacionTabForm from '$lib/components/dashboard/pedimentos/edit/cuentas-compensacion-tab-form.svelte';
import DigitalizacionTabForm from '$lib/components/dashboard/pedimentos/edit/digitalizacion-tab-form.svelte';
import OtrosDatosTabForm from '$lib/components/dashboard/pedimentos/edit/otros-datos-tab-form.svelte';
import FacturasTabForm from '$lib/components/dashboard/pedimentos/edit/invoices-tab-form.svelte';
import PartidasTabForm from '$lib/components/dashboard/pedimentos/edit/items-tab-form.svelte';
import BultosTransportesTabForm from '$lib/components/dashboard/pedimentos/edit/package-transportation-tab-form.svelte';
import DescargasTabForm from '$lib/components/dashboard/pedimentos/edit/discharge-tab-form.svelte';
import ContribucionesTabForm from '$lib/components/dashboard/pedimentos/edit/contributions-tab-form.svelte';
import CuentasCompensacionTabForm from '$lib/components/dashboard/pedimentos/edit/accounts-compensation-tab-form.svelte';
import DigitalizacionTabForm from '$lib/components/dashboard/pedimentos/edit/digitization-tab-form.svelte';
import OtrosDatosTabForm from '$lib/components/dashboard/pedimentos/edit/other-data-tab-form.svelte';
import PaymentsTabForm from '$lib/components/dashboard/pedimentos/edit/payments-tab-form.svelte';
import TransportTabForm from '$lib/components/dashboard/pedimentos/edit/transport-tab-form.svelte';
import ValidationTabForm from '$lib/components/dashboard/pedimentos/edit/validation-tab-form.svelte';
@@ -104,6 +104,9 @@
let digitalizacionFormData = $state({
digitalizaciones: []
});
let identificadoresFormData = $state({
identificadores: []
});
let otrosDatosFormData = $state({
tipo_calculo: 'ninguno',
dta_por_operacion_ag_facturas: false,
@@ -187,11 +190,8 @@
license: 'Patente',
pedimento_number: 'Número de Pedimento',
client_id: 'ID del Cliente',
operation_type: 'Tipo de Operación',
pedimento_type: 'Tipo de Pedimento',
pedimento_code: 'Clave',
regime: 'Régimen',
status: 'Estado'
regime: 'Régimen'
};
const missingFields: string[] = [];
@@ -226,13 +226,28 @@
exchange_rate: generalFormData?.exchange_rate || undefined
};
// Fechas - enviar si hay al menos un campo con valor
if (generalFormData) {
const hasDatesValue = generalFormData.entry_date || generalFormData.pedimento_date ||
generalFormData.extraction_date || generalFormData.rectification_payment_date ||
generalFormData.original_date || generalFormData.payment_date;
if (hasDatesValue) {
payload.pedimento_dates = {
entry_date: generalFormData.entry_date || null,
pedimento_date: generalFormData.pedimento_date || null,
payment_date: generalFormData.payment_date || null,
rectification_payment_date: generalFormData.rectification_payment_date || null,
extraction_date: generalFormData.extraction_date || null,
original_date: generalFormData.original_date || null
};
}
}
// Solo agregar sub-recursos en modo UPDATE (no en CREATE)
// Y solo si tienen valores reales (no enviar objetos vacíos/null)
// Observaciones - solo enviar si hay valor
if (observacionesFormData?.observaciones) {
payload.observaciones = observacionesFormData.observaciones;
}
// Observaciones - siempre enviar (puede ser string vacío para borrar)
payload.observations = observacionesFormData?.observaciones || '';
// Incrementables - solo enviar si hay al menos un campo con valor
if (generalFormData) {
@@ -310,6 +325,133 @@
}
// Identificadores - enviar array de identificadores si existen
if (identificadoresFormData?.identificadores && identificadoresFormData.identificadores.length > 0) {
payload.identificadores = identificadoresFormData.identificadores;
}
// Config Calculations - configuraciones de cálculo DTA, IVA, prevalidación
if (otrosDatosFormData) {
const hasCalculationsValue = otrosDatosFormData.tipo_calculo ||
otrosDatosFormData.dta_por_operacion_ag_facturas !== undefined ||
otrosDatosFormData.dta_por_numero_vehiculos !== undefined ||
otrosDatosFormData.paga_iva !== undefined ||
otrosDatosFormData.paga_prevalidacion !== undefined ||
otrosDatosFormData.aplicar_dta_8_millar_partida !== undefined ||
otrosDatosFormData.incluir_eci !== undefined ||
otrosDatosFormData.cuota_fija_adicional_vehiculo !== undefined ||
otrosDatosFormData.cuota_fija_adicional_fp;
if (hasCalculationsValue) {
// Convertir tipo_calculo a 1 carácter para dta_type
let dtaTypeValue = null;
if (otrosDatosFormData.tipo_calculo === 'normal') {
dtaTypeValue = '1';
} else if (otrosDatosFormData.tipo_calculo === 'simplificado') {
dtaTypeValue = '2';
}
payload.pedimento_config_calculations = {
dta_type: dtaTypeValue,
dta_operation: otrosDatosFormData.dta_por_operacion_ag_facturas ? 1 : 0,
dta_vehicle_count: otrosDatosFormData.dta_por_numero_vehiculos ? 1 : 0,
dta_mixed_rate_8permil: otrosDatosFormData.aplicar_dta_8_millar_partida ? 1 : 0,
pays_vat: otrosDatosFormData.paga_iva ? 1 : 0,
pays_prevalidation: otrosDatosFormData.paga_prevalidacion ? 1 : 0,
include_sagar_certificate_fee: otrosDatosFormData.incluir_eci ? 1 : 0,
fixed_vehicle_dta_fee: otrosDatosFormData.cuota_fija_adicional_vehiculo ? 1 : 0,
additional_fixed_fee: otrosDatosFormData.cuota_fija_adicional_fp ? parseInt(otrosDatosFormData.cuota_fija_adicional_fp) : 0,
additional_fixed_fee_payment_method: null
};
}
}
// Config Surcharges - configuraciones de recargos
if (otrosDatosFormData) {
const hasSurchargesValue = otrosDatosFormData.recargo_igi !== undefined ||
otrosDatosFormData.deducible_recargos !== undefined ||
otrosDatosFormData.recargo_iva !== undefined ||
otrosDatosFormData.recargo_ieps !== undefined ||
otrosDatosFormData.recargo_isan !== undefined ||
otrosDatosFormData.recargo_cc !== undefined;
if (hasSurchargesValue) {
payload.pedimento_config_surcharges = {
surcharge_igi: otrosDatosFormData.recargo_igi ? 1 : 0,
surcharge_dta: otrosDatosFormData.deducible_recargos ? 1 : 0,
surcharge_vat: otrosDatosFormData.recargo_iva ? 1 : 0,
surcharge_ieps: otrosDatosFormData.recargo_ieps ? 1 : 0,
surcharge_isan: otrosDatosFormData.recargo_isan ? 1 : 0,
surcharge_cc: otrosDatosFormData.recargo_cc ? 1 : 0
};
}
}
// Config Parameters - parámetros de configuración del pedimento
if (otrosDatosFormData) {
const hasParametersValue = otrosDatosFormData.es_embajada !== undefined ||
otrosDatosFormData.embajada_dta ||
otrosDatosFormData.regla_3_1_21_factores !== undefined ||
otrosDatosFormData.cambio_tarifa_anterior ||
otrosDatosFormData.agregar_entidad_federativa_proveedor !== undefined ||
otrosDatosFormData.calculo_valor_aduana_v2 !== undefined ||
otrosDatosFormData.calculo_2_decimales_valor_unitario !== undefined ||
otrosDatosFormData.calcular_valor_aduana_base_partidas !== undefined ||
otrosDatosFormData.proveedor_nacional_modifico_dta !== undefined;
if (hasParametersValue) {
payload.pedimento_config_parameters = {
is_embassy: otrosDatosFormData.es_embajada ? 1 : 0,
embassy_dta: otrosDatosFormData.embajada_dta || '0.00',
rule_3121_section_ii: otrosDatosFormData.regla_3_1_21_factores ? 1 : 0,
use_previous_tariff: otrosDatosFormData.cambio_tarifa_anterior ? 1 : 0,
use_payment_date_fi: null,
add_state_supplier_record_505: otrosDatosFormData.agregar_entidad_federativa_proveedor ? 1 : 0,
customs_value_calculation: otrosDatosFormData.calculo_valor_aduana_v2 ? 1 : 0,
two_decimals_unit_value: otrosDatosFormData.calculo_2_decimales_valor_unitario ? 1 : 0,
customs_value_per_item: otrosDatosFormData.calcular_valor_aduana_base_partidas ? 1 : 0,
is_national_supplier: otrosDatosFormData.proveedor_nacional_modifico_dta ? 1 : 0,
is_consolidated: null
};
}
}
// Config Updates - configuraciones de actualización de valores
if (otrosDatosFormData) {
const hasUpdatesValue = otrosDatosFormData.actualizar_iva !== undefined ||
otrosDatosFormData.actualizar_advalorem !== undefined ||
otrosDatosFormData.actualizar_cc !== undefined ||
otrosDatosFormData.actualizar_ieps !== undefined;
if (hasUpdatesValue) {
payload.pedimento_config_updates = {
update_vat: otrosDatosFormData.actualizar_iva ? 1 : 0,
update_advalorem: otrosDatosFormData.actualizar_advalorem ? 1 : 0,
update_cc: otrosDatosFormData.actualizar_cc ? 1 : 0,
update_ieps: otrosDatosFormData.actualizar_ieps ? 1 : 0
};
}
}
// Config Update Rectification - configuraciones de actualización en rectificación
if (otrosDatosFormData) {
const hasUpdateRectValue = otrosDatosFormData.actualizar_iva_rect !== undefined ||
otrosDatosFormData.actualizar_advalorem_rect !== undefined ||
otrosDatosFormData.actualizar_cc_rect !== undefined ||
otrosDatosFormData.actualizar_ieps_rect !== undefined ||
otrosDatosFormData.calcular_recargos_diferencias !== undefined;
if (hasUpdateRectValue) {
payload.pedimento_config_update_rectification = {
update_vat: otrosDatosFormData.actualizar_iva_rect ? 1 : 0,
update_advalorem: otrosDatosFormData.actualizar_advalorem_rect ? 1 : 0,
update_cc: otrosDatosFormData.actualizar_cc_rect ? 1 : 0,
update_ieps: otrosDatosFormData.actualizar_ieps_rect ? 1 : 0,
calculate_surcharge: otrosDatosFormData.calcular_recargos_diferencias ? 1 : 0
};
}
}
// Eliminar campos undefined para no enviarlos
Object.keys(payload).forEach(key => {
if (payload[key as keyof typeof payload] === undefined) {
@@ -319,7 +461,10 @@
let newPedimentoId = pedimentoId;
if (data.isCreate) {
// Determinar si es creación o actualización basándose en si tenemos un ID
const isCreating = !pedimentoId || data.isCreate;
if (isCreating) {
// Crear nuevo pedimento con todos sus sub-recursos
const response = await pedimentosApi.create(payload as CreatePedimentoData);
if (response.error) {
@@ -336,6 +481,9 @@
// Actualizar pedimento existente con todos sus sub-recursos
const response = await pedimentosApi.update(pedimentoId!, payload as UpdatePedimentoData);
if (response.error) throw new Error(response.error);
// Recargar los datos del pedimento desde el servidor
await invalidateAll();
}
success = true;
@@ -420,6 +568,7 @@
<GeneralTabForm
pedimento={data.pedimento}
bind:formData={generalFormData}
bind:identificadoresFormData={identificadoresFormData}
pedimentoCodes={data.pedimentoCodes || []}
customsSections={data.customsSections || []}
customsBrokers={data.customsBrokers || []}
@@ -461,29 +610,28 @@
bind:formData={bultosTransportesFormData}
/>
</Tabs.Content>
<!-- <Tabs.Content value="descargas">
<!-- <Tabs.Content value="descargas">
<DescargasTabForm
bind:formData={descargasFormData}
/>
</Tabs.Content> -->
<Tabs.Content value="contribuciones">
<Tabs.Content value="contribuciones">
<ContribucionesTabForm
bind:formData={contribucionesFormData}
/>
</Tabs.Content>
<Tabs.Content value="cuentas-compensacion">
<Tabs.Content value="cuentas-compensacion">
<CuentasCompensacionTabForm
bind:formData={cuentasCompensacionFormData}
/>
</Tabs.Content>
<Tabs.Content value="otros-datos">
<OtrosDatosTabForm bind:formData={otrosDatosFormData} />
</Tabs.Content>
<Tabs.Content value="digitalizacion">
<DigitalizacionTabForm bind:formData={digitalizacionFormData} />
</Tabs.Content>
</Tabs.Root>
<Tabs.Content value="otros-datos">
<OtrosDatosTabForm bind:formData={otrosDatosFormData} />
</Tabs.Content>
<Tabs.Content value="digitalizacion">
<DigitalizacionTabForm bind:formData={digitalizacionFormData} />
</Tabs.Content>
</Tabs.Root>
</div>
</div>
@@ -528,8 +676,8 @@
<Tabs.Trigger value="cuentas-compensacion" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm">
<Wallet size={14} />
<span>Cuentas/Comp.</span>
</Tabs.Trigger>
<Tabs.Trigger value="otros-datos" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm">
</Tabs.Trigger>
<Tabs.Trigger value="otros-datos" class="flex items-center gap-1.5 px-2.5 py-1.5 text-sm">
<FileStack size={14} />
<span>Otros</span>
</Tabs.Trigger>

View File

@@ -9,7 +9,8 @@
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
"moduleResolution": "bundler",
"allowArbitraryExtensions": true
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files