From 461f8ececbdfbe772d5f6405153dcd91052cda0d Mon Sep 17 00:00:00 2001 From: Galindo97 Date: Fri, 30 Jan 2026 18:03:41 -0600 Subject: [PATCH] fix: update invoice type filtering for repair imports and exports --- .../invoices/services/export_repair.py | 2 +- .../invoices/services/query_builders.py | 92 +++++---------- .../movements/invoices/services/repair.py | 8 +- .../dashboard/reports/invoices/+page.svelte | 106 ++++++++++++------ 4 files changed, 104 insertions(+), 104 deletions(-) diff --git a/backend/api/v1/modules/a76/reports/movements/invoices/services/export_repair.py b/backend/api/v1/modules/a76/reports/movements/invoices/services/export_repair.py index 51044161..13143ef6 100644 --- a/backend/api/v1/modules/a76/reports/movements/invoices/services/export_repair.py +++ b/backend/api/v1/modules/a76/reports/movements/invoices/services/export_repair.py @@ -337,7 +337,7 @@ class ExportRepairService: # ALL mode: bring all exports without filtering by specific invoice_type pass else: - where_conditions.append("ih.invoice_type IN ('EXREP', 'MATEXREP')") + where_conditions.append("ih.invoice_type = 'REPAR'") # Date range filter if filters.range_type.value == "FF": diff --git a/backend/api/v1/modules/a76/reports/movements/invoices/services/query_builders.py b/backend/api/v1/modules/a76/reports/movements/invoices/services/query_builders.py index d141392c..7e6417c1 100644 --- a/backend/api/v1/modules/a76/reports/movements/invoices/services/query_builders.py +++ b/backend/api/v1/modules/a76/reports/movements/invoices/services/query_builders.py @@ -41,26 +41,17 @@ class TemporaryImportQueries: '' AS C56, '' AS C57, '' AS C58, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_usd END), 0) AS total_me, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_mxn END), 0) AS total_mn + COALESCE(fin.value_me, 0) AS total_me, + COALESCE(fin.value_mn, 0) AS total_mn FROM a76.invoice_header ih LEFT JOIN a76.invoice_compliance_mx cmp ON cmp.invoice_id = ih.id LEFT JOIN a76.invoice_financials fin ON fin.invoice_id = ih.id LEFT JOIN a76.invoice_logistics log ON log.invoice_id = ih.id LEFT JOIN a76.pedimentos ped ON ped.id = cmp.pedimento_id LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = cmp.pedimento_r1 - LEFT JOIN a76.items i ON i.invoice_id = ih.id - LEFT JOIN a76.item_lines il ON il.item_id = i.id - LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id - LEFT JOIN a76.item_line_financials lf ON lf.item_line_id = il.id WHERE ih.operation_type = 'imp' AND ih.invoice_type = 'TEM' AND {where_str} - GROUP BY ih.id, ih.invoice_number, ped.pedimento_number, ped.pedimento_code, ped.regime, - log.entry_exit_date, log.delivery_date, log.payment_date, cmp.remesa, fin.exchange_rate, - cmp.provider_id, cmp.sold_to_id, cmp.customs_broker_id, cmp.aduana, ped_r1.pedimento_number, - cmp.edocument, cmp.vucem_operation_num, ih.emission_date, ih.capture_user, ih.who_updated, - log.carrier_id, log.transport_num, log.license_plate ORDER BY ih.invoice_number """ @@ -133,9 +124,8 @@ class TemporaryImportQueries: LEFT JOIN a76.invoice_financials fin ON fin.invoice_id = ih.id LEFT JOIN a76.invoice_logistics log ON log.invoice_id = ih.id LEFT JOIN a76.pedimentos ped ON ped.id = cmp.pedimento_id - LEFT JOIN a76.item_lines il ON il.item_id = ( - SELECT id FROM a76.items WHERE invoice_id = ih.id LIMIT 1 - ) + LEFT JOIN a76.items i ON i.invoice_id = ih.id + LEFT JOIN a76.item_lines il ON il.item_id = i.id LEFT JOIN a76.item_line_descriptions ld ON ld.item_line_id = il.id LEFT JOIN a76.item_line_quantities lq ON lq.item_line_id = il.id LEFT JOIN a76.item_line_financials lf ON lf.item_line_id = il.id @@ -146,6 +136,7 @@ class TemporaryImportQueries: WHERE ih.operation_type = 'imp' AND ih.invoice_type = 'TEM' AND {where_str} + ORDER BY ih.invoice_number, il.line_number """ @staticmethod @@ -219,27 +210,17 @@ class DefinitiveImportQueries: '' AS C57, '' AS C58, '' AS C59, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_usd END), 0) AS total_me, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_mxn END), 0) AS total_mn + COALESCE(fin.value_me, 0) AS total_me, + COALESCE(fin.value_mn, 0) AS total_mn FROM a76.invoice_header ih LEFT JOIN a76.invoice_compliance_mx cmp ON cmp.invoice_id = ih.id LEFT JOIN a76.invoice_financials fin ON fin.invoice_id = ih.id LEFT JOIN a76.invoice_logistics log ON log.invoice_id = ih.id LEFT JOIN a76.pedimentos ped ON ped.id = cmp.pedimento_id LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = cmp.pedimento_r1 - LEFT JOIN a76.items i ON i.invoice_id = ih.id - LEFT JOIN a76.item_lines il ON il.item_id = i.id - LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id - LEFT JOIN a76.item_line_financials lf ON lf.item_line_id = il.id WHERE ih.operation_type = 'imp' AND ih.invoice_type IN ('DEF', 'EXDEF', 'MATDE') AND {where_clause} - GROUP BY ih.id, ih.invoice_number, ped.pedimento_number, ped.pedimento_code, ped.regime, - log.entry_exit_date, log.delivery_date, log.payment_date, log.payment_receipt_num, - fin.exchange_rate, cmp.provider_id, cmp.sold_to_id, cmp.customs_broker_id, - ih.purchase_order, cmp.aduana, ped_r1.pedimento_number, cmp.edocument, - cmp.vucem_operation_num, ih.emission_date, ih.capture_user, ih.who_updated, - log.transport_id, log.transport_num ORDER BY ih.invoice_number """ @@ -355,7 +336,12 @@ class DefinitiveImportQueries: class RepairImportQueries: - """SQL queries for repair imports (PostgreSQL schema).""" + """SQL queries for repair imports (PostgreSQL schema). + + Note: Repair imports are NOT identified by invoice_type, but by having + cross-references (search_invoice field) that link them to export invoices. + These are regular import invoices (TEM, DEF, etc.) that were imported for repair. + """ @staticmethod def build_aggregated_query(db_name: str, where_str: str, discharge_clause: str = "") -> str: @@ -387,27 +373,23 @@ class RepairImportQueries: COALESCE(log.carrier_id, '') AS C44, COALESCE(log.transport_num, '') AS C45, COALESCE(ped.pedimento_code, '') AS C47, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_usd END), 0) AS total_me, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_mxn END), 0) AS total_mn + COALESCE(fin.value_me, 0) AS total_me, + COALESCE(fin.value_mn, 0) AS total_mn FROM a76.invoice_header ih LEFT JOIN a76.invoice_compliance_mx cmp ON cmp.invoice_id = ih.id LEFT JOIN a76.invoice_financials fin ON fin.invoice_id = ih.id LEFT JOIN a76.invoice_logistics log ON log.invoice_id = ih.id LEFT JOIN a76.pedimentos ped ON ped.id = cmp.pedimento_id LEFT JOIN a76.items i ON i.invoice_id = ih.id - LEFT JOIN a76.item_lines il ON il.item_id = i.id - LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id - LEFT JOIN a76.item_line_financials lf ON lf.item_line_id = il.id WHERE ih.operation_type = 'imp' - AND ih.invoice_type = 'REP' AND COALESCE(cmp.is_regime_change, false) = false + AND EXISTS ( + SELECT 1 FROM a76.item_lines il2 + INNER JOIN a24.fa_item_lines fil2 ON fil2.id = il2.id + WHERE il2.item_id = i.id AND fil2.search_invoice IS NOT NULL + ) {"AND " + where_str if where_str else ""} {discharge_filter} - GROUP BY ih.id, ih.invoice_number, ped.pedimento_number, ped.pedimento_code, ped.regime, - log.payment_date, cmp.remesa, fin.exchange_rate, cmp.provider_id, cmp.sold_to_id, - cmp.customs_broker_id, ih.purchase_order, ped.customs_office, cmp.edocument, - cmp.vucem_operation_num, ih.emission_date, ih.capture_user, ih.who_updated, - log.carrier_id, log.transport_num ORDER BY ih.invoice_number """ @@ -476,11 +458,12 @@ class RepairImportQueries: LEFT JOIN a76.item_line_quantities lq ON lq.item_line_id = il.id LEFT JOIN a76.item_line_financials lf ON lf.item_line_id = il.id LEFT JOIN a76.item_line_customs lc ON lc.item_line_id = il.id + LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id LEFT JOIN a76.parts prt ON prt.id = il.part_number LEFT JOIN a76.units_of_measure um ON um.id = il.unit_of_measure WHERE ih.operation_type = 'imp' - AND ih.invoice_type = 'REP' AND COALESCE(cmp.is_regime_change, false) = false + AND fil.search_invoice IS NOT NULL {"AND " + where_str if where_str else ""} {discharge_filter} ORDER BY ih.invoice_number, il.line_number @@ -562,24 +545,14 @@ class ExportQueries: COALESCE(ih.capture_user, '') AS C50, COALESCE(ih.who_updated, '') AS C51, COALESCE(log.transport_id || ' ' || log.transport_num, '') AS C53, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_usd END), 0) AS total_me, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_mxn END), 0) AS total_mn + COALESCE(fin.value_me, 0) AS total_me, + COALESCE(fin.value_mn, 0) AS total_mn FROM a76.invoice_header ih LEFT JOIN a76.invoice_compliance_mx cmp ON cmp.invoice_id = ih.id LEFT JOIN a76.invoice_financials fin ON fin.invoice_id = ih.id LEFT JOIN a76.invoice_logistics log ON log.invoice_id = ih.id LEFT JOIN a76.pedimentos ped ON ped.id = cmp.pedimento_id - LEFT JOIN a76.items i ON i.invoice_id = ih.id - LEFT JOIN a76.item_lines il ON il.item_id = i.id - LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id - LEFT JOIN a76.item_line_financials lf ON lf.item_line_id = il.id WHERE {where_clause} - GROUP BY ih.id, ih.invoice_number, ih.is_updated, ped.pedimento_number, ped.pedimento_code, ped.regime, - log.entry_exit_date, log.delivery_date, log.payment_date, log.payment_receipt_num, - cmp.provider_id, cmp.sold_to_id, cmp.customs_broker_id, ih.purchase_order, cmp.aduana, - ih.invoice_type, cmp.edocument, cmp.vucem_operation_num, fin.exchange_rate, - ih.emission_date, ih.capture_user, ih.who_updated, log.transport_id, log.transport_num, - ih.invoice_date ORDER BY ih.invoice_number """ @@ -736,25 +709,16 @@ class ExportRepairQueries: COALESCE(ih.who_updated, '') AS C51, COALESCE(log.carrier_id, '') AS C52, COALESCE(log.transport_id || ' ' || log.transport_num, '') AS C53, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_usd END), 0) AS total_me, - COALESCE(SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE lf.value_mxn END), 0) AS total_mn + COALESCE(fin.value_me, 0) AS total_me, + COALESCE(fin.value_mn, 0) AS total_mn FROM a76.invoice_header ih LEFT JOIN a76.invoice_compliance_mx cmp ON cmp.invoice_id = ih.id LEFT JOIN a76.invoice_financials fin ON fin.invoice_id = ih.id LEFT JOIN a76.invoice_logistics log ON log.invoice_id = ih.id LEFT JOIN a76.pedimentos ped ON ped.id = cmp.pedimento_id - LEFT JOIN a76.items i ON i.invoice_id = ih.id - LEFT JOIN a76.item_lines il ON il.item_id = i.id - LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id - LEFT JOIN a76.item_line_financials lf ON lf.item_line_id = il.id WHERE ih.operation_type = 'exp' - AND ih.invoice_type = 'REP' + AND ih.invoice_type = 'REPAR' {"AND " + where_str if where_str else ""} - GROUP BY ih.id, ih.invoice_number, ped.pedimento_number, ped.pedimento_code, ped.regime, - log.payment_date, cmp.remesa, fin.exchange_rate, cmp.provider_id, cmp.sold_to_id, - cmp.customs_broker_id, ih.purchase_order, ped.customs_office, ih.document_type, - cmp.edocument, cmp.vucem_operation_num, ih.invoice_date, ih.capture_user, - ih.who_updated, log.carrier_id, log.transport_id, log.transport_num ORDER BY ih.invoice_number """ @@ -837,7 +801,7 @@ class ExportRepairQueries: LEFT JOIN a76.parts prt ON prt.id = il.part_number LEFT JOIN a76.units_of_measure um ON um.id = il.unit_of_measure WHERE UPPER(ih.operation_type) IN ('EXP', 'TRA', 'RET') - AND UPPER(ih.invoice_type) IN ('DEF', 'REP', 'EXDEF', 'MATDE') + AND UPPER(ih.invoice_type) IN ('DEF', 'REPAR', 'EXDEF', 'MATDE') AND {where_str} ORDER BY ih.invoice_number, il.line_number """ diff --git a/backend/api/v1/modules/a76/reports/movements/invoices/services/repair.py b/backend/api/v1/modules/a76/reports/movements/invoices/services/repair.py index 0a4619ab..889d3185 100644 --- a/backend/api/v1/modules/a76/reports/movements/invoices/services/repair.py +++ b/backend/api/v1/modules/a76/reports/movements/invoices/services/repair.py @@ -331,12 +331,8 @@ class RepairImportService: # STRICT SEPARATION: Only imports for repair where_conditions.append("ih.operation_type = 'imp'") - # GOLDEN RULE: If coming from /all, only filter by operation_type - if hasattr(filters, 'discharge_filter') and filters.discharge_filter == 'ALL': - # ALL mode: bring all imports without filtering by specific invoice_type - pass - else: - where_conditions.append("ih.invoice_type IN ('REP', 'MATREP')") + # Repair imports are identified by cross-references, not invoice_type + where_conditions.append("COALESCE(cmp.is_regime_change, false) = false") # Date range filter if filters.range_type.value == "FF": diff --git a/frontend/src/routes/dashboard/reports/invoices/+page.svelte b/frontend/src/routes/dashboard/reports/invoices/+page.svelte index b2060ede..a1f33b08 100644 --- a/frontend/src/routes/dashboard/reports/invoices/+page.svelte +++ b/frontend/src/routes/dashboard/reports/invoices/+page.svelte @@ -83,7 +83,6 @@ let filters = $state({ includeNA: false, - includePartial: false, downloaded: 'all' as 'all' | 'downloaded' | 'not_downloaded' }); @@ -291,30 +290,6 @@ return { valid: true }; } - function getSelectedMovementTypes(): string[] { - const selected: string[] = []; - - // Imports - if (types.import.TEM) selected.push('IMTEM'); - if (types.import.DEF) selected.push('IMPDF'); - if (types.import.REP) selected.push('IMPRE'); - - // Exports - if (types.export.main.DEF || types.export.additional.TODAS) selected.push('EXPO_DEF'); - if (types.export.main.REP || types.export.additional.TODAS) selected.push('EXPO_REP'); - if (types.export.additional.AFIJO) selected.push('AFIJO'); - if (types.export.additional.REEXP) selected.push('REEXP'); - if (types.export.additional.NODES) selected.push('NODES'); - if (types.export.additional.DONAC) selected.push('DONAC'); - if (types.export.additional.SCRAP) selected.push('SCRAP'); - - // Others - if (types.other.VEMEX) selected.push('VEMEX'); - if (types.other.COMEX) selected.push('COMEX'); - - return selected; - } - // --- LÓGICA --- async function handleGenerateReport() { @@ -408,7 +383,7 @@ if (response.data) allResults.push(...response.data); } - // Importaciones Definitivas (IMPDF) + // Importaciones Definitivas (IMPDF) o COMEX if (types.import.DEF) { toast.info('Obteniendo importaciones definitivas...'); const movementType = types.other.COMEX ? 'COMEX' : 'IMPDF'; @@ -416,12 +391,12 @@ ? await invoiceMovementsApi.getDefinitiveImports({ ...baseFilter, database_name: 'default', - movement_type: movementType === 'COMEX' ? 'COMEX' : 'IMPDF' + movement_type: movementType }) : await invoiceMovementsApi.getDefinitiveImportsDetailed({ ...baseFilter, database_name: 'default', - movement_type: movementType === 'COMEX' ? 'COMEX' : 'IMPDF' + movement_type: movementType }); if (response.data) allResults.push(...response.data); } @@ -445,10 +420,11 @@ if (response.data) allResults.push(...response.data); } - // Exportaciones Definitivas - if (types.export.main.DEF || types.export.additional.TODAS || Object.values(types.export.additional).some(v => v)) { + // Exportaciones Definitivas (incluye VEMEX) + if (types.export.main.DEF || types.other.VEMEX || types.export.additional.TODAS || Object.values(types.export.additional).some(v => v)) { toast.info('Obteniendo exportaciones...'); + // Determinar tipo de movimiento basado en checkboxes adicionales let movementType: any = 'ALL'; if (types.export.additional.AFIJO) movementType = 'AFIJO'; else if (types.export.additional.NODES) movementType = 'NODES'; @@ -466,7 +442,7 @@ database_name: 'default', movement_type: movementType, discharge_filter: dischargeFilter, - use_transport_method: false // Por defecto, ajustar según necesidad + use_transport_method: false }) : await invoiceMovementsApi.getExportsDetailed({ ...baseFilter, @@ -482,6 +458,7 @@ if (types.export.main.REP || types.export.additional.TODAS) { toast.info('Obteniendo exportaciones de reparación...'); + // Para reparaciones solo aplican AFIJO y NODES let movementType: any = 'ALL'; if (types.export.additional.AFIJO) movementType = 'AFIJO'; else if (types.export.additional.NODES) movementType = 'NODES'; @@ -505,6 +482,61 @@ if (response.data) allResults.push(...response.data); } + // Cambio de Régimen (CREG) - Exportaciones con cambio de régimen + if (types.export.main.CREG) { + toast.info('Obteniendo cambios de régimen...'); + + // Para cambio de régimen solo aplican AFIJO y SCRAP + let movementType: any = 'ALL'; + if (types.export.additional.AFIJO) movementType = 'AFIJO'; + else if (types.export.additional.SCRAP) movementType = 'SCRAP'; + + const dischargeFilter = filters.downloaded === 'downloaded' ? 'SiDes' : + filters.downloaded === 'not_downloaded' ? 'NoDes' : 'ALL'; + + const response = config.reportType === 'normal' + ? await invoiceMovementsApi.getExports({ + ...baseFilter, + database_name: 'default', + movement_type: movementType, + discharge_filter: dischargeFilter, + use_transport_method: false + }) + : await invoiceMovementsApi.getExportsDetailed({ + ...baseFilter, + database_name: 'default', + movement_type: movementType, + discharge_filter: dischargeFilter, + use_transport_method: false + }); + if (response.data) allResults.push(...response.data); + } + + // CREGEXP (Cambio Régimen Export) - Caso especial + if (types.other.CREGEXP) { + toast.info('Obteniendo cambios de régimen export...'); + + const dischargeFilter = filters.downloaded === 'downloaded' ? 'SiDes' : + filters.downloaded === 'not_downloaded' ? 'NoDes' : 'ALL'; + + const response = config.reportType === 'normal' + ? await invoiceMovementsApi.getExports({ + ...baseFilter, + database_name: 'default', + movement_type: 'ALL', + discharge_filter: dischargeFilter, + use_transport_method: false + }) + : await invoiceMovementsApi.getExportsDetailed({ + ...baseFilter, + database_name: 'default', + movement_type: 'ALL', + discharge_filter: dischargeFilter, + use_transport_method: false + }); + if (response.data) allResults.push(...response.data); + } + results = allResults; showResults = true; @@ -760,6 +792,14 @@ return dateStr; } + function formatCurrency(value: number | null | undefined): string { + if (value === null || value === undefined) return '-'; + return new Intl.NumberFormat('en-US', { + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }).format(value); + } + function handleClose() { // Reset form instead of navigating back showResults = false; @@ -938,7 +978,7 @@ bind:checked={types.import[key as keyof typeof types.import]} /> {/each} @@ -1237,7 +1277,7 @@ {row.ClavePed || '-'} {row.Factura} {formatDateFromYYYYMMDD(row.FechaFactura)} - ${row.ValorComercialMN} + ${formatCurrency(row.ValorComercialMN)} {row.TipoMovTemDef}