diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py index 003af79d..d543a5a2 100644 --- a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py @@ -58,6 +58,7 @@ class FacturaSchema(BaseModel): aduana: str = "" destino: str = "" observaciones: str = "" + transportista_info: str = "" class PartidaSchema(BaseModel): numero_parte: str diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py index 6bfab155..5cff09b4 100644 --- a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py @@ -169,6 +169,10 @@ class ConsolidadoImportacionMexService: caat_val = "" scac_val = "" licencia_cond_val = "" + conductor_nombre = "" + + # Block Logic (Clarion Style) for transportista_info + transport_lines = [] if logistics: # 1. Transporter (CAAT / SCAC) @@ -179,6 +183,35 @@ class ConsolidadoImportacionMexService: scac_val = transporter_obj.transport_code or "" # Mapping transport_code to SCAC transportista_val = transporter_obj.name or logistics.carrier_id + # Clarion Logic: Name first + # Line 1: Name + transport_lines.append(transporter_obj.name or "") + + # Line 2: Streets + if transporter_obj.streets: + transport_lines.append(transporter_obj.streets) + + # Line 3: City, State, Country + loc_line = "" + if transporter_obj.city: + loc_line = transporter_obj.city + if transporter_obj.state: + loc_line += f", {transporter_obj.state}, " + else: + loc_line += ", " + else: + if transporter_obj.state: + loc_line = f"{transporter_obj.state}," + + country_desc = transporter_obj.country or "" + if loc_line: + loc_line += f" {country_desc}" + elif country_desc: + loc_line = country_desc + + if loc_line.strip(", "): + transport_lines.append(loc_line) + # 2. Vehicle (Placas Tracto) - Try transport_id first if logistics.transport_id: veh_obj = db.query(Vehicle).filter(Vehicle.vehicle_key == logistics.transport_id).first() @@ -197,6 +230,7 @@ class ConsolidadoImportacionMexService: # 4. Driver (License) if logistics.carrier_id and logistics.driver_name: + conductor_nombre = logistics.driver_name # Attempt to find driver by name + carrier drv_obj = db.query(Driver).filter( Driver.transporter_key == logistics.carrier_id, @@ -204,6 +238,45 @@ class ConsolidadoImportacionMexService: ).first() if drv_obj: licencia_cond_val = drv_obj.license_number or "" + + # --- Building the rest of the block --- + + # Line 4: Driver + if conductor_nombre: + transport_lines.append(f"Driver/Conductor: {conductor_nombre}") + + # Line 5: Conveyance / Transporte + t_label = "Conveyance / Transporte" + t_val = placas_val # Default to Truck Plate + + if logistics.transport_type: + ttype = str(logistics.transport_type).lower() + if "caja" in ttype or "trailer" in ttype: + t_label = "Trailer / Caja" + t_val = placas_remolque_val or num_transporte_val + elif "placa" in ttype: + t_label = "Plates / Placas" + elif "camion" in ttype or "truck" in ttype: + t_label = "Truck / Camión" + + if t_val: + transport_lines.append(f"{t_label}: {t_val}") + + # Line 6: SCAC / CAAT + codes_line = "" + if scac_val: + codes_line = f"SCAC Code/Clave: {scac_val}" + if caat_val: + if codes_line: + codes_line += f", CAAT Code/Clave: {caat_val}" + else: + codes_line = f"CAAT Code/Clave: {caat_val}" + + if codes_line: + transport_lines.append(codes_line) + + # Join with newlines + transport_block_str = "\n".join([l for l in transport_lines if l]) factura_schema = FacturaSchema( numero=header.invoice_number or "S/N", @@ -230,7 +303,8 @@ class ConsolidadoImportacionMexService: destino=(logistics.destination_goods or "") if logistics else "", remesa=remesa_valor, acuse_electronico=acuse_valor, representante_legal=getattr(company, 'responsible', "") or "", - nombre_empresa=getattr(company, 'name', "") or "" + nombre_empresa=getattr(company, 'name', "") or "", + transportista_info=transport_block_str ) if progress_callback: progress_callback(50, "Procesando partidas...") @@ -267,6 +341,10 @@ class ConsolidadoImportacionMexService: # For simplicity in this step, we query inside or rely on Part data. # Ideally fetch USTariffFraction from DB based on Part.us_fraction + # --- Optimización: Cargar Facturas en Memoria --- + invoices_list = db.query(InvoiceHeader).filter(InvoiceHeader.id.in_(target_invoice_ids)).all() + invoice_map = {inv.id: inv for inv in invoices_list} + from api.v1.modules.a76.general_catalogs.us_tariff_fractions.models import USTariffFraction for line in lines: @@ -274,7 +352,7 @@ class ConsolidadoImportacionMexService: fin = db.query(LineFinancial).filter(LineFinancial.item_line_id == line.id).first() part_master = db.query(Part).filter(Part.id == line.part_number).first() - # --- Resolver Identificadores --- + # --- Resolver Identificadores (MOVED INSIDE MAIN LOOP) --- us_fraction_raw = "" origin_final = "MEX" @@ -282,22 +360,9 @@ class ConsolidadoImportacionMexService: origin_final = part_master.fa_data.origin_country if (part_master.fa_data and part_master.fa_data.origin_country) else "MEX" us_fraction_raw = part_master.us_fraction if part_master.us_fraction else "" - # Cleaning Fraction - us_frac_clean = us_fraction_raw.strip() - # Key for aggregation + us_frac_clean = us_fraction_raw.strip() agg_key = (us_frac_clean, origin_final) - - # --- Weights & Qty --- - # --- Optimización: Cargar Facturas en Memoria (Evitar N+1 y arreglar AttributeError) --- - # Pre-fetch invoices explicitly since line.item.invoice relationship might not exist - invoices_list = db.query(InvoiceHeader).filter(InvoiceHeader.id.in_(target_invoice_ids)).all() - invoice_map = {inv.id: inv for inv in invoices_list} - - for line in lines: - qty = db.query(LineQuantity).filter(LineQuantity.item_line_id == line.id).first() - fin = db.query(LineFinancial).filter(LineFinancial.item_line_id == line.id).first() - part_master = db.query(Part).filter(Part.id == line.part_number).first() # --- Weights & Qty --- q_line = float(qty.quantity) if (qty and qty.quantity) else 0.0 nw_line = float(qty.net_weight) if qty else 0.0 diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html b/backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html index 17f4051a..2f0d026b 100644 --- a/backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html @@ -309,34 +309,39 @@
|
- Invoice No. / Num. Factura: + |
+ Invoice No.: |
- + |
{{ factura.numero }} |
||
|
- Date / Fecha: + |
+ Date: |
- + |
{{ factura.fecha }} |
- ||
|
- Rate / Cambio: + |
+ Rate: |
- + |
{{ factura.tipo_cambio }} |
||
Coveyance Co. / Cia. Transportista:
+{{ factura.transportista_info }}
+Normal Por Parte
-Declaro bajo protesta de decir verdad que la información contenida en - este documento es verdadera y me hago responsable de comprobar lo aquí declarado.
+I declare under penalty of perjury that the information contained in + this document is true and I am responsible for proving what is declared here.