feaature/catalogo-empresa-mejoras

This commit is contained in:
2026-04-23 14:28:56 -06:00
parent 8dce23d624
commit 29c305cd2c
8 changed files with 566 additions and 179 deletions

View File

@@ -21,18 +21,19 @@ export interface CompanyAddress {
export interface CompanyCertification {
id?: number;
is_certified_company?: string | null;
is_certified_company?: boolean | null;
certified_company_registration?: string | null;
certified_company_start_date?: number | null;
certified_company_end_date?: number | null;
annex31_certification_date?: number | null;
annex31_certification_number?: string | null;
annex31_modality?: string | null;
annex31_company_type?: string | null;
annex31_renewal_date?: number | null;
annex31_final_certification_date?: number | null;
is_oea_company?: number | null;
neec_company?: number | null;
certified_company_start_date?: string | null;
certified_company_end_date?: string | null;
annex30_certification_date?: string | null;
annex30_certification_number?: string | null;
annex30_modality?: string | null;
annex30_company_type?: string | null;
annex30_renewal_date?: string | null;
annex30_final_certification_date?: string | null;
is_seciit_company?: boolean | null;
is_oea_company?: boolean | null;
neec_company?: boolean | null;
}
export interface CompanyDigitalCertificate {
@@ -107,6 +108,8 @@ export interface Company {
responsible_rfc?: string | null;
position?: string | null;
has_express_line?: boolean;
fiscal_deposit?: boolean;
generate_barcodes_with_fiel?: boolean;
is_service_company?: boolean;
order_format_type?: string | null;
ctpat_svi?: string | null;
@@ -140,18 +143,19 @@ export interface Company {
sql_language?: string | null;
balance_operation_mode?: string | null;
// Campos de certificación (CompanyCertification aplanado)
is_certified_company?: string | null;
is_certified_company?: boolean | null;
certified_company_registration?: string | null;
certified_company_start_date?: number | null;
certified_company_end_date?: number | null;
annex31_certification_date?: number | null;
annex31_certification_number?: string | null;
annex31_modality?: string | null;
annex31_company_type?: string | null;
annex31_renewal_date?: number | null;
annex31_final_certification_date?: number | null;
is_oea_company?: number | null;
neec_company?: number | null;
certified_company_start_date?: string | null;
certified_company_end_date?: string | null;
annex30_certification_date?: string | null;
annex30_certification_number?: string | null;
annex30_modality?: string | null;
annex30_company_type?: string | null;
annex30_renewal_date?: string | null;
annex30_final_certification_date?: string | null;
is_seciit_company?: boolean | null;
is_oea_company?: boolean | null;
neec_company?: boolean | null;
// Campos de dirección principal (CompanyAddress - main)
main_street?: string | null;
main_exterior_number?: string | null;
@@ -270,6 +274,8 @@ export interface CompanyCreate {
responsible_rfc?: string | null;
position?: string | null;
has_express_line?: boolean;
fiscal_deposit?: boolean;
generate_barcodes_with_fiel?: boolean;
is_service_company?: boolean;
order_format_type?: string | null;
ctpat_svi?: string | null;
@@ -323,18 +329,19 @@ export interface CompanyCreate {
sql_language?: string | null;
balance_operation_mode?: string | null;
// Campos de certificación
is_certified_company?: string | null;
is_certified_company?: boolean | null;
certified_company_registration?: string | null;
certified_company_start_date?: number | null;
certified_company_end_date?: number | null;
annex31_certification_date?: number | null;
annex31_certification_number?: string | null;
annex31_modality?: string | null;
annex31_company_type?: string | null;
annex31_renewal_date?: number | null;
annex31_final_certification_date?: number | null;
is_oea_company?: number | null;
neec_company?: number | null;
certified_company_start_date?: string | null;
certified_company_end_date?: string | null;
annex30_certification_date?: string | null;
annex30_certification_number?: string | null;
annex30_modality?: string | null;
annex30_company_type?: string | null;
annex30_renewal_date?: string | null;
annex30_final_certification_date?: string | null;
is_seciit_company?: boolean | null;
is_oea_company?: boolean | null;
neec_company?: boolean | null;
// Campos de dirección principal
main_street?: string | null;
main_exterior_number?: string | null;

View File

@@ -0,0 +1,57 @@
/**
* Utility for date formatting and conversion.
* Canonical API format: DD/MM/YYYY
* Native input[type="date"] format: YYYY-MM-DD
*/
/**
* Converts DD/MM/YYYY or YYYYMMDD to YYYY-MM-DD for native date input.
*/
export function toInputDate(dateStr: string | number | null | undefined): string {
if (!dateStr) return '';
const str = String(dateStr);
if (/^\d{8}$/.test(str)) {
const y = str.substring(0, 4);
const m = str.substring(4, 6);
const d = str.substring(6, 8);
return `${y}-${m}-${d}`;
}
if (/^\d{2}\/\d{2}\/\d{4}$/.test(str)) {
const [d, m, y] = str.split('/');
return `${y}-${m}-${d}`;
}
if (/^\d{4}-\d{2}-\d{2}$/.test(str)) {
return str;
}
return '';
}
/**
* Converts YYYY-MM-DD or YYYYMMDD to DD/MM/YYYY for API.
*/
export function toDbDate(dateStr: string | null | undefined): string | null {
if (!dateStr) return null;
if (/^\d{2}\/\d{2}\/\d{4}$/.test(dateStr)) {
return dateStr;
}
if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
const [y, m, d] = dateStr.split('-');
return `${d}/${m}/${y}`;
}
if (/^\d{8}$/.test(dateStr)) {
const y = dateStr.substring(0, 4);
const m = dateStr.substring(4, 6);
const d = dateStr.substring(6, 8);
return `${d}/${m}/${y}`;
}
return null;
}

View File

@@ -19,6 +19,7 @@
} from '$lib/api/dashboard/a76/general_catalogs/company';
import { companyStore } from '$lib/stores/company.svelte';
import { getBackendAssetUrl, getFileDisplayName } from '$lib/utils';
import { toDbDate, toInputDate } from '$lib/utils/date';
import {
ArrowLeft,
LoaderCircle,
@@ -86,6 +87,8 @@
position: '',
manufacturer_id: '',
has_express_line: false,
fiscal_deposit: false,
generate_barcodes_with_fiel: false,
is_service_company: false,
order_format_type: '',
ctpat_svi: '',
@@ -103,18 +106,19 @@
sector2: '',
sector3: '',
// Certificaciones (CompanyCertification)
is_certified_company: '',
is_certified_company: false,
certified_company_registration: '',
certified_company_start_date: 0,
certified_company_end_date: 0,
annex31_certification_date: 0,
annex31_certification_number: '',
annex31_modality: '',
annex31_company_type: '',
annex31_renewal_date: 0,
annex31_final_certification_date: 0,
is_oea_company: 0,
neec_company: 0,
certified_company_start_date: '',
certified_company_end_date: '',
annex30_certification_date: '',
annex30_certification_number: '',
annex30_modality: '',
annex30_company_type: '',
annex30_renewal_date: '',
annex30_final_certification_date: '',
is_seciit_company: false,
is_oea_company: false,
neec_company: false,
// Dirección Principal
main_street: '',
main_exterior_number: '',
@@ -255,6 +259,8 @@
position: item.position || '',
manufacturer_id: item.manufacturer_id || '',
has_express_line: item.has_express_line || false,
fiscal_deposit: item.fiscal_deposit || false,
generate_barcodes_with_fiel: item.generate_barcodes_with_fiel || false,
is_service_company: item.is_service_company || false,
order_format_type: item.order_format_type || '',
ctpat_svi: item.ctpat_svi || '',
@@ -289,18 +295,19 @@
sql_language: item.sql_language || '',
balance_operation_mode: item.balance_operation_mode || '',
// Certificaciones
is_certified_company: item.is_certified_company || '',
is_certified_company: item.is_certified_company || false,
certified_company_registration: item.certified_company_registration || '',
certified_company_start_date: item.certified_company_start_date || 0,
certified_company_end_date: item.certified_company_end_date || 0,
annex31_certification_date: item.annex31_certification_date || 0,
annex31_certification_number: item.annex31_certification_number || '',
annex31_modality: item.annex31_modality || '',
annex31_company_type: item.annex31_company_type || '',
annex31_renewal_date: item.annex31_renewal_date || 0,
annex31_final_certification_date: item.annex31_final_certification_date || 0,
is_oea_company: item.is_oea_company || 0,
neec_company: item.neec_company || 0,
certified_company_start_date: toInputDate(item.certified_company_start_date),
certified_company_end_date: toInputDate(item.certified_company_end_date),
annex30_certification_date: toInputDate(item.annex30_certification_date),
annex30_certification_number: item.annex30_certification_number || '',
annex30_modality: item.annex30_modality || '',
annex30_company_type: item.annex30_company_type || '',
annex30_renewal_date: toInputDate(item.annex30_renewal_date),
annex30_final_certification_date: toInputDate(item.annex30_final_certification_date),
is_seciit_company: item.is_seciit_company || false,
is_oea_company: item.is_oea_company || false,
neec_company: item.neec_company || false,
// Direcciones - Principal
main_street: item.main_street || '',
main_exterior_number: item.main_exterior_number || '',
@@ -586,18 +593,19 @@
sql_language: clean(formData.sql_language),
balance_operation_mode: clean(formData.balance_operation_mode),
// Certificaciones
is_certified_company: clean(formData.is_certified_company),
is_certified_company: formData.is_certified_company,
certified_company_registration: clean(formData.certified_company_registration),
certified_company_start_date: Number(formData.certified_company_start_date) || 0,
certified_company_end_date: Number(formData.certified_company_end_date) || 0,
annex31_certification_date: Number(formData.annex31_certification_date) || 0,
annex31_certification_number: clean(formData.annex31_certification_number),
annex31_modality: clean(formData.annex31_modality),
annex31_company_type: clean(formData.annex31_company_type),
annex31_renewal_date: Number(formData.annex31_renewal_date) || 0,
annex31_final_certification_date: Number(formData.annex31_final_certification_date) || 0,
is_oea_company: Number(formData.is_oea_company) || 0,
neec_company: Number(formData.neec_company) || 0,
certified_company_start_date: toDbDate(formData.certified_company_start_date),
certified_company_end_date: toDbDate(formData.certified_company_end_date),
annex30_certification_date: toDbDate(formData.annex30_certification_date),
annex30_certification_number: clean(formData.annex30_certification_number),
annex30_modality: clean(formData.annex30_modality),
annex30_company_type: clean(formData.annex30_company_type),
annex30_renewal_date: toDbDate(formData.annex30_renewal_date),
annex30_final_certification_date: toDbDate(formData.annex30_final_certification_date),
is_seciit_company: formData.is_seciit_company,
is_oea_company: formData.is_oea_company,
neec_company: formData.neec_company,
// Direcciones - Principal
main_street: clean(formData.main_street),
main_exterior_number: clean(formData.main_exterior_number),
@@ -687,6 +695,8 @@
cancel_key_exp: Number(formData.cancel_key_exp) || 0,
// Ensure optional booleans are passed correctly or default to false/null if needed
has_express_line: formData.has_express_line,
fiscal_deposit: formData.fiscal_deposit,
generate_barcodes_with_fiel: formData.generate_barcodes_with_fiel,
is_service_company: formData.is_service_company
};
@@ -815,7 +825,12 @@
</div>
<div class="grid gap-2">
<Label for="client_name">Nombre Cliente (Maquila)</Label>
<Input id="client_name" bind:value={formData.client_name} />
<Input
id="client_name"
bind:value={formData.client_name}
disabled={!formData.is_service_company}
placeholder={formData.is_service_company ? 'Para Shelters' : 'Disponible para Empresa de Servicios'}
/>
</div>
</Tabs.Content>
@@ -846,8 +861,16 @@
<Input id="broker_company" bind:value={formData.broker_company} />
</div>
<div class="grid gap-2">
<Label for="subassembly">Modo Sub-ensamble</Label>
<Input id="subassembly" bind:value={formData.subassembly_mode} />
<Label for="subassembly">Selector Para Submaquilar</Label>
<select
id="subassembly"
bind:value={formData.subassembly_mode}
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value="">Seleccionar</option>
<option value="SI">Si</option>
<option value="NO">No</option>
</select>
</div>
</div>
@@ -914,26 +937,15 @@
/>
</div>
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="flex items-center gap-3 rounded-lg border p-4">
<Switch id="express" bind:checked={formData.has_express_line} />
<Label for="express">Carril Exprés (OEA/NEEC)</Label>
</div>
<div class="flex items-center gap-3 rounded-lg border p-4">
<Switch
id="is_oea"
checked={formData.is_oea_company === 1}
onCheckedChange={(checked) => (formData.is_oea_company = checked ? 1 : 0)}
/>
<Label for="is_oea">Empresa OEA</Label>
</div>
<div class="flex items-center gap-3 rounded-lg border p-4">
<Switch
id="neec"
checked={formData.neec_company === 1}
onCheckedChange={(checked) => (formData.neec_company = checked ? 1 : 0)}
/>
<Label for="neec">Empresa NEEC</Label>
<div class="grid grid-cols-1 items-start gap-4">
<div class="grid gap-3 rounded-lg border p-4">
<label for="has_express_line" class="flex items-center justify-between gap-3">
<span class="text-sm font-medium">Tiene Linea Express</span>
<Switch
id="has_express_line"
bind:checked={formData.has_express_line}
/>
</label>
</div>
</div>
</div>
@@ -941,14 +953,38 @@
<div class="grid gap-4 rounded-lg border bg-muted/30 p-4">
<h3 class="font-semibold">Certificación General</h3>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="grid gap-2">
<Label for="cert_status">¿Es Empresa Certificada?</Label>
<Input
id="cert_status"
bind:value={formData.is_certified_company}
maxlength={1}
placeholder="S/N"
/>
<div class="grid gap-3 rounded-lg border p-4 md:col-span-2">
<label for="is_certified_company" class="flex items-center justify-between gap-3 rounded-md border border-border/60 bg-background/40 px-3 py-2">
<span class="text-sm font-medium">¿Es Empresa Certificada?</span>
<Switch
id="is_certified_company"
bind:checked={formData.is_certified_company}
/>
</label>
<Label>Tipos de Certificacion</Label>
<div class="grid grid-cols-1 gap-3 md:grid-cols-3">
<label class="flex items-center justify-between gap-3 rounded-md border border-border/60 bg-background/40 px-3 py-2 text-sm">
<span>SECIIT</span>
<Switch
id="seciit"
bind:checked={formData.is_seciit_company}
/>
</label>
<label class="flex items-center justify-between gap-3 rounded-md border border-border/60 bg-background/40 px-3 py-2 text-sm">
<span>OEA</span>
<Switch
id="oea"
bind:checked={formData.is_oea_company}
/>
</label>
<label class="flex items-center justify-between gap-3 rounded-md border border-border/60 bg-background/40 px-3 py-2 text-sm">
<span>RFE / NEEC</span>
<Switch
id="neec"
bind:checked={formData.neec_company}
/>
</label>
</div>
</div>
<div class="grid gap-2">
<Label for="cert_reg">Registro de Empresa Certificada</Label>
@@ -962,75 +998,85 @@
<Label for="cert_start">Fecha Inicio Certificación</Label>
<Input
id="cert_start"
type="number"
type="date"
bind:value={formData.certified_company_start_date}
placeholder="YYYYMMDD"
placeholder="DD/MM/YYYY"
/>
</div>
<div class="grid gap-2">
<Label for="cert_end">Fecha Fin Certificación</Label>
<Input
id="cert_end"
type="number"
type="date"
bind:value={formData.certified_company_end_date}
placeholder="YYYYMMDD"
placeholder="DD/MM/YYYY"
/>
</div>
</div>
</div>
<div class="grid gap-4 rounded-lg border bg-muted/30 p-4">
<h3 class="font-semibold">Anexo 31</h3>
<h3 class="font-semibold">Anexo 30</h3>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="grid gap-2">
<Label for="a31_cert_date">Fecha Certificación Anexo 31</Label>
<Label for="a31_cert_date">Fecha Certificación Anexo 30</Label>
<Input
id="a31_cert_date"
type="number"
bind:value={formData.annex31_certification_date}
placeholder="YYYYMMDD"
type="date"
bind:value={formData.annex30_certification_date}
placeholder="DD/MM/YYYY"
/>
</div>
<div class="grid gap-2">
<Label for="a31_cert_num">Número Certificación Anexo 31</Label>
<Label for="a31_cert_num">Número Certificación Anexo 30</Label>
<Input
id="a31_cert_num"
bind:value={formData.annex31_certification_number}
bind:value={formData.annex30_certification_number}
maxlength={50}
/>
</div>
<div class="grid gap-2">
<Label for="a31_modality">Modalidad Anexo 31</Label>
<Input
<Label for="a31_modality">Modalidad Anexo 30</Label>
<select
id="a31_modality"
bind:value={formData.annex31_modality}
maxlength={50}
/>
bind:value={formData.annex30_modality}
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value="">Seleccionar</option>
<option value="A">A</option>
<option value="AA">AA</option>
<option value="AAA">AAA</option>
</select>
</div>
<div class="grid gap-2">
<Label for="a31_type">Tipo de Empresa Anexo 31</Label>
<Input
<Label for="a31_type">Tipo de Empresa Anexo 30</Label>
<select
id="a31_type"
bind:value={formData.annex31_company_type}
maxlength={50}
/>
bind:value={formData.annex30_company_type}
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value="">Seleccionar</option>
<option value="NO_CERTIFICADA">No Certificada</option>
<option value="CERTIFICADA">Certificada</option>
<option value="BAJO_FIANZA">Bajo Fianza</option>
</select>
</div>
<div class="grid gap-2">
<Label for="a31_renewal">Fecha Renovación Anexo 31</Label>
<Label for="a31_renewal">Fecha de Renovacion A31</Label>
<Input
id="a31_renewal"
type="number"
bind:value={formData.annex31_renewal_date}
placeholder="YYYYMMDD"
type="date"
bind:value={formData.annex30_renewal_date}
placeholder="DD/MM/YYYY"
/>
</div>
<div class="grid gap-2">
<Label for="a31_final">Fecha Final Certificación Anexo 31</Label>
<Label for="a31_final">Fecha de Cancelación Anexo 30</Label>
<Input
id="a31_final"
type="number"
bind:value={formData.annex31_final_certification_date}
placeholder="YYYYMMDD"
type="date"
bind:value={formData.annex30_final_certification_date}
placeholder="DD/MM/YYYY"
/>
</div>
</div>
@@ -1373,10 +1419,32 @@
<div class="grid gap-4 rounded-lg border bg-muted/30 p-4">
<h3 class="font-semibold">Configuración General</h3>
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
<div class="flex items-center gap-3 rounded-lg border p-4">
<Switch id="service" bind:checked={formData.is_service_company} />
<Label for="service">Es Empresa de Servicios</Label>
<div class="grid gap-2">
<Label for="is_service_company">Empresa de Servicios?</Label>
<select
id="is_service_company"
bind:value={formData.is_service_company}
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value={true}>Sí</option>
<option value={false}>No</option>
</select>
</div>
<div class="grid gap-2">
<Label for="fiscal_deposit">Deposito Fiscal</Label>
<select
id="fiscal_deposit"
bind:value={formData.fiscal_deposit}
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value={true}>Sí</option>
<option value={false}>No</option>
</select>
</div>
<label class="flex items-center gap-3 rounded-lg border p-4">
<Switch id="generate_fiel_barcodes" bind:checked={formData.generate_barcodes_with_fiel} />
<Label for="generate_fiel_barcodes">Generar Codigos de barras con FIEL</Label>
</label>
<div class="flex items-center gap-3 rounded-lg border p-4">
<Switch id="seventh" bind:checked={formData.seventh_amendment} />
<Label for="seventh">Séptima Enmienda</Label>
@@ -1482,8 +1550,16 @@
<Input id="man_id" bind:value={formData.manufacturer_id} />
</div>
<div class="grid gap-2">
<Label for="order_format">Formato de Pedido</Label>
<Input id="order_format" bind:value={formData.order_format_type} />
<Label for="order_format">Formato Interfase Pedimento</Label>
<select
id="order_format"
bind:value={formData.order_format_type}
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value="">Seleccionar formato</option>
<option value="INTERFASE_PEDIMENTO">Interfase Pedimento</option>
<option value="ESTANDAR">Estandar</option>
</select>
</div>
<div class="grid gap-2">
<Label for="inter_db">Base de Datos Intermedia</Label>
@@ -1513,15 +1589,29 @@
</div>
<div class="grid gap-2">
<Label for="sql_language">Lenguaje SQL</Label>
<Input id="sql_language" bind:value={formData.sql_language} maxlength={19} />
<select
id="sql_language"
bind:value={formData.sql_language}
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value="">Seleccionar lenguaje</option>
<option value="SQLSERVER">SQL Server</option>
<option value="POSTGRESQL">PostgreSQL</option>
<option value="MYSQL">MySQL</option>
</select>
</div>
<div class="grid gap-2">
<Label for="balance_mode">Modo de Operación de Balance</Label>
<Input
<select
id="balance_mode"
bind:value={formData.balance_operation_mode}
maxlength={50}
/>
class="flex h-9 w-full rounded-md border border-input bg-card px-3 py-1 text-sm shadow-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
>
<option value="">Seleccionar modo</option>
<option value="PEDIMENTO">Por Pedimento</option>
<option value="FACTURA">Por Factura</option>
<option value="PARTIDA">Por Partida</option>
</select>
</div>
</div>
</div>