feat: add pedimento fields and selection functionality to invoice forms
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '$lib/components/ui/input';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import * as Select from '$lib/components/ui/select';
|
||||
import * as Select from '$lib/components/ui/select';
|
||||
import * as RadioGroup from '$lib/components/ui/radio-group';
|
||||
import type { Invoice } from '$lib/api/dashboard/a76/invoices';
|
||||
import type { InvoiceType } from '$lib/api/dashboard/refrence_data/invoice_types';
|
||||
import type { CustomsBroker } from '$lib/api/dashboard/a76/customs-brokers';
|
||||
@@ -51,6 +52,12 @@
|
||||
// Extra fields
|
||||
operation_type: operationType,
|
||||
|
||||
// RANGO DE FECHAS fields
|
||||
fecha_pedimento_del: '',
|
||||
fecha_pedimento_al: '',
|
||||
clave_pedimento: '',
|
||||
regimen_pedimento: '',
|
||||
|
||||
// LEFT fields
|
||||
provider_header: invoice.compliance_mx?.provider_header || '',
|
||||
provider_id: invoice.compliance_mx?.provider_id || null,
|
||||
@@ -63,6 +70,7 @@
|
||||
|
||||
// RIGHT fields
|
||||
currency_type: invoice.financials?.currency_type || '',
|
||||
currency_mode: 'extranjera', // extranjera, nacional, captura
|
||||
weight_type: '',
|
||||
iva_factor: invoice.financials?.iva_factor || null,
|
||||
carrier_id: invoice.logistics?.[0]?.carrier_id || null,
|
||||
@@ -72,6 +80,7 @@
|
||||
transport_num: invoice.logistics?.[0]?.vehicle_num || '',
|
||||
aduana: invoice.compliance_mx?.aduana || '',
|
||||
invoice_type: invoice.invoice_type || '',
|
||||
clave_regimen_aduanero: '',
|
||||
};
|
||||
} else {
|
||||
// Creando una nueva factura
|
||||
@@ -87,6 +96,12 @@
|
||||
// Extra fields
|
||||
operation_type: defaultOperationType ?? null,
|
||||
|
||||
// RANGO DE FECHAS fields
|
||||
fecha_pedimento_del: '',
|
||||
fecha_pedimento_al: '',
|
||||
clave_pedimento: '',
|
||||
regimen_pedimento: '',
|
||||
|
||||
// LEFT fields
|
||||
provider_header: '',
|
||||
provider_id: null,
|
||||
@@ -99,6 +114,7 @@
|
||||
|
||||
// RIGHT fields
|
||||
currency_type: '',
|
||||
currency_mode: 'extranjera', // extranjera, nacional, captura
|
||||
weight_type: '',
|
||||
iva_factor: null,
|
||||
carrier_id: null,
|
||||
@@ -108,8 +124,14 @@
|
||||
transport_num: '',
|
||||
aduana: '',
|
||||
invoice_type: defaultInvoiceType ?? '',
|
||||
clave_regimen_aduanero: '',
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Si formData ya existe, asegurar que tiene currency_mode
|
||||
if (formData.currency_mode === undefined) {
|
||||
formData.currency_mode = 'extranjera';
|
||||
}
|
||||
}
|
||||
|
||||
// Opciones de tipo de peso
|
||||
@@ -154,14 +176,33 @@
|
||||
const allClientsProviders = [...clients, ...providers];
|
||||
</script>
|
||||
|
||||
<!-- Top fields moved to shared component -->
|
||||
|
||||
<!-- Layout de 2 columnas compacto -->
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<!-- Columna Izquierda: Clientes - Proveedores - Agente Aduanal -->
|
||||
<div class="border rounded-md p-3 space-y-3">
|
||||
<div class="space-y-2">
|
||||
<h4 class="text-xs font-semibold text-muted-foreground uppercase">Datos del pedimento</h4>
|
||||
<div class="grid grid-cols-4 gap-3 text-xs">
|
||||
<div>
|
||||
<span class="text-muted-foreground">Fecha del:</span>
|
||||
<p class="font-medium">{formData.fecha_pedimento_del || '-'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-muted-foreground">Fecha al:</span>
|
||||
<p class="font-medium">{formData.fecha_pedimento_al || '-'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-muted-foreground">Clave:</span>
|
||||
<p class="font-medium">{formData.clave_pedimento || '-'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-muted-foreground">Régimen:</span>
|
||||
<p class="font-medium">{formData.regimen_pedimento || '-'}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="text-xs font-semibold text-muted-foreground uppercase">Clientes - Proveedores - Agente Aduanal</h4>
|
||||
|
||||
<div class="space-y-1.5">
|
||||
<Label for="provider_id" class="text-xs">Proveedor:</Label>
|
||||
<Select.Root
|
||||
@@ -367,6 +408,24 @@
|
||||
<div class="border rounded-md p-3 space-y-2">
|
||||
<h4 class="text-xs font-semibold text-muted-foreground uppercase">Tipo de Moneda - Pesos Netos y Brutos</h4>
|
||||
|
||||
<!-- Radio buttons para tipo de moneda -->
|
||||
<div class="space-y-1.5">
|
||||
<RadioGroup.Root bind:value={formData.currency_mode} class="flex gap-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroup.Item value="extranjera" id="currency-extranjera" class="h-4 w-4" />
|
||||
<Label for="currency-extranjera" class="text-xs font-normal cursor-pointer">Extranjera (Dlls)</Label>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroup.Item value="nacional" id="currency-nacional" class="h-4 w-4" />
|
||||
<Label for="currency-nacional" class="text-xs font-normal cursor-pointer">Nacional (Pesos)</Label>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroup.Item value="captura" id="currency-captura" class="h-4 w-4" />
|
||||
<Label for="currency-captura" class="text-xs font-normal cursor-pointer">De Captura</Label>
|
||||
</div>
|
||||
</RadioGroup.Root>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<div class="space-y-1.5">
|
||||
<Label for="currency_type" class="text-xs">Moneda:</Label>
|
||||
@@ -505,6 +564,11 @@
|
||||
<Label for="aduana" class="text-xs">Aduana y Sección de Despacho:</Label>
|
||||
<Input id="aduana" bind:value={formData.aduana} class="h-7 text-xs" />
|
||||
</div>
|
||||
|
||||
<div class="space-y-1.5">
|
||||
<Label for="clave_regimen_aduanero" class="text-xs">Clave de Régimen Aduanero:</Label>
|
||||
<Input id="clave_regimen_aduanero" bind:value={formData.clave_regimen_aduanero} class="h-7 text-xs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,21 +5,41 @@
|
||||
import { Switch } from '$lib/components/ui/switch';
|
||||
import type { Invoice } from '$lib/api/dashboard/a76/invoices';
|
||||
import type { InvoiceType } from '$lib/api/dashboard/refrence_data/invoice_types';
|
||||
import type { Pedimento } from '$lib/api/dashboard/a76/pedimentos';
|
||||
|
||||
let {
|
||||
invoice,
|
||||
formData = $bindable(),
|
||||
invoiceTypes = [],
|
||||
pedimentos = [],
|
||||
defaultOperationType = undefined,
|
||||
defaultInvoiceType = undefined,
|
||||
}: {
|
||||
invoice: Invoice | null;
|
||||
formData?: any;
|
||||
invoiceTypes?: InvoiceType[];
|
||||
pedimentos?: Pedimento[];
|
||||
defaultOperationType?: number | null;
|
||||
defaultInvoiceType?: string | null;
|
||||
} = $props();
|
||||
|
||||
function handlePedimentoChange(pedimentoId: string) {
|
||||
if (!pedimentoId) return;
|
||||
|
||||
const selectedPedimento = pedimentos.find(p => p.id === parseInt(pedimentoId));
|
||||
if (!selectedPedimento) return;
|
||||
|
||||
// Actualizar los campos del pedimento en formData
|
||||
formData.fecha_pedimento_del = selectedPedimento.pedimento_dates?.start_date || '';
|
||||
formData.fecha_pedimento_al = selectedPedimento.pedimento_dates?.end_date || '';
|
||||
formData.clave_pedimento = selectedPedimento.pedimento_code || '';
|
||||
formData.regimen_pedimento = selectedPedimento.regime || '';
|
||||
|
||||
// Construir el número de pedimento completo
|
||||
const pedimentoNumber = `${selectedPedimento.year || ''}-${selectedPedimento.customs_office || ''}-${selectedPedimento.license || ''}-${selectedPedimento.pedimento_number || ''}`.replace(/^-+|-+$/g, '');
|
||||
formData.pedimento = pedimentoNumber;
|
||||
}
|
||||
|
||||
if (!formData) {
|
||||
let operationType: number | null = null;
|
||||
if (invoice?.operation_type) {
|
||||
@@ -30,6 +50,7 @@
|
||||
|
||||
formData = {
|
||||
is_pedimento_pending: false,
|
||||
pedimento_id: null,
|
||||
pedimento: invoice?.compliance_mx?.pedimento || '',
|
||||
remesa: invoice?.compliance_mx?.remesa || '',
|
||||
invoice_number: invoice?.invoice_number || '',
|
||||
@@ -37,6 +58,11 @@
|
||||
emission_date: '',
|
||||
operation_type: operationType,
|
||||
invoice_type: invoice?.invoice_type || (defaultInvoiceType ?? ''),
|
||||
// Campos del pedimento (se llenarán al seleccionar un pedimento)
|
||||
fecha_pedimento_del: '',
|
||||
fecha_pedimento_al: '',
|
||||
clave_pedimento: '',
|
||||
regimen_pedimento: '',
|
||||
};
|
||||
}
|
||||
</script>
|
||||
@@ -103,7 +129,29 @@
|
||||
</div>
|
||||
<div class="col-span-2 space-y-1">
|
||||
<Label for="pedimento" class="text-xs">Pedimento</Label>
|
||||
<Input id="pedimento" bind:value={formData.pedimento} class="h-8 text-sm" />
|
||||
<Select.Root
|
||||
type="single"
|
||||
value={formData.pedimento_id ? String(formData.pedimento_id) : ''}
|
||||
onValueChange={(v) => {
|
||||
formData.pedimento_id = v ? parseInt(v) : null;
|
||||
if (v) {
|
||||
handlePedimentoChange(v);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Select.Trigger id="pedimento" class="h-8 text-sm">
|
||||
<span class="truncate">
|
||||
{formData.pedimento || 'Selecciona pedimento...'}
|
||||
</span>
|
||||
</Select.Trigger>
|
||||
<Select.Content class="max-h-[300px]">
|
||||
{#each pedimentos as pedimento}
|
||||
<Select.Item value={String(pedimento.id)}>
|
||||
{pedimento.year}-{pedimento.customs_office}-{pedimento.license}-{pedimento.pedimento_number}
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</div>
|
||||
|
||||
<div class="col-span-1 space-y-1">
|
||||
|
||||
@@ -95,6 +95,13 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
fetch
|
||||
);
|
||||
|
||||
const pedimentosPromise = authenticatedFetch(
|
||||
`v1/a76/pedimentos?company_id=${companyId}&page=1&page_size=100`,
|
||||
{},
|
||||
cookies,
|
||||
fetch
|
||||
);
|
||||
|
||||
// Si el ID es "new", es una creación
|
||||
if (params.id === 'new') {
|
||||
const [
|
||||
@@ -106,7 +113,8 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
transportTypesResponse,
|
||||
sealsResponse,
|
||||
incotermsResponse,
|
||||
enclosureResponse
|
||||
enclosureResponse,
|
||||
pedimentosResponse
|
||||
] = await Promise.all([
|
||||
invoiceTypesPromise,
|
||||
customsBrokersPromise,
|
||||
@@ -116,7 +124,8 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
transportTypesPromise,
|
||||
sealsPromise,
|
||||
incotermsPromise,
|
||||
enclosurePromise
|
||||
enclosurePromise,
|
||||
pedimentosPromise
|
||||
]);
|
||||
|
||||
const invoiceTypes = invoiceTypesResponse.ok ? await invoiceTypesResponse.json() : { items: [] };
|
||||
@@ -128,6 +137,7 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
const seals = sealsResponse.ok ? await sealsResponse.json() : { items: [] };
|
||||
const incoterms = incotermsResponse.ok ? await incotermsResponse.json() : { items: [] };
|
||||
const enclosure = enclosureResponse.ok ? await enclosureResponse.json() : { items: [] };
|
||||
const pedimentos = pedimentosResponse.ok ? await pedimentosResponse.json() : { items: [] };
|
||||
|
||||
return {
|
||||
invoice: null,
|
||||
@@ -142,6 +152,7 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
seals: seals.items || [],
|
||||
incoterms: incoterms.items || [],
|
||||
enclosure: enclosure.items || [],
|
||||
pedimentos: pedimentos.items || [],
|
||||
// Filtros desde query parameters para preselección
|
||||
filters: {
|
||||
operation_type: parsedOperationType,
|
||||
@@ -180,7 +191,8 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
transportTypesResponse,
|
||||
sealsResponse,
|
||||
incotermsResponse,
|
||||
enclosureResponse
|
||||
enclosureResponse,
|
||||
pedimentosResponse
|
||||
] = await Promise.all([
|
||||
invoiceTypesPromise,
|
||||
customsBrokersPromise,
|
||||
@@ -190,7 +202,8 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
transportTypesPromise,
|
||||
sealsPromise,
|
||||
incotermsPromise,
|
||||
enclosurePromise
|
||||
enclosurePromise,
|
||||
pedimentosPromise
|
||||
]);
|
||||
|
||||
const invoiceTypes = invoiceTypesResponse.ok ? await invoiceTypesResponse.json() : { items: [] };
|
||||
@@ -202,6 +215,7 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
const seals = sealsResponse.ok ? await sealsResponse.json() : { items: [] };
|
||||
const incoterms = incotermsResponse.ok ? await incotermsResponse.json() : { items: [] };
|
||||
const enclosure = enclosureResponse.ok ? await enclosureResponse.json() : { items: [] };
|
||||
const pedimentos = pedimentosResponse.ok ? await pedimentosResponse.json() : { items: [] };
|
||||
|
||||
return {
|
||||
invoice,
|
||||
@@ -216,6 +230,7 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => {
|
||||
seals: seals.items || [],
|
||||
incoterms: incoterms.items || [],
|
||||
enclosure: enclosure.items || [],
|
||||
pedimentos: pedimentos.items || [],
|
||||
// Filtros desde query parameters para preselección
|
||||
filters: {
|
||||
operation_type: parsedOperationType,
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
operation_type?: number | null;
|
||||
invoice_type?: string | null;
|
||||
};
|
||||
pedimentos?: any[];
|
||||
}
|
||||
|
||||
let { data }: { data: ExtendedPageData } = $props();
|
||||
@@ -573,6 +574,7 @@
|
||||
invoice={data.invoice}
|
||||
bind:formData={generalFormData}
|
||||
invoiceTypes={data.invoiceTypes || []}
|
||||
pedimentos={data.pedimentos || []}
|
||||
defaultOperationType={data.filters?.operation_type ?? undefined}
|
||||
defaultInvoiceType={data.filters?.invoice_type ?? undefined}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user