diff --git a/backend/api/v1/modules/a76/clients_and_providers/service.py b/backend/api/v1/modules/a76/clients_and_providers/service.py index 759cae59..417228ee 100644 --- a/backend/api/v1/modules/a76/clients_and_providers/service.py +++ b/backend/api/v1/modules/a76/clients_and_providers/service.py @@ -350,7 +350,6 @@ class ClientProviderService: ) if client_or_provider: - from .models import ClientOrProviderEnum query = query.filter( or_( ClientProvider.client_or_provider == client_or_provider, diff --git a/backend/api/v1/modules/a76/invoices/imports/temporary/validators/common.py b/backend/api/v1/modules/a76/invoices/imports/temporary/validators/common.py index 0440bf81..afba527a 100644 --- a/backend/api/v1/modules/a76/invoices/imports/temporary/validators/common.py +++ b/backend/api/v1/modules/a76/invoices/imports/temporary/validators/common.py @@ -12,6 +12,76 @@ from api.v1.modules.public.reference_data.currency_types.models import CurrencyT from api.v1.modules.public.reference_data.customs_sections.models import CustomsSection from ....models import TransportType, Currency, WeightUnit from core.exceptions import ErrorCollector +from typing import Dict, Any + + +def validate_required_fields_by_operation( + invoice_data: Dict[str, Any], + operation_type: str, + errors: ErrorCollector +) -> None: + """ + Valida campos obligatorios según tipo de operación. + Usar ANTES de guardar en BD. + """ + + # PROVEEDOR (SIEMPRE OBLIGATORIO - mensaje dinámico) + if not invoice_data.get('provider_id'): + # Mensaje dinámico según el header seleccionado + provider_labels = { + 'proveedor': 'Proveedor', + 'exportador': 'Exportador' + } + provider_header = invoice_data.get('provider_header') or 'proveedor' + field_label = provider_labels.get(provider_header, 'Proveedor') + + errors.add_error( + field="provider_id", + message=f"Debe seleccionar {field_label}", + solution=["Seleccione un proveedor de la lista desplegable"], + code="REQUIRED", + value=None + ) + + # VENDIDO A / CONSIGNADO A (SIEMPRE OBLIGATORIO - mensaje dinámico) + if not invoice_data.get('sold_to_id'): + # Mensaje dinámico según el header seleccionado + sold_to_labels = { + 'consignado_a': 'Consignado a', + 'vendido_a': 'Vendido a', + 'exportado_a': 'Exportado a', + 'importador': 'Importador' + } + sold_to_header = invoice_data.get('sold_to_header') or 'consignado_a' + field_label = sold_to_labels.get(sold_to_header, 'Cliente') + + errors.add_error( + field="sold_to_id", + message=f"Debe seleccionar {field_label}", + solution=["Seleccione una opción de la lista desplegable"], + code="REQUIRED", + value=None + ) + + # ENVIADO A (SIEMPRE OBLIGATORIO - mensaje fijo) + if not invoice_data.get('shipped_to_id'): + errors.add_error( + field="shipped_to_id", + message="Debe seleccionar el Destinatario", + solution=["Seleccione un destinatario de la lista desplegable"], + code="REQUIRED", + value=None + ) + + # AGENTE ADUANAL (OBLIGATORIO si hay pedimento) + if invoice_data.get('pedimento_id') and not invoice_data.get('customs_broker_id'): + errors.add_error( + field="customs_broker_id", + message="Debe seleccionar un Agente Aduanal", + solution=["Seleccione un agente aduanal de la lista desplegable"], + code="REQUIRED", + value=None + ) def validate_common( @@ -245,78 +315,87 @@ def validate_common( value=invoice.document_type, ) - provider_exists = ( - db.query(ClientProvider) - .filter( - ClientProvider.id == invoice.compliance_mx.provider_id, - ClientProvider.tenant_id == tenant_id, - ClientProvider.company_id == company_id, - ) - .first() - ) - if not provider_exists: - errors.add_error( - field="compliance_mx.provider_id", - message="El Proveedor no existe en el Catálogo de Clientes y Proveedores.", - solution=["Verifica el ID del Proveedor", "Revisa el catálogo"], - code="NOT_FOUND", - value=invoice.compliance_mx.provider_id, + # Validar proveedor solo si se proporciona + if invoice.compliance_mx.provider_id: + provider_exists = ( + db.query(ClientProvider) + .filter( + ClientProvider.id == invoice.compliance_mx.provider_id, + ClientProvider.tenant_id == tenant_id, + ClientProvider.company_id == company_id, + ) + .first() ) + if not provider_exists: + errors.add_error( + field="compliance_mx.provider_id", + message="El Proveedor no existe en el Catálogo de Clientes y Proveedores.", + solution=["Verifica el ID del Proveedor", "Revisa el catálogo"], + code="NOT_FOUND", + value=invoice.compliance_mx.provider_id, + ) - selled_to_exists = ( - db.query(ClientProvider) - .filter( - ClientProvider.id == invoice.compliance_mx.sold_to_id, - ClientProvider.tenant_id == tenant_id, - ClientProvider.company_id == company_id, - ) - .first() - ) - if not selled_to_exists: - errors.add_error( - field="compliance_mx.sold_to_id", - message="El Cliente no existe en el Catálogo de Clientes y Proveedores.", - solution=["Verifica el ID del Cliente", "Revisa el catálogo"], - code="NOT_FOUND", - value=invoice.compliance_mx.sold_to_id, + # Validar vendido a solo si se proporciona + if invoice.compliance_mx.sold_to_id: + selled_to_exists = ( + db.query(ClientProvider) + .filter( + ClientProvider.id == invoice.compliance_mx.sold_to_id, + ClientProvider.tenant_id == tenant_id, + ClientProvider.company_id == company_id, + ) + .first() ) + if not selled_to_exists: + errors.add_error( + field="compliance_mx.sold_to_id", + message="El Cliente no existe en el Catálogo de Clientes y Proveedores.", + solution=["Verifica el ID del Cliente", "Revisa el catálogo"], + code="NOT_FOUND", + value=invoice.compliance_mx.sold_to_id, + ) - shipped_to_exists = ( - db.query(ClientProvider) - .filter( - ClientProvider.id == invoice.compliance_mx.shipped_to_id, - ClientProvider.tenant_id == tenant_id, - ClientProvider.company_id == company_id, - ) - .first() - ) - if not shipped_to_exists: - errors.add_error( - field="compliance_mx.shipped_to_id", - message="El Destinatario no existe en el Catálogo de Clientes y Proveedores.", - solution=["Verifica el ID del Destinatario", "Revisa el catálogo"], - code="NOT_FOUND", - value=invoice.compliance_mx.shipped_to_id, + # Validar destinatario solo si se proporciona + if invoice.compliance_mx.shipped_to_id: + shipped_to_exists = ( + db.query(ClientProvider) + .filter( + ClientProvider.id == invoice.compliance_mx.shipped_to_id, + ClientProvider.tenant_id == tenant_id, + ClientProvider.company_id == company_id, + ) + .first() ) + if not shipped_to_exists: + errors.add_error( + field="compliance_mx.shipped_to_id", + message="El Destinatario no existe en el Catálogo de Clientes y Proveedores.", + solution=["Verifica el ID del Destinatario", "Revisa el catálogo"], + code="NOT_FOUND", + value=invoice.compliance_mx.shipped_to_id, + ) - customs_broker_exists = ( - db.query(CustomsBroker) - .filter( - CustomsBroker.id == invoice.compliance_mx.customs_broker_id, - CustomsBroker.tenant_id == tenant_id, - CustomsBroker.company_id == company_id, - ) - .first() - ) - if not customs_broker_exists: - errors.add_error( - field="compliance_mx.customs_broker_id", - message="El Agente Aduanal no existe en el Catálogo de Clientes y Proveedores.", - solution=["Verifica el ID del Agente Aduanal", "Revisa el catálogo"], - code="NOT_FOUND", - value=invoice.compliance_mx.customs_broker_id, + # Validar agente aduanal solo si se proporciona + if invoice.compliance_mx.customs_broker_id: + customs_broker_exists = ( + db.query(CustomsBroker) + .filter( + CustomsBroker.id == invoice.compliance_mx.customs_broker_id, + CustomsBroker.tenant_id == tenant_id, + CustomsBroker.company_id == company_id, + ) + .first() ) + if not customs_broker_exists: + errors.add_error( + field="compliance_mx.customs_broker_id", + message="El Agente Aduanal no existe en el Catálogo de Clientes y Proveedores.", + solution=["Verifica el ID del Agente Aduanal", "Revisa el catálogo"], + code="NOT_FOUND", + value=invoice.compliance_mx.customs_broker_id, + ) + # Validar transportista solo si se proporciona if invoice.logistics.carrier_id: carrier_exists = ( db.query(ClientProvider) diff --git a/backend/api/v1/modules/a76/invoices/imports/temporary/validators/create.py b/backend/api/v1/modules/a76/invoices/imports/temporary/validators/create.py index be6f6fc1..56800ff5 100644 --- a/backend/api/v1/modules/a76/invoices/imports/temporary/validators/create.py +++ b/backend/api/v1/modules/a76/invoices/imports/temporary/validators/create.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import Session from api.v1.modules.a76.general_catalogs.exchange_rate.models import ExchangeRate from core.exceptions import ErrorCollector from ....schemas import InvoiceHeaderCreate -from .common import validate_common +from .common import validate_common, validate_required_fields_by_operation def validate_create(db: Session, invoice: InvoiceHeaderCreate, tenant_id: int, company_id: int, errors: ErrorCollector) -> None: """ Valida la creación de una nueva factura de importe temporal """ @@ -21,22 +21,31 @@ def validate_create(db: Session, invoice: InvoiceHeaderCreate, tenant_id: int, c errors.add_required_error("invoice_number") if not invoice.invoice_date: - errors.add_required_error("invoice_date") - - if not invoice.compliance_mx.provider_id: - errors.add_required_error("compliance_mx.provider_id") + errors.add_required_error("invoice_date") - if not invoice.compliance_mx.sold_to_id: - errors.add_required_error("compliance_mx.sold_to_id") - - if not invoice.compliance_mx.shipped_to_id: - errors.add_required_error("compliance_mx.shipped_to_id") - - if not invoice.compliance_mx.customs_broker_id: - errors.add_required_error("compliance_mx.customs_broker_id") - if errors.has_errors(): - """Se retorna por que hay campos obligatiorios para las validaciones que tienen que ser llenados""" + """Se retorna porque hay campos obligatorios básicos que deben ser llenados""" + return + + # Validar campos obligatorios según tipo de operación + invoice_data = { + 'provider_header': invoice.compliance_mx.provider_header if invoice.compliance_mx else None, + 'provider_id': invoice.compliance_mx.provider_id if invoice.compliance_mx else None, + 'sold_to_id': invoice.compliance_mx.sold_to_id if invoice.compliance_mx else None, + 'sold_to_header': invoice.compliance_mx.sold_to_header if invoice.compliance_mx else None, + 'shipped_to_id': invoice.compliance_mx.shipped_to_id if invoice.compliance_mx else None, + 'customs_broker_id': invoice.compliance_mx.customs_broker_id if invoice.compliance_mx else None, + 'pedimento_id': invoice.compliance_mx.pedimento_id if invoice.compliance_mx else None, + } + + validate_required_fields_by_operation( + invoice_data=invoice_data, + operation_type=invoice.operation_type, + errors=errors + ) + + if errors.has_errors(): + """Se retorna porque hay campos obligatorios según el tipo de operación que deben ser llenados""" return validate_common(db, invoice, tenant_id, company_id, errors) diff --git a/backend/api/v1/modules/a76/invoices/imports/temporary/validators/update.py b/backend/api/v1/modules/a76/invoices/imports/temporary/validators/update.py index 58efd41a..da4cc970 100644 --- a/backend/api/v1/modules/a76/invoices/imports/temporary/validators/update.py +++ b/backend/api/v1/modules/a76/invoices/imports/temporary/validators/update.py @@ -5,6 +5,7 @@ from decimal import Decimal from core.exceptions import ErrorCollector from ....schemas import InvoiceHeaderUpdate from ....models import InvoiceHeader +from .common import validate_required_fields_by_operation # Helper function para limpiar strings (equivalente a Clip()) @@ -33,6 +34,22 @@ def validate_update( None (modifica invoice_data in-place y acumula errores en errors) """ + # Validar campos requeridos según el tipo de operación + invoice_dict = { + 'provider_id': invoice_data.compliance_mx.provider_id if invoice_data.compliance_mx else None, + 'sold_to_id': invoice_data.compliance_mx.sold_to_id if invoice_data.compliance_mx else None, + 'sold_to_header': invoice_data.compliance_mx.sold_to_header if invoice_data.compliance_mx else None, + 'shipped_to_id': invoice_data.compliance_mx.shipped_to_id if invoice_data.compliance_mx else None, + 'customs_broker_id': invoice_data.compliance_mx.customs_broker_id if invoice_data.compliance_mx else None, + 'pedimento_id': invoice_data.compliance_mx.pedimento_id if invoice_data.compliance_mx else None, + } + + validate_required_fields_by_operation( + invoice_data=invoice_dict, + operation_type=invoice_data.operation_type or 'IMP', + errors=errors + ) + # Primero ejecutar validaciones comunes # validate_common(invoice_data, errors) diff --git a/backend/api/v1/modules/a76/invoices/schemas.py b/backend/api/v1/modules/a76/invoices/schemas.py index af111dc8..a1324e69 100644 --- a/backend/api/v1/modules/a76/invoices/schemas.py +++ b/backend/api/v1/modules/a76/invoices/schemas.py @@ -113,17 +113,17 @@ class InvoiceComplianceMxBase(BaseModel): manifest_number: Optional[str] = Field( None, max_length=15, description="Manifest number" ) - provider_header: str = Field(None, max_length=20, description="Provider header") - provider_id: int = Field(None, description="Provider ID") - sold_to_header: str = Field(None, max_length=20, description="Sold to header") - sold_to_id: int = Field(None, description="Sold to ID") - shipped_to_header: str = Field(None, max_length=20, description="Shipped to header") - shipped_to_id: int = Field(None, description="Shipped to ID") + provider_header: Optional[str] = Field(None, max_length=20, description="Provider header") + provider_id: Optional[int] = Field(None, description="Provider ID") + sold_to_header: Optional[str] = Field(None, max_length=20, description="Sold to header") + sold_to_id: Optional[int] = Field(None, description="Sold to ID") + shipped_to_header: Optional[str] = Field(None, max_length=20, description="Shipped to header") + shipped_to_id: Optional[int] = Field(None, description="Shipped to ID") shipped_by_header: Optional[int] = Field( None, max_length=20, description="Shipped by header" ) shipped_by_id: Optional[int] = Field(None, description="Shipped by ID") - customs_broker_id: int = Field(None, description="Customs broker ID") + customs_broker_id: Optional[int] = Field(None, description="Customs broker ID") customs_broker_us_id: Optional[int] = Field( None, description="US customs broker ID" ) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 4225b510..49d51d59 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -91,6 +91,11 @@ }, "clients_and_providers": "Clients and Providers", "customs_brokers": "Customs Brokers", + "client_provider_type": { + "client_indicator": "C", + "provider_indicator": "P", + "both_indicator": "B" + }, "nav_user": { "profile": "Profile", "settings": "Settings", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index 2acc042b..48dcc061 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -91,6 +91,11 @@ }, "clients_and_providers": "Clientes y Proveedores", "customs_brokers": "Agentes Aduanales", + "client_provider_type": { + "client_indicator": "C", + "provider_indicator": "P", + "both_indicator": "A" + }, "nav_user": { "profile": "Perfil", "settings": "Configuración" diff --git a/frontend/src/lib/components/dashboard/invoices/edit/general-tab-form.svelte b/frontend/src/lib/components/dashboard/invoices/edit/general-tab-form.svelte index c7875be8..f9c18642 100644 --- a/frontend/src/lib/components/dashboard/invoices/edit/general-tab-form.svelte +++ b/frontend/src/lib/components/dashboard/invoices/edit/general-tab-form.svelte @@ -8,6 +8,12 @@ import type { CustomsBroker } from '$lib/api/dashboard/a76/customs-brokers'; import type { ClientProvider } from '$lib/api/dashboard/a76/clients-providers'; + interface CodePedimentoRegimen { + regimen_code: string; + type_code: string; + [key: string]: any; + } + let { invoice, formData = $bindable(), @@ -22,6 +28,7 @@ customsSections = [], codePedimentoRegimens = [], operationType = undefined, + defaultOperationType = undefined, exchangeRate = undefined }: { invoice: Invoice | null; @@ -37,8 +44,8 @@ drivers?: any[]; trailers?: any[]; customsSections?: any[]; - codePedimentoRegimens?: any[]; - defaultOperationType?: string | null; + codePedimentoRegimens?: CodePedimentoRegimen[]; + defaultOperationType?: string | number | null; defaultInvoiceType?: string | null; operationType?: number | null; exchangeRate?: number | null; @@ -176,25 +183,55 @@ ] ); - // Combinar clientes y proveedores para shipped_to - const allClientsProviders = [...clients, ...providers]; - - // Filtrar regímenes por tipo de operación (1='E' exp, 2='I' imp) y obtener valores únicos - const filteredRegimens = $derived.by(() => { - const typeCode = operationType === 1 ? 'E' : operationType === 2 ? 'I' : null; - const filtered = codePedimentoRegimens.filter(r => r.type_code === typeCode); - - // Obtener solo regímenes únicos por regimen_code + // Combinar clientes y proveedores para shipped_to, evitando duplicados de tipo "both" + const allClientsProviders = $derived.by(() => { const uniqueMap = new Map(); - filtered.forEach(r => { - if (r.regimen_code && !uniqueMap.has(r.regimen_code)) { - uniqueMap.set(r.regimen_code, r); + + // Agregar todos los clientes + clients.forEach(c => { + uniqueMap.set(c.id, { ...c, type: c.client_or_provider }); + }); + + // Agregar proveedores solo si no existen (evita duplicados de "both") + providers.forEach(p => { + if (!uniqueMap.has(p.id)) { + uniqueMap.set(p.id, { ...p, type: p.client_or_provider }); } }); return Array.from(uniqueMap.values()); }); + // Determinar tipo de código basado en operationType prop, defaultOperationType o invoice.operation_type + const typeCode = $derived( + operationType === 1 ? 'E' + : operationType === 2 ? 'I' + : defaultOperationType === 1 ? 'E' + : defaultOperationType === 2 ? 'I' + : defaultOperationType === 'exp' ? 'E' + : defaultOperationType === 'imp' ? 'I' + : invoice?.operation_type === 'exp' ? 'E' + : invoice?.operation_type === 'imp' ? 'I' + : null + ); + + // Filtrar regímenes por tipo de operación (1='E' exp, 2='I' imp) y obtener valores únicos + const filteredRegimens = $derived( + !codePedimentoRegimens || codePedimentoRegimens.length === 0 || !typeCode + ? [] + : Array.from( + codePedimentoRegimens + .filter(r => r.type_code === typeCode) + .reduce((map, r) => { + if (r.regimen_code && !map.has(r.regimen_code)) { + map.set(r.regimen_code, r); + } + return map; + }, new Map()) + .values() + ) + ); + // Efecto: Limpiar régimen si no existe en los regímenes filtrados al cambiar operation_type $effect(() => { if (formData.document_type && filteredRegimens.length > 0) { @@ -263,9 +300,11 @@ > - {formData.provider_id - ? providers.find(p => p.id === formData.provider_id)?.name || 'Selecciona...' - : 'Selecciona...'} + {#if formData.provider_id} + {providers.find(p => p.id === formData.provider_id)?.name || 'Selecciona...'} + {:else} + Selecciona... + {/if} @@ -309,9 +348,11 @@ > - {formData.sold_to_id - ? clients.find(c => c.id === formData.sold_to_id)?.name || 'Selecciona...' - : 'Selecciona...'} + {#if formData.sold_to_id} + {clients.find(c => c.id === formData.sold_to_id)?.name || 'Selecciona...'} + {:else} + Selecciona... + {/if} @@ -355,15 +396,17 @@ > - {formData.shipped_to_id - ? allClientsProviders.find(cp => cp.id === formData.shipped_to_id)?.name || 'Selecciona...' - : 'Selecciona...'} + {#if formData.shipped_to_id} + {allClientsProviders.find(cp => cp.id === formData.shipped_to_id)?.name || 'Selecciona...'} + {:else} + Selecciona... + {/if} {#each allClientsProviders as cp} - {cp.name} ({cp.type === 'client' ? 'C' : 'P'}) + {cp.name} {/each} diff --git a/frontend/src/lib/components/dashboard/invoices/edit/invoice-top-fields.svelte b/frontend/src/lib/components/dashboard/invoices/edit/invoice-top-fields.svelte index 47743eef..e3549f05 100644 --- a/frontend/src/lib/components/dashboard/invoices/edit/invoice-top-fields.svelte +++ b/frontend/src/lib/components/dashboard/invoices/edit/invoice-top-fields.svelte @@ -46,6 +46,16 @@ } }); + // Efecto para actualizar operation_type cuando cambia defaultOperationType + $effect(() => { + if (formData && defaultOperationType !== undefined && defaultOperationType !== null) { + // Si operation_type está vacío, null, o undefined, actualizarlo con defaultOperationType + if (!formData.operation_type) { + formData.operation_type = defaultOperationType; + } + } + }); + if (!formData) { let operationType: string | null = null; if (invoice?.operation_type) { @@ -69,6 +79,11 @@ clave_pedimento: '', regimen_pedimento: '', }; + } else { + // Si formData ya existe pero operation_type está vacío, usar defaultOperationType + if (!formData.operation_type && defaultOperationType !== undefined && defaultOperationType !== null) { + formData.operation_type = defaultOperationType; + } } diff --git a/frontend/src/lib/components/dashboard/invoices/edit/save-invoice.ts b/frontend/src/lib/components/dashboard/invoices/edit/save-invoice.ts index fbd26b64..e6f6b550 100644 --- a/frontend/src/lib/components/dashboard/invoices/edit/save-invoice.ts +++ b/frontend/src/lib/components/dashboard/invoices/edit/save-invoice.ts @@ -97,7 +97,7 @@ export async function saveInvoice(options: SaveInvoiceOptions): Promise void): ColumnDef[] { return renderSnippet(dateSnippet, { date: formatDate(row.original.pedimento_dates?.payment_date) }); } }, - /*{ - accessorKey: "pedimento_config_update_rectification.pediment_rectifed_18", - header: "Pedimento 18", - meta: { className: "hidden lg:table-cell" }, - cell: ({ row }) => { - const ped18Snippet = createRawSnippet<[{ value?: string | null }]>((getValue) => { - const { value } = getValue(); - return { - render: () => - `
${value || '-'}
` - }; - }); - return renderSnippet(ped18Snippet, { value: row.original.pedimento_config_update_rectification?.pediment_rectifed_18 }); - } - },*/ - /*{ - accessorKey: "pedimento_config_update_rectification.r1", - header: "Pedimento R1", - meta: { className: "hidden lg:table-cell" }, - cell: ({ row }) => { - const r1Snippet = createRawSnippet<[{ value?: string | null }]>((getValue) => { - const { value } = getValue(); - return { - render: () => - `
${value || '-'}
` - }; - }); - return renderSnippet(r1Snippet, { value: row.original.pedimento_config_update_rectification?.r1 }); - } - },*/ { accessorKey: "pedimento_validation.electronic_signature", header: "Acuse Electrónico", diff --git a/frontend/src/routes/dashboard/invoices/+page.svelte b/frontend/src/routes/dashboard/invoices/+page.svelte index 06086755..61138a73 100644 --- a/frontend/src/routes/dashboard/invoices/+page.svelte +++ b/frontend/src/routes/dashboard/invoices/+page.svelte @@ -427,11 +427,6 @@ function handleCreateClick() { const params = new URLSearchParams(window.location.search); - const operationType = params.get('operation_type'); - if (operationType) { - const operationTypeNumber = operationType === 'exp' ? 1 : 2; - params.set('operation_type', operationTypeNumber.toString()); - } const queryString = params.toString(); const url = queryString diff --git a/frontend/src/routes/dashboard/invoices/edit/[id]/+page.server.ts b/frontend/src/routes/dashboard/invoices/edit/[id]/+page.server.ts index 2ec29c64..78a4d101 100644 --- a/frontend/src/routes/dashboard/invoices/edit/[id]/+page.server.ts +++ b/frontend/src/routes/dashboard/invoices/edit/[id]/+page.server.ts @@ -20,13 +20,10 @@ export const load: PageServerLoad = async ({ params, cookies, fetch, url }) => { const operationTypeParam = url.searchParams.get('operation_type'); const invoiceTypeParam = url.searchParams.get('invoice_type'); - // Parsear operation_type de forma segura - let parsedOperationType: number | null = null; - if (operationTypeParam) { - const parsed = parseInt(operationTypeParam, 10); - if (!isNaN(parsed)) { - parsedOperationType = parsed; - } + // Validar que operation_type sea 'exp' o 'imp' + let parsedOperationType: string | null = null; + if (operationTypeParam && (operationTypeParam === 'exp' || operationTypeParam === 'imp')) { + parsedOperationType = operationTypeParam; } // Cargar datos de referencia necesarios diff --git a/frontend/src/routes/dashboard/invoices/edit/[id]/+page.svelte b/frontend/src/routes/dashboard/invoices/edit/[id]/+page.svelte index f00643cd..9567cb94 100644 --- a/frontend/src/routes/dashboard/invoices/edit/[id]/+page.svelte +++ b/frontend/src/routes/dashboard/invoices/edit/[id]/+page.svelte @@ -1,7 +1,8 @@