feat: Enhance fixed asset class management with new fields, refactor forms, and update invoice-related services.
This commit is contained in:
@@ -223,6 +223,7 @@ class ClassWithFADataResponse(BaseModel):
|
||||
fa_class_id: Optional[int] = None
|
||||
depreciation_rate: Optional[Decimal] = None
|
||||
fda_code: Optional[str] = None
|
||||
eccn_code: Optional[str] = None
|
||||
class_enabled: Optional[bool] = None
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
@@ -152,6 +152,7 @@ class ClassService:
|
||||
"fa_class_id": fa_class.id if fa_class else None,
|
||||
"depreciation_rate": fa_class.depreciation_rate if fa_class else None,
|
||||
"fda_code": fa_class.fda_code if fa_class else None,
|
||||
"eccn_code": fa_class.eccn_code if fa_class else None,
|
||||
"class_enabled": fa_class.class_enabled if fa_class else None,
|
||||
}
|
||||
combined.append(class_dict)
|
||||
|
||||
@@ -134,12 +134,14 @@ class InvoiceCatalogService:
|
||||
|
||||
# Drivers
|
||||
try:
|
||||
drivers, _ = DriverService.get_all(db, tenant_id, company_id, limit=1000)
|
||||
drivers = DriverService.list_drivers(db, str(company_id), str(tenant_id))
|
||||
response.drivers = [
|
||||
DriverResponseDTO.model_validate(d) for d in drivers
|
||||
]
|
||||
except Exception as e:
|
||||
print(f"Error fetching drivers: {e}")
|
||||
# Initialize drivers as empty list if an error occurs
|
||||
drivers = []
|
||||
|
||||
# Trailers
|
||||
try:
|
||||
|
||||
@@ -188,6 +188,23 @@ def validate_create(
|
||||
line.financial.unit_cost_mxn = unit_cost_capture
|
||||
# Si es otro tipo de moneda, dejamos el costo como está
|
||||
|
||||
# Calcular valores totales basados en cantidad y costo unitario
|
||||
quantity = line.quantity.quantity or Decimal("0")
|
||||
|
||||
# Valor Comercial
|
||||
if line.financial.unit_cost_usd is not None:
|
||||
line.financial.value_usd = line.financial.unit_cost_usd * quantity
|
||||
if line.financial.unit_cost_mxn is not None:
|
||||
line.financial.value_mxn = line.financial.unit_cost_mxn * quantity
|
||||
|
||||
# Valor Aduanas (asumiendo que es igual al Valor Comercial por defecto)
|
||||
line.financial.customs_value_usd = line.financial.value_usd
|
||||
line.financial.customs_value_mxn = line.financial.value_mxn
|
||||
|
||||
# Valor MP Temp (Materia Prima Temporal)
|
||||
line.financial.value_temp_material_usd = line.financial.value_usd
|
||||
line.financial.value_temp_material_mxn = line.financial.value_mxn
|
||||
|
||||
# ==========================================
|
||||
# VALIDAR Y CONVERTIR PESOS NETOS
|
||||
# ==========================================
|
||||
|
||||
@@ -64,6 +64,30 @@ def validate_update(
|
||||
# Costo unitario
|
||||
if line.financial.unit_cost_capture is None:
|
||||
line.financial.unit_cost_capture = existing_line.financial.unit_cost_capture
|
||||
|
||||
# Recalcular valores monetarios si el costo o la cantidad cambian
|
||||
currency_type = invoice.financials.currency_type
|
||||
unit_cost_capture = line.financial.unit_cost_capture or Decimal("0")
|
||||
|
||||
if currency_type in ["USD", "ME"]:
|
||||
line.financial.unit_cost_usd = unit_cost_capture
|
||||
line.financial.unit_cost_mxn = unit_cost_capture * exchange_rate
|
||||
elif currency_type in ["MXN", "MN"]:
|
||||
line.financial.unit_cost_usd = (unit_cost_capture / exchange_rate) if exchange_rate else Decimal("0")
|
||||
line.financial.unit_cost_mxn = unit_cost_capture
|
||||
|
||||
quantity = line.quantity.quantity if line.quantity.quantity is not None else existing_line.quantity.quantity
|
||||
|
||||
if line.financial.unit_cost_usd is not None:
|
||||
line.financial.value_usd = line.financial.unit_cost_usd * quantity
|
||||
if line.financial.unit_cost_mxn is not None:
|
||||
line.financial.value_mxn = line.financial.unit_cost_mxn * quantity
|
||||
|
||||
line.financial.customs_value_usd = line.financial.value_usd
|
||||
line.financial.customs_value_mxn = line.financial.value_mxn
|
||||
|
||||
line.financial.value_temp_material_usd = line.financial.value_usd
|
||||
line.financial.value_temp_material_mxn = line.financial.value_mxn
|
||||
|
||||
# Convertir peso neto si se proporcionó
|
||||
invoice_weight_type = invoice.logistics.weight_type
|
||||
|
||||
@@ -4,7 +4,7 @@ Complete nested one-to-one structure:
|
||||
LineItem -> LineFinancial -> LineQuantity -> LineCustoms -> LineDescription -> LineReference
|
||||
"""
|
||||
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, Union
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from pydantic import BaseModel, Field, ConfigDict, model_validator
|
||||
@@ -58,13 +58,13 @@ class LineItemBase(BaseModel):
|
||||
line_number: int = Field(..., description="Line number")
|
||||
|
||||
# Part identification
|
||||
part_number_id: Optional[int] = Field(
|
||||
part_number_id: Union[int, str, None] = Field(
|
||||
None,
|
||||
description="Part number",
|
||||
alias="part_number",
|
||||
serialization_alias="part_number_id",
|
||||
)
|
||||
component_part_number_id: Optional[int] = Field(
|
||||
component_part_number_id: Union[int, str, None] = Field(
|
||||
None,
|
||||
description="Component part number",
|
||||
alias="component_part_number",
|
||||
|
||||
@@ -36,6 +36,7 @@ from .line_references.models import LineReference
|
||||
from api.v1.modules.a24.fa.fa_item_lines.models import FaLineItem
|
||||
from .models import LineItem
|
||||
from api.v1.modules.a76.invoices.models import InvoiceHeader
|
||||
from api.v1.modules.a76.parts.models import Part
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -45,6 +46,33 @@ class ItemService:
|
||||
Service for managing Items and related entities with tenant/company isolation
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _resolve_part_number(
|
||||
db: Session,
|
||||
part_number: Optional[str],
|
||||
tenant_id: int,
|
||||
company_id: int,
|
||||
) -> Optional[int]:
|
||||
"""Try to resolve a part number string to its database ID."""
|
||||
if not part_number:
|
||||
return None
|
||||
|
||||
# If it's already an integer (or a string representing an integer), it might be the ID
|
||||
try:
|
||||
return int(part_number)
|
||||
except (ValueError, TypeError):
|
||||
# It's a string part number (e.g., "MAQ-001"), look it up
|
||||
part = (
|
||||
db.query(Part)
|
||||
.filter(
|
||||
Part.part_number == part_number,
|
||||
Part.tenant_id == tenant_id,
|
||||
Part.company_id == company_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
return part.id if part else None
|
||||
|
||||
@staticmethod
|
||||
def _get_next_line_number(db: Session, invoice_id: int) -> int:
|
||||
"""Calculate the next line_number for a given invoice based on database."""
|
||||
@@ -282,6 +310,24 @@ class ItemService:
|
||||
# Calculate the next line number for this single item
|
||||
line_number = ItemService._get_next_line_number(db, item_data.invoice_id)
|
||||
|
||||
# Resolve part ID if a string is provided in part_number (alias for part_number_id)
|
||||
if item_data.part_number_id and not isinstance(item_data.part_number_id, int):
|
||||
resolved_id = ItemService._resolve_part_number(
|
||||
db, str(item_data.part_number_id), tenant_id, company_id
|
||||
)
|
||||
if resolved_id:
|
||||
item_data.part_number_id = resolved_id
|
||||
|
||||
# Resolve component part ID
|
||||
if item_data.component_part_number_id and not isinstance(
|
||||
item_data.component_part_number_id, int
|
||||
):
|
||||
resolved_id = ItemService._resolve_part_number(
|
||||
db, str(item_data.component_part_number_id), tenant_id, company_id
|
||||
)
|
||||
if resolved_id:
|
||||
item_data.component_part_number_id = resolved_id
|
||||
|
||||
# Validar el item
|
||||
validate_create(
|
||||
db,
|
||||
@@ -378,6 +424,24 @@ class ItemService:
|
||||
):
|
||||
errors.raise_if_errors("Error al actualizar el item")
|
||||
|
||||
# Resolve part ID if a string is provided in part_number (alias for part_number_id)
|
||||
if hasattr(item_data, 'part_number_id') and item_data.part_number_id and not isinstance(item_data.part_number_id, int):
|
||||
resolved_id = ItemService._resolve_part_number(
|
||||
db, str(item_data.part_number_id), tenant_id, company_id
|
||||
)
|
||||
if resolved_id:
|
||||
item_data.part_number_id = resolved_id
|
||||
|
||||
# Resolve component part ID
|
||||
if hasattr(item_data, 'component_part_number_id') and item_data.component_part_number_id and not isinstance(
|
||||
item_data.component_part_number_id, int
|
||||
):
|
||||
resolved_id = ItemService._resolve_part_number(
|
||||
db, str(item_data.component_part_number_id), tenant_id, company_id
|
||||
)
|
||||
if resolved_id:
|
||||
item_data.component_part_number_id = resolved_id
|
||||
|
||||
# Validar el item que se va a actualizar
|
||||
validate_update(
|
||||
db,
|
||||
|
||||
@@ -112,9 +112,10 @@ class DatabaseHelper:
|
||||
|
||||
try:
|
||||
sql = text("""
|
||||
SELECT name, rfc
|
||||
FROM a76.clients_and_providers
|
||||
WHERE id = :client_code AND client_or_provider = :client_type
|
||||
SELECT cp.name, cp.rfc, cpp.tax_id
|
||||
FROM a76.clients_and_providers cp
|
||||
LEFT JOIN a76.clients_and_providers_programs cpp ON cpp.client_id = cp.id
|
||||
WHERE cp.id = :client_code AND cp.client_or_provider = :client_type
|
||||
""")
|
||||
result = db.execute(sql, {"client_code": client_code, "client_type": client_type}).fetchone()
|
||||
|
||||
@@ -122,7 +123,7 @@ class DatabaseHelper:
|
||||
return {
|
||||
"name": result[0],
|
||||
"rfc": result[1],
|
||||
"tax_id": None # Column does not exist in this table
|
||||
"tax_id": result[2]
|
||||
}
|
||||
else:
|
||||
logger.debug(f"Client {client_code} not found as {client_type}")
|
||||
@@ -233,8 +234,7 @@ class DatabaseHelper:
|
||||
SELECT serial_numbers, model, brand
|
||||
FROM a76.item_line_series ils
|
||||
INNER JOIN a76.item_lines il ON ils.line_item_id = il.id
|
||||
INNER JOIN a76.items i ON il.item_id = i.id
|
||||
WHERE i.invoice_id = :invoice_id
|
||||
WHERE il.invoice_id = :invoice_id
|
||||
AND il.line_number = :linea
|
||||
ORDER BY ils.id
|
||||
LIMIT 1
|
||||
@@ -290,8 +290,7 @@ class DatabaseHelper:
|
||||
SELECT serial_numbers, model, expo_brad
|
||||
FROM a76.item_line_series ils
|
||||
INNER JOIN a76.item_lines il ON ils.line_item_id = il.id
|
||||
INNER JOIN a76.items i ON il.item_id = i.id
|
||||
WHERE i.invoice_id = :invoice_id
|
||||
WHERE il.invoice_id = :invoice_id
|
||||
AND il.line_number = :linea
|
||||
ORDER BY ils.id
|
||||
LIMIT 1
|
||||
|
||||
@@ -89,6 +89,11 @@ class DefinitiveImportService:
|
||||
# Totals come directly from GROUP BY query (no N+1 problem)
|
||||
total_me = to_float(row[28]) # total_me from SUM aggregation
|
||||
total_mn = to_float(row[29]) # total_mn from SUM aggregation
|
||||
sum_value_usd = to_float(row[30])
|
||||
sum_value_mxn = to_float(row[31])
|
||||
|
||||
total_me = sum_value_usd if sum_value_usd > 0 else total_me
|
||||
total_mn = sum_value_mxn if sum_value_mxn > 0 else total_mn
|
||||
|
||||
# Calculate exchange rate and value
|
||||
valor_comercial, tipo_cambio = ExchangeRateCalculator.calculate_for_aggregated(
|
||||
@@ -215,58 +220,58 @@ class DefinitiveImportService:
|
||||
valor_comercial, tipo_cambio = ExchangeRateCalculator.calculate_exchange_rate_and_value(
|
||||
db=db,
|
||||
db_name=filters.database_name,
|
||||
es_subpartida=row[39], # EsSubPartida
|
||||
valor_me=row[26],
|
||||
valor_mn_direct=row[24],
|
||||
fecha_pago=row[12],
|
||||
fecha_inicio=row[10],
|
||||
clave_ped=row[58],
|
||||
tipo_cambio_partida=row[50],
|
||||
es_subpartida=row[39], # C40 - EsSubPartida
|
||||
valor_me=row[26], # C27 - ValorImpoME
|
||||
valor_mn_direct=row[24], # C25 - ValorImpoMN
|
||||
fecha_pago=row[12], # C13 - Fecha_Pago
|
||||
fecha_inicio=row[10], # C1 entry_date
|
||||
clave_ped=row[57] if len(row) > 57 else '', # C58 - TIPOPEDIMENTOTRANSPORTEE
|
||||
tipo_cambio_partida=row[49], # C50 - TipoCambio
|
||||
currency_type=filters.currency_type.value,
|
||||
exchange_rate_type=filters.exchange_rate_type.value,
|
||||
met_trans=met_trans
|
||||
)
|
||||
|
||||
# Set peso values based on subpartida flag
|
||||
if row[39] == 'P':
|
||||
peso_neto = float(row[28]) if row[28] else 0.0
|
||||
peso_bruto = float(row[29]) if row[29] else 0.0
|
||||
if row[39] == 'P': # C40 - EsSubPartida
|
||||
peso_neto = float(row[28]) if row[28] else 0.0 # C29
|
||||
peso_bruto = float(row[29]) if row[29] else 0.0 # C30
|
||||
else:
|
||||
peso_neto = 0.0
|
||||
peso_bruto = 0.0
|
||||
|
||||
series_info = DatabaseHelper.get_series_info(
|
||||
db, filters.database_name, row[34], row[44], filters.is_shelter
|
||||
db, filters.database_name, row[38], row[43], filters.is_shelter # C39, C44
|
||||
)
|
||||
|
||||
simbolo_ex = None
|
||||
if row[19]:
|
||||
if row[48]: # C49 - Part Number
|
||||
simbolo_ex = DatabaseHelper.get_part_export_symbol(
|
||||
db, filters.database_name, row[19], filters.is_shelter
|
||||
db, filters.database_name, row[48], filters.is_shelter
|
||||
)
|
||||
|
||||
pedimento_r1 = DatabaseHelper.get_rectification_pedimento(
|
||||
db, row[1], row[41], filters.is_shelter
|
||||
db, row[1], row[40], filters.is_shelter # C2, C41
|
||||
)
|
||||
|
||||
num_gaf_uni = DatabaseHelper.get_driver_badge(
|
||||
db, filters.database_name, row[0]
|
||||
db, filters.database_name, row[0] # C1
|
||||
)
|
||||
|
||||
movement = MovementItemDetailed(
|
||||
Linea=row[44],
|
||||
Factura=row[0],
|
||||
Pedimento=row[1],
|
||||
FechaFactura=row[2],
|
||||
Estatus=row[3],
|
||||
ClavePed=row[4],
|
||||
Linea=row[43], # C44
|
||||
Factura=row[0], # C1
|
||||
Pedimento=row[1], # C2
|
||||
FechaFactura=parse_yyyymmdd_date(row[2]), # C3
|
||||
Estatus=row[3], # C4
|
||||
ClavePed=row[4], # C5
|
||||
TipoMovTemDef='IMPDF',
|
||||
EsCambioRegimen='N',
|
||||
Regimen=row[9],
|
||||
Fecha_Inicio=row[10],
|
||||
Fecha_Fin=row[11],
|
||||
Fecha_Pago=row[12],
|
||||
Remesa=row[13],
|
||||
Regimen=row[9], # C10
|
||||
Fecha_Inicio=parse_yyyymmdd_date(row[10]), # C11
|
||||
Fecha_Fin=parse_yyyymmdd_date(row[11]), # C12
|
||||
Fecha_Pago=parse_yyyymmdd_date(row[12]), # C13
|
||||
Remesa=str(row[13]) if row[13] is not None else None, # C14
|
||||
Proveedor=row[7], # C8 - Provider name (from JOIN)
|
||||
RFCProveedor=proveedor_info.get('rfc'),
|
||||
ProveedorTaxID=proveedor_info.get('tax_id'),
|
||||
@@ -275,42 +280,42 @@ class DefinitiveImportService:
|
||||
VendidoATaxID=vendido_info.get('tax_id'),
|
||||
AgenteAduanal=agente_info.get('name'),
|
||||
Patente=agente_info.get('license'),
|
||||
NumParte=row[19],
|
||||
DescripcionE=StringHelper.clean_text(row[20]),
|
||||
DescripcionI=StringHelper.clean_text(row[21]),
|
||||
CantidadIE=float(row[22]) if row[22] else 0.0,
|
||||
UniMed=row[23],
|
||||
NumParte=row[48], # C49
|
||||
DescripcionE=StringHelper.clean_text(row[20]), # C21
|
||||
DescripcionI=StringHelper.clean_text(row[21]), # C22
|
||||
CantidadIE=float(row[22]) if row[22] else 0.0, # C23
|
||||
UniMed=row[23], # C24
|
||||
ValorComercialMN=valor_comercial,
|
||||
TipoCambio=tipo_cambio,
|
||||
PesoNeto=peso_neto,
|
||||
PesoBruto=peso_bruto,
|
||||
OrdenCompraVenta=row[30],
|
||||
FraccionArancelaria=row[31],
|
||||
Preferencia=row[32],
|
||||
Sector=None, # row[34] is invoice ID, Sector not in query
|
||||
PaisOrigen=row[37],
|
||||
OrdenCompraVenta=row[30], # C31
|
||||
FraccionArancelaria=row[31], # C32
|
||||
Preferencia=row[32], # C33
|
||||
Sector=row[34], # C35
|
||||
PaisOrigen=row[36], # C37
|
||||
Aduana=aduana_nombre,
|
||||
Advalorem=row[39],
|
||||
Advalorem='P' if row[39] == 'P' else 'S', # C40
|
||||
TipoExpo='',
|
||||
PedimentoR1=pedimento_r1,
|
||||
EDocument=row[42],
|
||||
NumOperacionVU=row[43],
|
||||
EDocument=row[41], # C42
|
||||
NumOperacionVU=row[42], # C43
|
||||
Series=series_info,
|
||||
Marca=StringHelper.clean_text(row[45]),
|
||||
Modelo=StringHelper.clean_text(row[46]),
|
||||
FraccionAmericana=row[47],
|
||||
ECCN=row[48],
|
||||
Marca=StringHelper.clean_text(row[44]), # C45
|
||||
Modelo=StringHelper.clean_text(row[45]), # C46
|
||||
FraccionAmericana=row[46], # C47
|
||||
ECCN=row[47], # C48
|
||||
SimboloEx=simbolo_ex,
|
||||
FechaEmision=row[51],
|
||||
FechaEmision=parse_yyyymmdd_date(row[50]) if row[50] else None, # C51
|
||||
BaseDeDatos=filters.database_name,
|
||||
NumGafUni=num_gaf_uni,
|
||||
UsuarioCap=row[52],
|
||||
UsuarioAcr=row[53],
|
||||
Transportista=row[54],
|
||||
NumCaja=row[55],
|
||||
Pedimento18=row[56],
|
||||
AduanaCru=row[38],
|
||||
Lote=row[57]
|
||||
UsuarioCap=row[51], # C52
|
||||
UsuarioAcr=row[52], # C53
|
||||
Transportista=row[53], # C54
|
||||
NumCaja=row[54], # C55
|
||||
Pedimento18=row[55] if len(row) > 55 else '', # C56
|
||||
AduanaCru=row[37], # C38
|
||||
Lote=row[56] if len(row) > 56 else '' # C57
|
||||
)
|
||||
|
||||
movements.append(movement)
|
||||
@@ -337,7 +342,7 @@ class DefinitiveImportService:
|
||||
if filters.range_type.value == "FF":
|
||||
where_conditions.append(f"ih.invoice_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND ih.invoice_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
else:
|
||||
where_conditions.append(f"log.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND log.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
where_conditions.append(f"pd.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND pd.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
|
||||
# Note: Status filter applied at Python level after CASE WHEN in SELECT
|
||||
# because is_updated doesn't directly represent AC/NA status
|
||||
@@ -367,8 +372,7 @@ class DefinitiveImportService:
|
||||
COALESCE(SUM(lf.value_mxn), 0)
|
||||
FROM a76.item_line_financials lf
|
||||
INNER JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
INNER JOIN a76.items itm ON itm.id = il.item_id
|
||||
WHERE itm.invoice_id = :consecutivo
|
||||
WHERE il.invoice_id = :consecutivo
|
||||
AND COALESCE(il.is_subpartida, false) = false
|
||||
""")
|
||||
|
||||
|
||||
@@ -65,13 +65,14 @@ class ExchangeRateCalculator:
|
||||
fecha_pago=fecha_pago,
|
||||
fecha_inicio=fecha_inicio,
|
||||
tipo_pedimento=clave_ped,
|
||||
use_transport_method=True, # Always use for detailed calculations
|
||||
use_transport_method=True,
|
||||
met_trans=met_trans
|
||||
)
|
||||
tc_value = DatabaseHelper.get_exchange_rate(db, db_name, fecha_tc)
|
||||
if tc_value:
|
||||
tipo_cambio_final = tc_value
|
||||
|
||||
# For ME, the value is always in foreign currency (USD)
|
||||
return (valor_comercial, tipo_cambio_final)
|
||||
|
||||
# Handle local currency (MN) case
|
||||
@@ -86,14 +87,14 @@ class ExchangeRateCalculator:
|
||||
tc_value = DatabaseHelper.get_exchange_rate(db, db_name, fecha_tc)
|
||||
|
||||
if tc_value and valor_me is not None:
|
||||
# Calculate MN value from ME * exchange rate
|
||||
# Calculate MN value from ME * payment date exchange rate
|
||||
return (valor_me * tc_value, tc_value)
|
||||
else:
|
||||
# Fall back to direct MN value and partida exchange rate
|
||||
if tc_value is None:
|
||||
logger.warning(f"Exchange rate not found for date {fecha_tc}, using partida values")
|
||||
return (valor_mn_direct or 0.0, tipo_cambio_partida)
|
||||
else:
|
||||
# exchange_rate_type == "FT" (Invoice Date)
|
||||
# Use direct MN value and partida exchange rate
|
||||
return (valor_mn_direct or 0.0, tipo_cambio_partida)
|
||||
|
||||
@@ -151,22 +152,42 @@ class ExchangeRateCalculator:
|
||||
use_transport_method=use_transport_method,
|
||||
met_trans=met_trans
|
||||
)
|
||||
# For Shelter + FP: validate exchange rate exists (Clarion logic)
|
||||
tc_value = DatabaseHelper.get_exchange_rate(
|
||||
db, db_name, fecha_tc,
|
||||
is_shelter=is_shelter,
|
||||
raise_on_missing=is_shelter # Raise error if shelter and not found
|
||||
raise_on_missing=is_shelter
|
||||
)
|
||||
|
||||
if tc_value:
|
||||
return (valor_me * tc_value, tc_value)
|
||||
# For ME, the value is always in foreign currency (USD). Just return the new exchange rate.
|
||||
return (valor_comercial, tc_value)
|
||||
else:
|
||||
logger.warning(f"Exchange rate not found for date {fecha_tc}, using DB values")
|
||||
return (valor_mn, tipo_cambio_db)
|
||||
else:
|
||||
# FT or no payment date: use DB values
|
||||
return (valor_comercial, tipo_cambio)
|
||||
|
||||
|
||||
return (valor_comercial, tipo_cambio)
|
||||
|
||||
# Local currency case
|
||||
else:
|
||||
return (valor_mn, tipo_cambio_db)
|
||||
if exchange_rate_type == "FP" and fecha_pago:
|
||||
fecha_tc = DateHelper.get_fecha_tipo_cambio(
|
||||
fecha_pago=fecha_pago,
|
||||
fecha_inicio=fecha_inicio,
|
||||
tipo_pedimento=tipo_pedimento,
|
||||
use_transport_method=use_transport_method,
|
||||
met_trans=met_trans
|
||||
)
|
||||
tc_value = DatabaseHelper.get_exchange_rate(
|
||||
db, db_name, fecha_tc,
|
||||
is_shelter=is_shelter,
|
||||
raise_on_missing=is_shelter
|
||||
)
|
||||
|
||||
if tc_value and valor_me is not None:
|
||||
# Calculate MN value from ME * payment date exchange rate
|
||||
return (valor_me * tc_value, tc_value)
|
||||
else:
|
||||
if tc_value is None:
|
||||
logger.warning(f"Exchange rate not found for date {fecha_tc}, using DB values")
|
||||
return (valor_mn, tipo_cambio_db)
|
||||
else:
|
||||
return (valor_mn, tipo_cambio_db)
|
||||
|
||||
@@ -73,8 +73,18 @@ class ExportService:
|
||||
consecutivo = row[16] # C35 - Consecutivo
|
||||
|
||||
# Totals come directly from GROUP BY query (no N+1 problem)
|
||||
total_me = row[24] # total_me from SUM aggregation
|
||||
total_mn = row[25] # total_mn from SUM aggregation
|
||||
def to_float(val):
|
||||
if val is None or val == '': return 0.0
|
||||
try: return float(val)
|
||||
except (ValueError, TypeError): return 0.0
|
||||
|
||||
total_me = to_float(row[24]) # total_me from SUM aggregation
|
||||
total_mn = to_float(row[25]) # total_mn from SUM aggregation
|
||||
sum_value_usd = to_float(row[27])
|
||||
sum_value_mxn = to_float(row[28])
|
||||
|
||||
total_me = sum_value_usd if sum_value_usd > 0 else total_me
|
||||
total_mn = sum_value_mxn if sum_value_mxn > 0 else total_mn
|
||||
|
||||
# Calculate exchange rate and value
|
||||
valor_comercial, tipo_cambio = ExchangeRateCalculator.calculate_for_aggregated(
|
||||
@@ -243,19 +253,19 @@ class ExportService:
|
||||
|
||||
# Build detailed movement item
|
||||
movement = MovementItemDetailed(
|
||||
Linea=row[41], # C42 - LineaExpo
|
||||
Factura=row[0], # C1 - FacturaExpo
|
||||
Pedimento=row[1], # C2 - PedimentoExpo
|
||||
FechaFactura=row[2], # C3 - FechaFactura
|
||||
Estatus=row[5], # C6 - Estatus
|
||||
ClavePed=row[6], # C7 - ClavePed
|
||||
TipoMovTemDef=row[33], # C34 - TipoFactura
|
||||
Linea=row[39], # C42 - LineaExpo
|
||||
Factura=row[0], # C1 - FacturaExpo
|
||||
Pedimento=row[1], # C2 - PedimentoExpo
|
||||
FechaFactura=row[2], # C3 - FechaFactura
|
||||
Estatus=row[5], # C6 - Estatus
|
||||
ClavePed=row[4], # C5 - ClavePed
|
||||
TipoMovTemDef=row[31], # C34 - TipoFactura
|
||||
EsCambioRegimen='N',
|
||||
Regimen=row[7], # C8 - Regimen
|
||||
Fecha_Inicio=row[8], # C9 - Fecha_Inicio
|
||||
Fecha_Fin=row[9], # C10 - Fecha_Fin
|
||||
Fecha_Pago=row[10], # C11 - Fecha_Pago
|
||||
Remesa=row[11], # C12 - Remesa
|
||||
Regimen=row[5], # C6 - Regime (Shared index with Estatus in this query)
|
||||
Fecha_Inicio=parse_yyyymmdd_date(row[6]), # C7 - Fecha_Inicio
|
||||
Fecha_Fin=parse_yyyymmdd_date(row[7]), # C8 - Fecha_Fin
|
||||
Fecha_Pago=parse_yyyymmdd_date(row[8]), # C9 - Fecha_Pago
|
||||
Remesa=row[9], # C12 - Remesa
|
||||
TipoCambio=tipo_cambio_final,
|
||||
Proveedor=proveedor_info.get("name"),
|
||||
RFCProveedor=proveedor_info.get("rfc"),
|
||||
@@ -265,41 +275,42 @@ class ExportService:
|
||||
VendidoATaxID=vendido_info.get("tax_id"),
|
||||
AgenteAduanal=agente_info.get("name"),
|
||||
Patente=agente_info.get("license"),
|
||||
NumParte=row[17], # C18 - Clase
|
||||
NumParte=row[17], # C18 - NumParte
|
||||
DescripcionE=StringHelper.remove_commas(row[18]), # C19 - DescripcionE
|
||||
DescripcionI=StringHelper.remove_commas(row[19]), # C20 - DescripcionI
|
||||
CantidadIE=row[20], # C21 - CantExpo
|
||||
UniMed=row[21], # C22 - UnidadMedida
|
||||
CantidadIE=row[20], # C21 - CantExpo
|
||||
UniMed=row[21], # C22 - UnidadMedida
|
||||
ValorComercialMN=valor_mn,
|
||||
PesoNeto=peso_neto_final,
|
||||
PesoBruto=peso_bruto_final,
|
||||
OrdenCompraVenta=row[26], # C27 - OrdenCompra
|
||||
FraccionArancelaria=row[27], # C28 - FraccionExpo
|
||||
Preferencia=row[28], # C29 - TipoFraccion
|
||||
Sector=row[30], # C31 - Sector
|
||||
PaisOrigen=row[31], # C32 - PaisOrigen
|
||||
OrdenCompraVenta=row[26], # C27 - OrdenCompra
|
||||
FraccionArancelaria=row[27], # C28 - FraccionExpo
|
||||
Preferencia=row[28], # C29 - TipoFraccion
|
||||
Sector=row[30], # C31 - Sector
|
||||
PaisOrigen=row[31], # C32 - PaisOrigen
|
||||
Aduana=customs_name,
|
||||
Advalorem=row[37], # C38 - EsSubPartida
|
||||
Advalorem=row[27], # C30 - Advalorem
|
||||
TipoExpo='EXPO DEF',
|
||||
PedimentoR1=rectified_pedimento,
|
||||
EDocument=row[39], # C40 - EDocument
|
||||
NumOperacionVU=row[40], # C41 - NumOperacionVU
|
||||
EDocument=row[37], # C40 - EDocument
|
||||
NumOperacionVU=row[38], # C41 - NumOperacionVU
|
||||
Series=series_info,
|
||||
Marca=row[42], # C43 - Marca
|
||||
Modelo=row[43], # C44 - Modelo
|
||||
FraccionAmericana=row[44], # C45 - FraccionAme
|
||||
ECCN=row[45], # C46 - ECCN
|
||||
FechaEmision=row[48], # C49 - FechaEmision
|
||||
Marca=StringHelper.clean_text(row[40]), # C43 - Marca
|
||||
Modelo=StringHelper.clean_text(row[41]), # C44 - Modelo
|
||||
FraccionAmericana=row[42], # C45 - FraccionAme
|
||||
ECCN=row[43], # C46 - ECCN
|
||||
FechaEmision=parse_yyyymmdd_date(row[46]) if row[46] else None, # C49 - FechaEmision
|
||||
BaseDeDatos=filters.database_name,
|
||||
NumGafUni=driver_badge,
|
||||
UsuarioCap=row[49], # C50 - UsuarioCap
|
||||
UsuarioAcr=row[50], # C51 - UsuarioAct
|
||||
Transportista=row[51], # C52 - Transportista
|
||||
NumCaja=row[52], # C53 - Transporte + NumTrasporte
|
||||
Pedimento18=row[53], # C54 - Pedimento18
|
||||
AduanaCru=row[32], # C33 - Aduana_Cruce
|
||||
Lote=row[54] # C55 - Lote
|
||||
UsuarioCap=row[47], # C50 - UsuarioCap
|
||||
UsuarioAcr=row[48], # C51 - UsuarioAct
|
||||
Transportista=row[49], # C52 - Carrier ID (derived from log.transport_id)
|
||||
NumCaja=row[50], # C53 - log.transport_id || log.transport_num
|
||||
Pedimento18=row[51], # C54 - empty
|
||||
AduanaCru=row[30], # C33 - Aduana_Cruce
|
||||
Lote=row[52] if len(row) > 52 else '' # C55 - Lote
|
||||
)
|
||||
|
||||
|
||||
movements.append(movement)
|
||||
|
||||
@@ -342,7 +353,7 @@ class ExportService:
|
||||
logger.debug("Including cancelled invoices (include_cancelled = true)")
|
||||
|
||||
# Date range
|
||||
date_field = "ih.invoice_date" if filters.range_type.value == "FF" else "log.payment_date"
|
||||
date_field = "ih.invoice_date" if filters.range_type.value == "FF" else "pd.payment_date"
|
||||
conditions.append(f"{date_field} >= TO_DATE('{filters.start_date}', 'YYYYMMDD')")
|
||||
conditions.append(f"{date_field} <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
|
||||
|
||||
@@ -102,8 +102,18 @@ class ExportRepairService:
|
||||
consecutivo = row[15] # C35 - Consecutivo
|
||||
|
||||
# Totals come directly from GROUP BY query (no N+1 problem)
|
||||
total_me = row[24] # total_me
|
||||
total_mn = row[25] # total_mn
|
||||
def to_float(val):
|
||||
if val is None or val == '': return 0.0
|
||||
try: return float(val)
|
||||
except (ValueError, TypeError): return 0.0
|
||||
|
||||
total_me = to_float(row[24]) # total_me
|
||||
total_mn = to_float(row[25]) # total_mn
|
||||
sum_value_usd = to_float(row[27])
|
||||
sum_value_mxn = to_float(row[28])
|
||||
|
||||
total_me = sum_value_usd if sum_value_usd > 0 else total_me
|
||||
total_mn = sum_value_mxn if sum_value_mxn > 0 else total_mn
|
||||
|
||||
# Calculate exchange rate and value
|
||||
valor_comercial, tipo_cambio = ExchangeRateCalculator.calculate_for_aggregated(
|
||||
@@ -294,9 +304,9 @@ class ExportRepairService:
|
||||
TipoMovTemDef=row[33], # C34 - TipoFactura
|
||||
EsCambioRegimen='N',
|
||||
Regimen=row[7], # C8 - Regimen
|
||||
Fecha_Inicio=row[8], # C9 - Fecha_Inicio
|
||||
Fecha_Fin=row[9], # C10 - Fecha_Fin
|
||||
Fecha_Pago=row[10], # C11 - Fecha_Pago
|
||||
Fecha_Inicio=parse_yyyymmdd_date(row[8]), # C9 - Fecha_Inicio
|
||||
Fecha_Fin=parse_yyyymmdd_date(row[9]), # C10 - Fecha_Fin
|
||||
Fecha_Pago=parse_yyyymmdd_date(row[10]), # C11 - Fecha_Pago
|
||||
Remesa=row[11], # C12 - Remesa
|
||||
Proveedor=proveedor_info.get('name'),
|
||||
RFCProveedor=proveedor_info.get('rfc'),
|
||||
@@ -306,7 +316,7 @@ class ExportRepairService:
|
||||
VendidoATaxID=vendido_info.get('tax_id'),
|
||||
AgenteAduanal=agente_info.get('name'),
|
||||
Patente=agente_info.get('license'),
|
||||
NumParte=row[17], # C18 - Clase (NumParte)
|
||||
NumParte=row[46], # C47 - NumParte
|
||||
DescripcionE=StringHelper.clean_text(row[18]), # C19
|
||||
DescripcionI=StringHelper.clean_text(row[19]), # C20
|
||||
CantidadIE=float(row[20]) if row[20] else 0.0, # C21
|
||||
@@ -332,7 +342,7 @@ class ExportRepairService:
|
||||
FraccionAmericana=row[44], # C45 - FraccionAme
|
||||
ECCN=row[45], # C46 - ECCN
|
||||
SimboloEx=simbolo_ex,
|
||||
FechaEmision=row[48], # C49 - FechaFactura
|
||||
FechaEmision=parse_yyyymmdd_date(row[48]) if row[48] else None, # C49 - FechaFactura
|
||||
BaseDeDatos=filters.database_name,
|
||||
NumGafUni=num_gaf_uni,
|
||||
UsuarioCap=row[49], # C50 - UsuarioCap
|
||||
@@ -341,7 +351,7 @@ class ExportRepairService:
|
||||
NumCaja=row[52], # C53 - Transporte + NumTrasporte
|
||||
Pedimento18=row[53], # C54 - Pedimento18
|
||||
AduanaCru=row[32], # C33 - Aduana_Cruce
|
||||
Lote=row[54] # C55 - Lote
|
||||
Lote=row[54] if len(row) > 54 else '' # C55 - Lote
|
||||
)
|
||||
|
||||
movements.append(movement)
|
||||
@@ -369,7 +379,7 @@ class ExportRepairService:
|
||||
if filters.range_type.value == "FF":
|
||||
where_conditions.append(f"ih.invoice_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND ih.invoice_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
else:
|
||||
where_conditions.append(f"log.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND log.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
where_conditions.append(f"pd.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND pd.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
|
||||
# Provider filter
|
||||
if filters.provider:
|
||||
@@ -391,30 +401,6 @@ class ExportRepairService:
|
||||
|
||||
return " AND ".join(where_conditions)
|
||||
|
||||
def _calculate_totals(self, db: Session, db_name: str, consecutivo: int, discharge_filter: str) -> tuple:
|
||||
"""Calculate totals for main partidas with discharge filter."""
|
||||
discharge_clause = ""
|
||||
if discharge_filter == "SiDes":
|
||||
discharge_clause = " AND il.is_discharged = true"
|
||||
elif discharge_filter == "NoDes":
|
||||
discharge_clause = " AND il.is_discharged = false"
|
||||
|
||||
sql = text(f"""
|
||||
SELECT
|
||||
COALESCE(SUM(lf.value_usd), 0),
|
||||
COALESCE(SUM(lf.value_mxn), 0)
|
||||
FROM a76.item_line_financials lf
|
||||
INNER JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
INNER JOIN a76.items itm ON itm.id = il.item_id
|
||||
WHERE itm.invoice_id = :consecutivo
|
||||
AND il.is_subpart = false
|
||||
{discharge_clause}
|
||||
""")
|
||||
|
||||
result = db.execute(sql, {"consecutivo": consecutivo}).fetchone()
|
||||
total_me = float(result[0]) if result and result[0] is not None else 0.0
|
||||
total_mn = float(result[1]) if result and result[1] is not None else 0.0
|
||||
|
||||
return total_me, total_mn
|
||||
|
||||
def _get_driver_badge(self, db: Session, db_name: str, factura: str) -> str:
|
||||
|
||||
@@ -19,9 +19,9 @@ class TemporaryImportQueries:
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END AS C4,
|
||||
COALESCE(ped.pedimento_code, '') AS C5,
|
||||
COALESCE(ped.regime, '') AS C10,
|
||||
COALESCE(TO_CHAR(log.entry_exit_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(log.delivery_date, 'YYYYMMDD'), '') AS C12,
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), '') AS C13,
|
||||
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C12,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C13,
|
||||
COALESCE(cmp.remesa, 0) AS C14,
|
||||
COALESCE(fin.exchange_rate, 0) AS C15,
|
||||
COALESCE(cmp.provider_id::text, '') AS C16,
|
||||
@@ -49,7 +49,9 @@ class TemporaryImportQueries:
|
||||
COALESCE(fin.value_mn, 0) AS total_mn,
|
||||
COALESCE(lf_agg.sum_value_mxn, 0) AS valor_comercial_mn,
|
||||
COALESCE(lf_agg.sum_value_temp_mxn, 0) AS valor_mp_temp_mn,
|
||||
COALESCE(lf_agg.sum_value_added_mxn, 0) AS valor_agre_mn
|
||||
COALESCE(lf_agg.sum_value_added_mxn, 0) AS valor_agre_mn,
|
||||
COALESCE(lf_agg.sum_value_temp_usd, 0) AS valor_mp_temp_usd,
|
||||
COALESCE(lf_agg.sum_value_usd, 0) AS sum_value_usd
|
||||
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
|
||||
@@ -62,15 +64,17 @@ class TemporaryImportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN (
|
||||
SELECT i.invoice_id,
|
||||
SELECT il.invoice_id,
|
||||
SUM(COALESCE(lf.value_mxn, 0)) AS sum_value_mxn,
|
||||
SUM(COALESCE(lf.value_temp_material_mxn, 0)) AS sum_value_temp_mxn,
|
||||
SUM(COALESCE(lf.value_added_mxn, 0)) AS sum_value_added_mxn
|
||||
FROM a76.items i
|
||||
JOIN a76.item_lines il ON il.item_id = i.id
|
||||
SUM(COALESCE(lf.value_added_mxn, 0)) AS sum_value_added_mxn,
|
||||
SUM(COALESCE(lf.value_temp_material_usd, 0)) AS sum_value_temp_usd,
|
||||
SUM(COALESCE(lf.value_usd, 0)) AS sum_value_usd
|
||||
FROM a76.item_lines il
|
||||
JOIN a76.item_line_financials lf ON lf.item_line_id = il.id
|
||||
GROUP BY i.invoice_id
|
||||
GROUP BY il.invoice_id
|
||||
) lf_agg ON lf_agg.invoice_id = ih.id
|
||||
WHERE ih.operation_type = 'imp'
|
||||
AND ih.invoice_type = 'TEM'
|
||||
@@ -95,9 +99,9 @@ class TemporaryImportQueries:
|
||||
COALESCE(prov.name, '') AS C8,
|
||||
COALESCE(client.name, '') AS C9,
|
||||
COALESCE(ped.regime, '') AS C10,
|
||||
COALESCE(TO_CHAR(log.entry_exit_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(log.delivery_date, 'YYYYMMDD'), '') AS C12,
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), '') AS C13,
|
||||
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C12,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C13,
|
||||
COALESCE(cmp.remesa, 0) AS C14,
|
||||
COALESCE(fin.exchange_rate, 0) AS C15,
|
||||
COALESCE(cmp.provider_id::text, '') AS C16,
|
||||
@@ -115,16 +119,16 @@ class TemporaryImportQueries:
|
||||
COALESCE(lf.customs_value_usd, 0) AS C28,
|
||||
COALESCE(lq.net_weight, 0) AS C29,
|
||||
COALESCE(lq.gross_weight, 0) AS C30,
|
||||
COALESCE(ih.purchase_order, '') AS C31,
|
||||
COALESCE(il.order, ih.purchase_order, '') AS C31,
|
||||
COALESCE(lc.fraction, '') AS C32,
|
||||
COALESCE(lc.fraction_type, '') AS C33,
|
||||
COALESCE(lc.advalorem_numeric, 0) AS C34,
|
||||
COALESCE(lc.sector, '') AS C35,
|
||||
COALESCE(NULLIF(lc.sector, ''), NULLIF(fap.sector, ''), '') AS C35,
|
||||
COALESCE(lf.igi_amount_usd, 0) AS C36,
|
||||
COALESCE(lc.origin_country, '') AS C37,
|
||||
COALESCE(cmp.aduana, '') AS C38,
|
||||
ih.id AS C39,
|
||||
FALSE AS C40,
|
||||
COALESCE(il.material_type, 'P') AS C40,
|
||||
COALESCE(
|
||||
ped_r1.year || '-' || ped_r1.customs_office || '-' || ped_r1.license || '-' || ped_r1.pedimento_number,
|
||||
pro_origin.original_pedimento_year || '-' || pro_origin.original_customs_office || '-' || pro_origin.original_license || '-' || pro_origin.original_pedimento_number,
|
||||
@@ -133,11 +137,11 @@ class TemporaryImportQueries:
|
||||
cmp.edocument AS C42, -- [41]
|
||||
cmp.vucem_operation_num AS C43, -- [42]
|
||||
COALESCE(il.line_number, 0) AS C44,
|
||||
'' AS C45,
|
||||
'' AS C46,
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.brand, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C45,
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.model, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C46,
|
||||
COALESCE(cls.us_fraction, '') AS C47,
|
||||
COALESCE(prt.eccn, '') AS C48,
|
||||
COALESCE(il.part_number::text, '') AS C49,
|
||||
COALESCE(prt.eccn, fac.eccn_code, '') AS C48,
|
||||
COALESCE(prt.part_number::text, '') AS C49,
|
||||
COALESCE(fin.exchange_rate, 0) AS C50,
|
||||
COALESCE(TO_CHAR(ih.emission_date, 'YYYYMMDD'), '') AS C51,
|
||||
COALESCE(ih.capture_user, '') AS C52,
|
||||
@@ -145,8 +149,10 @@ class TemporaryImportQueries:
|
||||
COALESCE(log.carrier_id, '') AS C54,
|
||||
COALESCE(log.transport_num || ' ' || log.license_plate, '') AS C55,
|
||||
'' AS C56,
|
||||
'' AS C57,
|
||||
'' AS C58
|
||||
COALESCE(ld.lot, '') AS C57,
|
||||
'' AS C58,
|
||||
COALESCE(lf.value_temp_material_mxn, 0) AS C59,
|
||||
COALESCE(lf.value_temp_material_usd, 0) AS C60
|
||||
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
|
||||
@@ -159,16 +165,18 @@ class TemporaryImportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN a76.clients_and_providers prov ON prov.id = cmp.provider_id
|
||||
LEFT JOIN a76.clients_and_providers client ON client.id = cmp.sold_to_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 a76.item_lines il ON il.invoice_id = ih.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
|
||||
LEFT JOIN a76.item_line_customs lc ON lc.item_line_id = il.id
|
||||
LEFT JOIN a76.classes cls ON cls.id = il.class_id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number
|
||||
LEFT JOIN a24.fa_classes fac ON fac.class_id = cls.id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number_id
|
||||
LEFT JOIN a24.fa_partes fap ON fap.id = prt.id
|
||||
LEFT JOIN a76.units_of_measure um ON um.id = il.unit_of_measure
|
||||
WHERE ih.operation_type = 'imp'
|
||||
AND ih.invoice_type = 'TEM'
|
||||
@@ -225,9 +233,9 @@ class DefinitiveImportQueries:
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END AS C4,
|
||||
COALESCE(ped.pedimento_code, '') AS C5,
|
||||
COALESCE(ped.regime, '') AS C10,
|
||||
COALESCE(TO_CHAR(log.entry_exit_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(log.delivery_date, 'YYYYMMDD'), '') AS C12,
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), '') AS C13,
|
||||
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C12,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C13,
|
||||
COALESCE(log.payment_receipt_num, '') AS C14,
|
||||
COALESCE(fin.exchange_rate, 0) AS C15,
|
||||
COALESCE(cmp.provider_id::text, '') AS C16,
|
||||
@@ -252,7 +260,9 @@ class DefinitiveImportQueries:
|
||||
'' AS C58,
|
||||
'' AS C59,
|
||||
COALESCE(fin.value_me, 0) AS total_me,
|
||||
COALESCE(fin.value_mn, 0) AS total_mn
|
||||
COALESCE(fin.value_mn, 0) AS total_mn,
|
||||
COALESCE(lf_agg.sum_value_usd, 0) AS sum_value_usd,
|
||||
COALESCE(lf_agg.sum_value_mxn, 0) AS sum_value_mxn
|
||||
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
|
||||
@@ -265,6 +275,16 @@ class DefinitiveImportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN (
|
||||
SELECT il.invoice_id,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_mxn, 0) END) AS sum_value_mxn,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_usd, 0) END) AS sum_value_usd
|
||||
FROM a76.item_lines il
|
||||
JOIN a76.item_line_financials lf ON lf.item_line_id = il.id
|
||||
LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id
|
||||
GROUP BY il.invoice_id
|
||||
) lf_agg ON lf_agg.invoice_id = ih.id
|
||||
WHERE ih.operation_type = 'imp'
|
||||
AND ih.invoice_type IN ('DEF', 'EXDEF', 'MATDE')
|
||||
AND {where_clause}
|
||||
@@ -273,70 +293,73 @@ class DefinitiveImportQueries:
|
||||
|
||||
@staticmethod
|
||||
def build_main_query(db_name: str, where_clause: str) -> str:
|
||||
"""Build main SQL query for DETAILED mode (all partidas) from PostgreSQL for definitive imports."""
|
||||
return f"""
|
||||
SELECT
|
||||
ih.invoice_number AS C1, -- [0]
|
||||
ped.pedimento_number AS C2, -- [1]
|
||||
ih.invoice_date AS C3, -- [2]
|
||||
ped.status AS C4, -- [3]
|
||||
ped.pedimento_code AS C5, -- [4]
|
||||
'' AS C6, -- [5]
|
||||
'' AS C7, -- [6]
|
||||
COALESCE(prov.name, '') AS C8, -- [7] Provider name
|
||||
COALESCE(client.name, '') AS C9, -- [8] Client name
|
||||
ped.regime AS C10, -- [9]
|
||||
log.entry_exit_date AS C11, -- [10]
|
||||
log.delivery_date AS C12, -- [11]
|
||||
log.payment_date AS C13, -- [12]
|
||||
log.payment_receipt_num AS C14, -- [13]
|
||||
'' AS C15, -- [14]
|
||||
cmp.provider_id AS C16, -- [15]
|
||||
cmp.sold_to_id AS C17, -- [16]
|
||||
cmp.customs_broker_id AS C18, -- [17]
|
||||
'' AS C19, -- [18]
|
||||
prt.part_number AS C20, -- [19]
|
||||
ld.description_spanish AS C21, -- [20]
|
||||
ld.description_english AS C22, -- [21]
|
||||
lq.quantity AS C23, -- [22]
|
||||
um.code AS C24, -- [23]
|
||||
lf.value_mxn AS C25, -- [24]
|
||||
'' AS C26, -- [25]
|
||||
lf.value_usd AS C27, -- [26]
|
||||
'' AS C28, -- [27]
|
||||
lq.net_weight AS C29, -- [28]
|
||||
lq.gross_weight AS C30, -- [29]
|
||||
ih.purchase_order AS C31, -- [30]
|
||||
lc.fraction AS C32, -- [31]
|
||||
'' AS C33, '' AS C34, -- [32-33]
|
||||
ih.id AS C35, -- [34]
|
||||
'' AS C36, '' AS C37, -- [35-36]
|
||||
lc.origin_country AS C38, -- [37]
|
||||
cmp.aduana AS C39, -- [38]
|
||||
il.material_type AS C40, -- [39]
|
||||
il.id AS C41, -- [40]
|
||||
ih.invoice_number AS C1,
|
||||
COALESCE(ped.pedimento_number, '') AS C2,
|
||||
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END AS C4,
|
||||
COALESCE(ped.pedimento_code, '') AS C5,
|
||||
COALESCE(fin.value_me, 0) AS C6,
|
||||
COALESCE(fin.value_mn, 0) AS C7,
|
||||
COALESCE(prov.name, '') AS C8,
|
||||
COALESCE(client.name, '') AS C9,
|
||||
COALESCE(ped.regime, '') AS C10,
|
||||
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C12,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C13,
|
||||
COALESCE(log.payment_receipt_num, '') AS C14,
|
||||
COALESCE(fin.exchange_rate, 0) AS C15,
|
||||
COALESCE(cmp.provider_id::text, '') AS C16,
|
||||
COALESCE(cmp.sold_to_id::text, '') AS C17,
|
||||
COALESCE(cmp.customs_broker_id::text, '') AS C18,
|
||||
'' AS C19,
|
||||
COALESCE(il.class_id::text, '') AS C20,
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.description_spanish, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C21,
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.description_english, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C22,
|
||||
COALESCE(lq.quantity, 0) AS C23,
|
||||
COALESCE(um.code, '') AS C24,
|
||||
COALESCE(lf.value_mxn, 0) AS C25,
|
||||
COALESCE(lf.customs_value_mxn, 0) AS C26,
|
||||
COALESCE(lf.value_usd, 0) AS C27,
|
||||
COALESCE(lf.customs_value_usd, 0) AS C28,
|
||||
COALESCE(lq.net_weight, 0) AS C29,
|
||||
COALESCE(lq.gross_weight, 0) AS C30,
|
||||
COALESCE(il.order, ih.purchase_order, '') AS C31,
|
||||
COALESCE(lc.fraction, '') AS C32,
|
||||
COALESCE(lc.fraction_type, '') AS C33,
|
||||
COALESCE(lc.advalorem_numeric, 0) AS C34,
|
||||
COALESCE(NULLIF(lc.sector, ''), NULLIF(fap.sector, ''), '') AS C35,
|
||||
COALESCE(lf.igi_amount_usd, 0) AS C36,
|
||||
COALESCE(lc.origin_country, '') AS C37,
|
||||
COALESCE(cmp.aduana, '') AS C38,
|
||||
ih.id AS C39,
|
||||
COALESCE(il.material_type, 'P') AS C40,
|
||||
COALESCE(
|
||||
ped_r1.year || '-' || ped_r1.customs_office || '-' || ped_r1.license || '-' || ped_r1.pedimento_number,
|
||||
pro_origin.original_pedimento_year || '-' || pro_origin.original_customs_office || '-' || pro_origin.original_license || '-' || pro_origin.original_pedimento_number,
|
||||
''
|
||||
) AS C42, -- [41] rectification_id
|
||||
cmp.edocument AS C43, -- [42]
|
||||
cmp.vucem_operation_num AS C44, -- [43]
|
||||
il.line_number AS C45, -- [44]
|
||||
ld.brand AS C46, -- [45]
|
||||
ld.model AS C47, -- [46]
|
||||
prt.us_fraction AS C48, -- [47]
|
||||
prt.eccn AS C49, -- [48]
|
||||
prt.id AS C50, -- [49]
|
||||
fin.exchange_rate AS C51, -- [50]
|
||||
ih.emission_date AS C52, -- [51]
|
||||
ih.capture_user AS C53, -- [52]
|
||||
ih.who_updated AS C54, -- [53]
|
||||
'' AS C55, -- [54]
|
||||
COALESCE(log.transport_id || ' ' || log.transport_num, '') AS C56, -- [55]
|
||||
'' AS C57, -- [56] Pedimento18 (row[56])
|
||||
COALESCE(ld.lot, '') AS C58, -- [57] Lote (row[57])
|
||||
'' AS C59, -- [58] TipoPed (row[58])
|
||||
'' AS C60 -- [59] Relleno final
|
||||
) AS C41,
|
||||
cmp.edocument AS C42,
|
||||
cmp.vucem_operation_num AS C43,
|
||||
COALESCE(il.line_number, 0) AS C44,
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.brand, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C45,
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.model, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C46,
|
||||
COALESCE(cls.us_fraction, '') AS C47,
|
||||
COALESCE(prt.eccn, fac.eccn_code, '') AS C48,
|
||||
COALESCE(prt.part_number::text, '') AS C49,
|
||||
COALESCE(fin.exchange_rate, 0) AS C50,
|
||||
COALESCE(TO_CHAR(ih.emission_date, 'YYYYMMDD'), '') AS C51,
|
||||
COALESCE(ih.capture_user, '') AS C52,
|
||||
COALESCE(ih.who_updated, '') AS C53,
|
||||
COALESCE(log.carrier_id, '') AS C54,
|
||||
COALESCE(log.transport_id || ' ' || log.transport_num, '') AS C55,
|
||||
'' AS C56,
|
||||
COALESCE(ld.lot, '') AS C57,
|
||||
'' AS C58,
|
||||
0 AS C59,
|
||||
0 AS C60
|
||||
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
|
||||
@@ -349,16 +372,18 @@ class DefinitiveImportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN a76.clients_and_providers prov ON prov.id = cmp.provider_id
|
||||
LEFT JOIN a76.clients_and_providers client ON client.id = cmp.sold_to_id
|
||||
LEFT JOIN a76.items itm ON itm.invoice_id = ih.id
|
||||
LEFT JOIN a76.item_lines il ON il.item_id = itm.id
|
||||
LEFT JOIN a76.item_lines il ON il.invoice_id = ih.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
|
||||
LEFT JOIN a76.item_line_customs lc ON lc.item_line_id = il.id
|
||||
LEFT JOIN a76.classes cls ON cls.id = il.class_id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number
|
||||
LEFT JOIN a24.fa_classes fac ON fac.class_id = cls.id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number_id
|
||||
LEFT JOIN a24.fa_partes fap ON fap.id = prt.id
|
||||
LEFT JOIN a76.units_of_measure um ON um.id = il.unit_of_measure
|
||||
WHERE {where_clause}
|
||||
ORDER BY ih.invoice_number, il.line_number
|
||||
@@ -374,8 +399,7 @@ class DefinitiveImportQueries:
|
||||
FROM a76.item_line_financials lf
|
||||
INNER JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id
|
||||
INNER JOIN a76.items itm ON itm.id = il.item_id
|
||||
WHERE itm.invoice_id = :consecutivo
|
||||
WHERE il.invoice_id = :consecutivo
|
||||
|
||||
"""
|
||||
|
||||
@@ -425,7 +449,7 @@ class RepairImportQueries:
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END AS C5,
|
||||
COALESCE(ped.pedimento_code, '') AS C6,
|
||||
COALESCE(ped.regime, '') AS C7,
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), '') AS C9,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C9,
|
||||
COALESCE(cmp.remesa::text, '') AS C10,
|
||||
COALESCE(fin.exchange_rate, 0) AS C11,
|
||||
COALESCE(cmp.provider_id::text, '') AS C12,
|
||||
@@ -449,7 +473,9 @@ class RepairImportQueries:
|
||||
ped_r1.year || '-' || ped_r1.customs_office || '-' || ped_r1.license || '-' || ped_r1.pedimento_number,
|
||||
pro_origin.original_pedimento_year || '-' || pro_origin.original_customs_office || '-' || pro_origin.original_license || '-' || pro_origin.original_pedimento_number,
|
||||
''
|
||||
) AS C48
|
||||
) AS C48,
|
||||
COALESCE(lf_agg.sum_value_usd, 0) AS sum_value_usd,
|
||||
COALESCE(lf_agg.sum_value_mxn, 0) AS sum_value_mxn
|
||||
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
|
||||
@@ -462,13 +488,23 @@ class RepairImportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN (
|
||||
SELECT il.invoice_id,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_mxn, 0) END) AS sum_value_mxn,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_usd, 0) END) AS sum_value_usd
|
||||
FROM a76.item_lines il
|
||||
JOIN a76.item_line_financials lf ON lf.item_line_id = il.id
|
||||
LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id
|
||||
WHERE 1=1 {discharge_filter}
|
||||
GROUP BY il.invoice_id
|
||||
) lf_agg ON lf_agg.invoice_id = ih.id
|
||||
WHERE ih.operation_type = 'imp'
|
||||
AND COALESCE(cmp.is_regime_change, false) = false
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM a76.items i2
|
||||
INNER JOIN a76.item_lines il2 ON il2.item_id = i2.id
|
||||
SELECT 1 FROM a76.item_lines il2
|
||||
INNER JOIN a24.fa_item_lines fil2 ON fil2.id = il2.id
|
||||
WHERE i2.invoice_id = ih.id AND fil2.search_invoice IS NOT NULL
|
||||
WHERE il2.invoice_id = ih.id AND fil2.search_invoice IS NOT NULL
|
||||
{discharge_filter}
|
||||
)
|
||||
{"AND " + where_str if where_str else ""}
|
||||
@@ -494,14 +530,15 @@ class RepairImportQueries:
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END,
|
||||
COALESCE(ped.pedimento_code, ''),
|
||||
COALESCE(ped.regime, ''),
|
||||
'',
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), ''),
|
||||
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), ''),
|
||||
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), ''),
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), ''),
|
||||
COALESCE(cmp.remesa::text, ''),
|
||||
COALESCE(fin.exchange_rate, 0),
|
||||
COALESCE(cmp.provider_id::text, ''),
|
||||
COALESCE(cmp.sold_to_id::text, ''),
|
||||
COALESCE(cmp.customs_broker_id::text, ''),
|
||||
COALESCE(il.part_number::text, ''),
|
||||
COALESCE(prt.part_number::text, ''),
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.description_spanish, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' '),
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.description_english, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' '),
|
||||
COALESCE(lq.quantity, 0),
|
||||
@@ -510,14 +547,14 @@ class RepairImportQueries:
|
||||
COALESCE(lf.value_usd, 0),
|
||||
COALESCE(lq.net_weight, 0),
|
||||
COALESCE(lq.gross_weight, 0),
|
||||
COALESCE(ih.purchase_order, ''),
|
||||
COALESCE(il.order, ih.purchase_order, ''),
|
||||
COALESCE(lc.fraction, ''),
|
||||
'',
|
||||
COALESCE(lc.sector, ''),
|
||||
COALESCE(NULLIF(lc.sector, ''), NULLIF(fap.sector, ''), ''),
|
||||
COALESCE(lc.origin_country, ''),
|
||||
COALESCE(ped.customs_office, ''),
|
||||
ih.id,
|
||||
'P',
|
||||
COALESCE(il.material_type, 'P'),
|
||||
COALESCE(
|
||||
ped_r1.year || '-' || ped_r1.customs_office || '-' || ped_r1.license || '-' || ped_r1.pedimento_number,
|
||||
pro_origin.original_pedimento_year || '-' || pro_origin.original_customs_office || '-' || pro_origin.original_license || '-' || pro_origin.original_pedimento_number,
|
||||
@@ -528,7 +565,7 @@ class RepairImportQueries:
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.brand, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' '),
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.model, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' '),
|
||||
COALESCE(lc.american_fraction, ''),
|
||||
COALESCE(prt.eccn, ''),
|
||||
COALESCE(prt.eccn, fac.eccn_code, ''),
|
||||
COALESCE(fin.exchange_rate, 0),
|
||||
COALESCE(TO_CHAR(ih.emission_date, 'YYYYMMDD'), ''),
|
||||
COALESCE(ih.capture_user, ''),
|
||||
@@ -549,14 +586,17 @@ class RepairImportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.items itm ON itm.invoice_id = ih.id
|
||||
LEFT JOIN a76.item_lines il ON il.item_id = itm.id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN a76.item_lines il ON il.invoice_id = ih.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
|
||||
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.classes cls ON cls.id = il.class_id
|
||||
LEFT JOIN a24.fa_classes fac ON fac.class_id = cls.id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number_id
|
||||
LEFT JOIN a24.fa_partes fap ON fap.id = prt.id
|
||||
LEFT JOIN a76.units_of_measure um ON um.id = il.unit_of_measure
|
||||
WHERE ih.operation_type = 'imp'
|
||||
AND COALESCE(cmp.is_regime_change, false) = false
|
||||
@@ -583,8 +623,7 @@ class RepairImportQueries:
|
||||
FROM a76.item_line_financials lf
|
||||
INNER JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id
|
||||
INNER JOIN a76.items itm ON itm.id = il.item_id
|
||||
WHERE itm.invoice_id = :consecutivo
|
||||
WHERE il.invoice_id = :consecutivo
|
||||
|
||||
{discharge_filter}
|
||||
"""
|
||||
@@ -628,9 +667,8 @@ class ExportQueries:
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END AS C6,
|
||||
COALESCE(ped.pedimento_code, '') AS C7,
|
||||
COALESCE(ped.regime, '') AS C8,
|
||||
COALESCE(TO_CHAR(log.entry_exit_date, 'YYYYMMDD'), '') AS C9,
|
||||
COALESCE(TO_CHAR(log.delivery_date, 'YYYYMMDD'), '') AS C10,
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C10,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(log.payment_receipt_num, '') AS C12,
|
||||
COALESCE(cmp.provider_id::text, '') AS C14,
|
||||
COALESCE(cmp.sold_to_id::text, '') AS C15,
|
||||
@@ -652,7 +690,9 @@ class ExportQueries:
|
||||
ped_r1.year || '-' || ped_r1.customs_office || '-' || ped_r1.license || '-' || ped_r1.pedimento_number,
|
||||
pro_origin.original_pedimento_year || '-' || pro_origin.original_customs_office || '-' || pro_origin.original_license || '-' || pro_origin.original_pedimento_number,
|
||||
''
|
||||
) AS C54
|
||||
) AS C54,
|
||||
COALESCE(lf_agg.sum_value_usd, 0) AS sum_value_usd,
|
||||
COALESCE(lf_agg.sum_value_mxn, 0) AS sum_value_mxn
|
||||
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
|
||||
@@ -665,6 +705,16 @@ class ExportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN (
|
||||
SELECT il.invoice_id,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_mxn, 0) END) AS sum_value_mxn,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_usd, 0) END) AS sum_value_usd
|
||||
FROM a76.item_lines il
|
||||
JOIN a76.item_line_financials lf ON lf.item_line_id = il.id
|
||||
LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id
|
||||
GROUP BY il.invoice_id
|
||||
) lf_agg ON lf_agg.invoice_id = ih.id
|
||||
WHERE {where_clause}
|
||||
ORDER BY ih.invoice_number
|
||||
"""
|
||||
@@ -677,34 +727,32 @@ class ExportQueries:
|
||||
ped.pedimento_number AS C2, -- [1]
|
||||
ih.invoice_date AS C3, -- [2]
|
||||
'' AS C4, -- [3]
|
||||
'' AS C5, -- [4]
|
||||
ped.status AS C6, -- [5]
|
||||
ped.pedimento_code AS C7, -- [6]
|
||||
ped.regime AS C8, -- [7]
|
||||
log.entry_exit_date AS C9, -- [8]
|
||||
log.delivery_date AS C10, -- [9]
|
||||
log.payment_date AS C11, -- [10]
|
||||
ped.pedimento_code AS C5, -- [4]
|
||||
ped.regime AS C6, -- [5]
|
||||
pd.entry_date AS C7, -- [6]
|
||||
COALESCE(pd.end_date, pd.payment_date) AS C8, -- [7]
|
||||
pd.payment_date AS C9, -- [8]
|
||||
log.payment_receipt_num AS C12, -- [11]
|
||||
'' AS C13, -- [12]
|
||||
cmp.provider_id AS C14, -- [13]
|
||||
cmp.sold_to_id AS C15, -- [14]
|
||||
cmp.customs_broker_id AS C16, -- [15]
|
||||
'' AS C17, -- [16]
|
||||
prt.part_number AS C18, -- [17]
|
||||
ld.description_spanish AS C19, -- [18]
|
||||
ld.description_english AS C20, -- [19]
|
||||
COALESCE(prt.part_number::text, '') AS C18, -- [17]
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.description_spanish, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C19, -- [18]
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.description_english, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C20, -- [19]
|
||||
lq.quantity AS C21, -- [20]
|
||||
um.code AS C22, -- [21]
|
||||
'' AS C23, -- [22]
|
||||
'' AS C24, -- [23]
|
||||
lq.net_weight AS C25, -- [24]
|
||||
lq.gross_weight AS C26, -- [25]
|
||||
ih.purchase_order AS C27, -- [26]
|
||||
lc.fraction AS C28, -- [27]
|
||||
'' AS C29, -- [28]
|
||||
'' AS C30, -- [29]
|
||||
'' AS C31, -- [30]
|
||||
'' AS C32, -- [31]
|
||||
COALESCE(lq.net_weight, 0) AS C25, -- [24]
|
||||
COALESCE(lq.gross_weight, 0) AS C26, -- [25]
|
||||
COALESCE(il.order, ih.purchase_order, '') AS C27, -- [26]
|
||||
COALESCE(lc.fraction, '') AS C28, -- [27]
|
||||
COALESCE(lc.fraction_type, '') AS C29, -- [28]
|
||||
COALESCE(lc.advalorem_numeric, 0) AS C30, -- [29]
|
||||
COALESCE(NULLIF(lc.sector, ''), NULLIF(fap.sector, ''), '') AS C31, -- [30]
|
||||
COALESCE(lc.origin_country, '') AS C32, -- [31]
|
||||
cmp.aduana AS C33, -- [32]
|
||||
ih.invoice_type AS C34, -- [33]
|
||||
ih.id AS C35, -- [34]
|
||||
@@ -719,10 +767,10 @@ class ExportQueries:
|
||||
cmp.edocument AS C40, -- [39]
|
||||
cmp.vucem_operation_num AS C41, -- [40]
|
||||
il.line_number AS C42, -- [41]
|
||||
ld.brand AS C43, -- [42]
|
||||
ld.model AS C44, -- [43]
|
||||
prt.us_fraction AS C45, -- [44]
|
||||
prt.eccn AS C46, -- [45]
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.brand, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C43, -- [42]
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.model, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C44, -- [43]
|
||||
COALESCE(cls.us_fraction, '') AS C45, -- [44]
|
||||
COALESCE(prt.eccn, fac.eccn_code, '') AS C46, -- [45]
|
||||
prt.id AS C47, -- [46]
|
||||
fin.exchange_rate AS C48, -- [47]
|
||||
ih.emission_date AS C49, -- [48]
|
||||
@@ -749,14 +797,16 @@ class ExportQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.items itm ON itm.invoice_id = ih.id
|
||||
LEFT JOIN a76.item_lines il ON il.item_id = itm.id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN a76.item_lines il ON il.invoice_id = ih.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
|
||||
LEFT JOIN a76.item_line_customs lc ON lc.item_line_id = il.id
|
||||
LEFT JOIN a76.classes cls ON cls.id = il.class_id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number
|
||||
LEFT JOIN a24.fa_classes fac ON fac.class_id = cls.id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number_id
|
||||
LEFT JOIN a24.fa_partes fap ON fap.id = prt.id
|
||||
LEFT JOIN a76.units_of_measure um ON um.id = il.unit_of_measure
|
||||
WHERE {where_clause}
|
||||
ORDER BY ih.invoice_number, il.line_number
|
||||
@@ -782,8 +832,7 @@ class ExportQueries:
|
||||
FROM a76.item_line_financials lf
|
||||
INNER JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id
|
||||
INNER JOIN a76.items itm ON itm.id = il.item_id
|
||||
WHERE itm.invoice_id = :consecutivo
|
||||
WHERE il.invoice_id = :consecutivo
|
||||
{discharge_filter}
|
||||
"""
|
||||
|
||||
@@ -828,7 +877,7 @@ class ExportRepairQueries:
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END AS C6,
|
||||
COALESCE(ped.pedimento_code, '') AS C7,
|
||||
COALESCE(ped.regime, '') AS C8,
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(cmp.remesa::text, '') AS C12,
|
||||
COALESCE(fin.exchange_rate, 0) AS C13,
|
||||
COALESCE(cmp.provider_id::text, '') AS C14,
|
||||
@@ -852,7 +901,9 @@ class ExportRepairQueries:
|
||||
ped_r1.year || '-' || ped_r1.customs_office || '-' || ped_r1.license || '-' || ped_r1.pedimento_number,
|
||||
pro_origin.original_pedimento_year || '-' || pro_origin.original_customs_office || '-' || pro_origin.original_license || '-' || pro_origin.original_pedimento_number,
|
||||
''
|
||||
) AS C54
|
||||
) AS C54,
|
||||
COALESCE(lf_agg.sum_value_usd, 0) AS sum_value_usd,
|
||||
COALESCE(lf_agg.sum_value_mxn, 0) AS sum_value_mxn
|
||||
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
|
||||
@@ -865,6 +916,17 @@ class ExportRepairQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN (
|
||||
SELECT il.invoice_id,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_mxn, 0) END) AS sum_value_mxn,
|
||||
SUM(CASE WHEN COALESCE(fil.is_subitem, false) THEN 0 ELSE COALESCE(lf.value_usd, 0) END) AS sum_value_usd
|
||||
FROM a76.item_lines il
|
||||
JOIN a76.item_line_financials lf ON lf.item_line_id = il.id
|
||||
LEFT JOIN a24.fa_item_lines fil ON fil.id = il.id
|
||||
WHERE 1=1 {discharge_filter}
|
||||
GROUP BY il.invoice_id
|
||||
) lf_agg ON lf_agg.invoice_id = ih.id
|
||||
WHERE ih.operation_type = 'exp'
|
||||
AND ih.invoice_type = 'REPAR'
|
||||
{"AND " + where_str if where_str else ""}
|
||||
@@ -884,9 +946,9 @@ class ExportRepairQueries:
|
||||
CASE WHEN ih.is_updated THEN 'AC' ELSE 'NA' END AS C6,
|
||||
COALESCE(ped.pedimento_code, '') AS C7,
|
||||
COALESCE(ped.regime, '') AS C8,
|
||||
'' AS C9,
|
||||
'' AS C10,
|
||||
COALESCE(TO_CHAR(log.payment_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C9,
|
||||
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C10,
|
||||
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C11,
|
||||
COALESCE(cmp.remesa::text, '') AS C12,
|
||||
COALESCE(fin.exchange_rate, 0) AS C13,
|
||||
COALESCE(cmp.provider_id::text, '') AS C14,
|
||||
@@ -902,18 +964,18 @@ class ExportRepairQueries:
|
||||
COALESCE(lf.customs_value_usd, 0) AS C24,
|
||||
COALESCE(lq.net_weight, 0) AS C25,
|
||||
COALESCE(lq.gross_weight, 0) AS C26,
|
||||
COALESCE(ih.purchase_order, '') AS C27,
|
||||
COALESCE(il.order, ih.purchase_order, '') AS C27,
|
||||
COALESCE(lc.fraction, '') AS C28,
|
||||
COALESCE(lc.fraction_type, '') AS C29,
|
||||
COALESCE(lc.advalorem_numeric, 0) AS C30,
|
||||
COALESCE(lc.sector, '') AS C31,
|
||||
COALESCE(NULLIF(lc.sector, ''), NULLIF(fap.sector, ''), '') AS C31,
|
||||
COALESCE(lc.origin_country, '') AS C32,
|
||||
COALESCE(ped.customs_office, '') AS C33,
|
||||
COALESCE(ih.document_type, '') AS C34,
|
||||
ih.id AS C35,
|
||||
COALESCE(lf.value_mxn, 0) AS C36,
|
||||
COALESCE(lf.value_usd, 0) AS C37,
|
||||
'P' AS C38,
|
||||
COALESCE(il.material_type, 'P') AS C38,
|
||||
COALESCE(
|
||||
ped_r1.year || '-' || ped_r1.customs_office || '-' || ped_r1.license || '-' || ped_r1.pedimento_number,
|
||||
pro_origin.original_pedimento_year || '-' || pro_origin.original_customs_office || '-' || pro_origin.original_license || '-' || pro_origin.original_pedimento_number,
|
||||
@@ -925,8 +987,8 @@ class ExportRepairQueries:
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.brand, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C43,
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(ld.model, ''), CHR(44), ' '), CHR(9), ' '), CHR(10), ' '), CHR(13), ' ') AS C44,
|
||||
COALESCE(cls.us_fraction, '') AS C45,
|
||||
COALESCE(prt.eccn, '') AS C46,
|
||||
COALESCE(il.part_number::text, '') AS C47,
|
||||
COALESCE(prt.eccn, fac.eccn_code, '') AS C46,
|
||||
COALESCE(prt.part_number::text, '') AS C47,
|
||||
COALESCE(fin.exchange_rate, 0) AS C48,
|
||||
COALESCE(TO_CHAR(ih.invoice_date, 'YYYYMMDD'), '') AS C49,
|
||||
COALESCE(ih.capture_user, '') AS C50,
|
||||
@@ -951,14 +1013,16 @@ class ExportRepairQueries:
|
||||
pro_rect.original_license = ped.license AND
|
||||
pro_rect.original_pedimento_number = ped.pedimento_number
|
||||
LEFT JOIN a76.pedimentos ped_r1 ON ped_r1.id = pro_rect.pedimento_id
|
||||
LEFT JOIN a76.items itm ON itm.invoice_id = ih.id
|
||||
LEFT JOIN a76.item_lines il ON il.item_id = itm.id
|
||||
LEFT JOIN a76.pedimento_dates pd ON pd.pedimento_id = ped.id
|
||||
LEFT JOIN a76.item_lines il ON il.invoice_id = ih.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
|
||||
LEFT JOIN a76.item_line_customs lc ON lc.item_line_id = il.id
|
||||
LEFT JOIN a76.classes cls ON cls.id = il.class_id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number
|
||||
LEFT JOIN a24.fa_classes fac ON fac.class_id = cls.id
|
||||
LEFT JOIN a76.parts prt ON prt.id = il.part_number_id
|
||||
LEFT JOIN a24.fa_partes fap ON fap.id = prt.id
|
||||
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', 'REPAR', 'EXDEF', 'MATDE')
|
||||
@@ -983,7 +1047,7 @@ class ExportRepairQueries:
|
||||
FROM a76.item_line_financials lf
|
||||
INNER JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
LEFT JOIN a24.fa_item_lines fil ON il.id = lf.item_line_id
|
||||
WHERE itm.invoice_id = :consecutivo
|
||||
WHERE il.invoice_id = :consecutivo
|
||||
|
||||
{discharge_filter}
|
||||
"""
|
||||
|
||||
@@ -93,6 +93,11 @@ class RepairImportService:
|
||||
# Totals come directly from GROUP BY query (no N+1 problem)
|
||||
total_me = to_float(row[24]) # total_me from SUM aggregation
|
||||
total_mn = to_float(row[25]) # total_mn from SUM aggregation
|
||||
sum_value_usd = to_float(row[27])
|
||||
sum_value_mxn = to_float(row[28])
|
||||
|
||||
total_me = sum_value_usd if sum_value_usd > 0 else total_me
|
||||
total_mn = sum_value_mxn if sum_value_mxn > 0 else total_mn
|
||||
|
||||
# Calculate exchange rate and value
|
||||
valor_comercial, tipo_cambio = ExchangeRateCalculator.calculate_for_aggregated(
|
||||
@@ -228,8 +233,8 @@ class RepairImportService:
|
||||
db=db,
|
||||
db_name=filters.database_name,
|
||||
es_subpartida=row[30], # 'P' or 'S'
|
||||
valor_me=row[20],
|
||||
valor_mn_direct=row[19],
|
||||
valor_me=row[21],
|
||||
valor_mn_direct=row[20],
|
||||
fecha_pago=row[8],
|
||||
fecha_inicio=row[7],
|
||||
clave_ped=row[45],
|
||||
@@ -240,9 +245,9 @@ class RepairImportService:
|
||||
)
|
||||
|
||||
# Set peso values based on subpartida flag
|
||||
if row[30] == 'P':
|
||||
peso_neto = float(row[21]) if row[21] else 0.0
|
||||
peso_bruto = float(row[22]) if row[22] else 0.0
|
||||
if row[31] == 'P':
|
||||
peso_neto = float(row[22]) if row[22] else 0.0
|
||||
peso_bruto = float(row[23]) if row[23] else 0.0
|
||||
else:
|
||||
peso_neto = 0.0
|
||||
peso_bruto = 0.0
|
||||
@@ -252,9 +257,9 @@ class RepairImportService:
|
||||
)
|
||||
|
||||
simbolo_ex = None
|
||||
if row[14]:
|
||||
if row[15]:
|
||||
simbolo_ex = DatabaseHelper.get_part_export_symbol(
|
||||
db, filters.database_name, row[14], filters.is_shelter
|
||||
db, filters.database_name, row[15], filters.is_shelter
|
||||
)
|
||||
|
||||
pedimento_r1 = DatabaseHelper.get_rectification_pedimento(
|
||||
@@ -275,10 +280,10 @@ class RepairImportService:
|
||||
TipoMovTemDef='IMPRE',
|
||||
EsCambioRegimen='N',
|
||||
Regimen=row[6],
|
||||
Fecha_Inicio=row[7],
|
||||
Fecha_Fin=row[7], # Using same valid column or empty
|
||||
Fecha_Pago=row[8],
|
||||
Remesa=row[9],
|
||||
Fecha_Inicio=parse_yyyymmdd_date(row[7]),
|
||||
Fecha_Fin=parse_yyyymmdd_date(row[8]),
|
||||
Fecha_Pago=parse_yyyymmdd_date(row[9]),
|
||||
Remesa=row[10],
|
||||
Proveedor=proveedor_info.get('name'),
|
||||
RFCProveedor=proveedor_info.get('rfc'),
|
||||
ProveedorTaxID=proveedor_info.get('tax_id'),
|
||||
@@ -287,42 +292,42 @@ class RepairImportService:
|
||||
VendidoATaxID=vendido_info.get('tax_id'),
|
||||
AgenteAduanal=agente_info.get('name'),
|
||||
Patente=agente_info.get('license'),
|
||||
NumParte=row[14],
|
||||
DescripcionE=StringHelper.clean_text(row[15]),
|
||||
DescripcionI=StringHelper.clean_text(row[16]),
|
||||
CantidadIE=float(row[17]) if row[17] else 0.0,
|
||||
UniMed=row[18],
|
||||
NumParte=row[15],
|
||||
DescripcionE=StringHelper.clean_text(row[16]),
|
||||
DescripcionI=StringHelper.clean_text(row[17]),
|
||||
CantidadIE=float(row[18]) if row[18] else 0.0,
|
||||
UniMed=row[19],
|
||||
ValorComercialMN=valor_comercial,
|
||||
TipoCambio=tipo_cambio,
|
||||
PesoNeto=peso_neto,
|
||||
PesoBruto=peso_bruto,
|
||||
OrdenCompraVenta=row[23],
|
||||
FraccionArancelaria=row[24],
|
||||
Preferencia=row[25],
|
||||
Sector=row[26],
|
||||
PaisOrigen=row[27],
|
||||
OrdenCompraVenta=row[24],
|
||||
FraccionArancelaria=row[25],
|
||||
Preferencia=row[26],
|
||||
Sector=row[27],
|
||||
PaisOrigen=row[28],
|
||||
Aduana=aduana_nombre,
|
||||
Advalorem=row[30],
|
||||
Advalorem='',
|
||||
TipoExpo='',
|
||||
PedimentoR1=pedimento_r1,
|
||||
EDocument=row[32],
|
||||
NumOperacionVU=row[33],
|
||||
EDocument=row[33],
|
||||
NumOperacionVU=row[34],
|
||||
Series=series_info,
|
||||
Marca=StringHelper.clean_text(row[34]),
|
||||
Modelo=StringHelper.clean_text(row[35]),
|
||||
FraccionAmericana=row[36],
|
||||
ECCN=row[37],
|
||||
Marca=StringHelper.clean_text(row[35]),
|
||||
Modelo=StringHelper.clean_text(row[36]),
|
||||
FraccionAmericana=row[37],
|
||||
ECCN=row[38],
|
||||
SimboloEx=simbolo_ex,
|
||||
FechaEmision=row[39],
|
||||
FechaEmision=parse_yyyymmdd_date(row[40]) if row[40] else None, # C41 - FechaEmision
|
||||
BaseDeDatos=filters.database_name,
|
||||
NumGafUni=num_gaf_uni,
|
||||
UsuarioCap=row[40],
|
||||
UsuarioAcr=row[41],
|
||||
Transportista=row[42],
|
||||
NumCaja=row[43],
|
||||
Pedimento18=row[44],
|
||||
AduanaCru=row[28],
|
||||
Lote='' # Not in query
|
||||
UsuarioCap=row[41],
|
||||
UsuarioAcr=row[42],
|
||||
Transportista=row[43],
|
||||
NumCaja=row[44],
|
||||
Pedimento18=row[45],
|
||||
AduanaCru=row[29],
|
||||
Lote=row[54] if len(row) > 54 else '' # Not in query but mapped safely
|
||||
)
|
||||
|
||||
movements.append(movement)
|
||||
@@ -347,7 +352,7 @@ class RepairImportService:
|
||||
if filters.range_type.value == "FF":
|
||||
where_conditions.append(f"ih.invoice_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND ih.invoice_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
else:
|
||||
where_conditions.append(f"log.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND log.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
where_conditions.append(f"pd.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND pd.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
|
||||
# Note: Status filter applied at Python level after CASE WHEN in SELECT
|
||||
# because is_updated doesn't directly represent AC/NA status
|
||||
@@ -383,8 +388,7 @@ class RepairImportService:
|
||||
COALESCE(SUM(lf.value_mxn), 0)
|
||||
FROM a76.item_line_financials lf
|
||||
INNER JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
INNER JOIN a76.items itm ON itm.id = il.item_id
|
||||
WHERE itm.invoice_id = :consecutivo
|
||||
WHERE il.invoice_id = :consecutivo
|
||||
AND il.is_subitem = false
|
||||
{discharge_clause}
|
||||
""")
|
||||
|
||||
@@ -97,6 +97,12 @@ class TemporaryImportService:
|
||||
valor_comercial_mn = to_float(row[30]) # valor_comercial_mn from item_line_financials
|
||||
valor_mp_temp_mn = to_float(row[31]) # valor_mp_temp_mn from item_line_financials
|
||||
valor_agre_mn = to_float(row[32]) # valor_agre_mn from item_line_financials
|
||||
valor_mp_temp_usd = to_float(row[33]) # valor_mp_temp_usd from item_line_financials
|
||||
sum_value_usd = to_float(row[34]) # sum_value_usd from item_line_financials (line item sum avoids zero-value header bug)
|
||||
|
||||
# Replace zero values with the computed sums
|
||||
total_me = sum_value_usd if sum_value_usd > 0 else total_me
|
||||
total_mn = valor_comercial_mn if valor_comercial_mn > 0 else total_mn
|
||||
|
||||
# Calculate exchange rate and value
|
||||
valor_comercial, tipo_cambio = ExchangeRateCalculator.calculate_for_aggregated(
|
||||
@@ -127,6 +133,24 @@ class TemporaryImportService:
|
||||
num_gaf_uni = DatabaseHelper.get_driver_badge(
|
||||
db, filters.database_name, factura
|
||||
)
|
||||
|
||||
# Calculate exchange rate for MPTemp explicitly decoupled from Valor Comercial
|
||||
valor_mp_temp_raw, _ = ExchangeRateCalculator.calculate_for_aggregated(
|
||||
db=db,
|
||||
db_name=filters.database_name,
|
||||
valor_me=to_float(row[33]), # sum_value_temp_usd
|
||||
valor_mn=to_float(row[31]), # sum_value_temp_mxn
|
||||
tipo_cambio_db=to_float(row[19]),
|
||||
fecha_pago=row[8],
|
||||
fecha_inicio=row[6],
|
||||
tipo_pedimento=row[4],
|
||||
currency_type=filters.currency_type.value,
|
||||
exchange_rate_type=filters.exchange_rate_type.value,
|
||||
is_shelter=filters.is_shelter,
|
||||
use_transport_method=False,
|
||||
met_trans=met_trans
|
||||
)
|
||||
valor_mp_temp = float(valor_mp_temp_raw)
|
||||
|
||||
# Build movement item
|
||||
movement = MovementItem(
|
||||
@@ -137,8 +161,8 @@ class TemporaryImportService:
|
||||
ClavePed=row[4], # C5 - ClavePed
|
||||
TipoMovTemDef='IMTEM',
|
||||
EsCambioRegimen='N',
|
||||
ValorMPTemp=valor_mp_temp_mn,
|
||||
ValorComercialMN=valor_comercial_mn,
|
||||
ValorMPTemp=valor_mp_temp,
|
||||
ValorComercialMN=valor_comercial,
|
||||
TipoCambio=tipo_cambio,
|
||||
ValorAgre=valor_agre_mn,
|
||||
TipoExpo='',
|
||||
@@ -212,6 +236,15 @@ class TemporaryImportService:
|
||||
db, filters.database_name, row[17] # C18 - AAduanal
|
||||
)
|
||||
|
||||
# Get provider and client details including RFC and TaxID
|
||||
provider_info = DatabaseHelper.get_client_info(
|
||||
db, filters.database_name, row[15], is_supplier=True
|
||||
) if row[15] else {}
|
||||
|
||||
client_info = DatabaseHelper.get_client_info(
|
||||
db, filters.database_name, row[16], is_supplier=False
|
||||
) if row[16] else {}
|
||||
|
||||
# Get customs section name
|
||||
aduana_nombre = DatabaseHelper.get_aduana_seccion_nombre(
|
||||
db, filters.database_name, row[37] # C38 - Aduana_Cruce
|
||||
@@ -233,13 +266,24 @@ class TemporaryImportService:
|
||||
met_trans=met_trans
|
||||
)
|
||||
|
||||
# ValorComercialMN should always be in MXN
|
||||
# If currency_type is ME, valor_comercial is in USD, so multiply by tipo_cambio
|
||||
if filters.currency_type.value == "ME" and tipo_cambio:
|
||||
valor_comercial_mn = float(valor_comercial) * float(tipo_cambio)
|
||||
else:
|
||||
# If currency_type is MN, valor_comercial is already in MXN
|
||||
valor_comercial_mn = float(valor_comercial)
|
||||
valor_mp_temp_raw, _ = ExchangeRateCalculator.calculate_exchange_rate_and_value(
|
||||
db=db,
|
||||
db_name=filters.database_name,
|
||||
es_subpartida=row[39], # C40 - EsSubPartida
|
||||
valor_me=float(row[59]) if row[59] else 0.0,
|
||||
valor_mn_direct=float(row[58]) if row[58] else 0.0,
|
||||
fecha_pago=row[12], # C13 - Fecha_Pago
|
||||
fecha_inicio=row[10], # C11 - Fecha_Inicio
|
||||
clave_ped=row[57], # C58 - TIPOPEDIMENTOTRANSPORTEE
|
||||
tipo_cambio_partida=row[49], # C50 - TipoCambio
|
||||
currency_type=filters.currency_type.value,
|
||||
exchange_rate_type=filters.exchange_rate_type.value,
|
||||
met_trans=met_trans
|
||||
)
|
||||
valor_mp_temp_mn = float(valor_mp_temp_raw)
|
||||
|
||||
# Assign the properly converted commercial value directly
|
||||
valor_comercial_mn = float(valor_comercial)
|
||||
|
||||
# Set peso values based on subpartida flag
|
||||
if row[39] == 'P': # C40 - EsSubPartida
|
||||
@@ -288,6 +332,8 @@ class TemporaryImportService:
|
||||
return 'P' if val else 'S' # Convert bool to P/S for Advalorem
|
||||
return str(val)
|
||||
|
||||
logger.error(f"DEBUG ROW: NumParte(17)='{row[17]}', Sector(30)='{row[30]}', Partida {row[43]}, Original Part ID(46)='{row[46]}'")
|
||||
|
||||
# Build detailed movement item
|
||||
movement = MovementItemDetailed(
|
||||
Linea=row[43], # C44 - LineaImpo
|
||||
@@ -299,31 +345,32 @@ class TemporaryImportService:
|
||||
TipoMovTemDef='IMTEM',
|
||||
EsCambioRegimen='N',
|
||||
Regimen=row[9], # C10 - Regimen
|
||||
Fecha_Inicio=none_if_empty(row[10]), # C11 - Fecha_Inicio
|
||||
Fecha_Fin=none_if_empty(row[11]), # C12 - Fecha_Fin
|
||||
Fecha_Pago=none_if_empty(row[12]), # C13 - Fecha_Pago
|
||||
Fecha_Inicio=parse_yyyymmdd_date(row[10]), # C11 - Fecha_Inicio
|
||||
Fecha_Fin=parse_yyyymmdd_date(row[11]), # C12 - Fecha_Fin
|
||||
Fecha_Pago=parse_yyyymmdd_date(row[12]), # C13 - Fecha_Pago
|
||||
Remesa=to_str(row[13]), # C14 - Remesa
|
||||
Proveedor=row[7], # C8 - Provider name (from JOIN)
|
||||
RFCProveedor=None, # RFC not in detailed query
|
||||
ProveedorTaxID=None, # Tax ID not in detailed query
|
||||
RFCProveedor=provider_info.get('rfc'),
|
||||
ProveedorTaxID=provider_info.get('tax_id'),
|
||||
VendidoA=row[8], # C9 - Client name (from JOIN)
|
||||
VendidoARFC=None, # RFC not in detailed query
|
||||
VendidoATaxID=None, # Tax ID not in detailed query
|
||||
VendidoARFC=client_info.get('rfc'),
|
||||
VendidoATaxID=client_info.get('tax_id'),
|
||||
AgenteAduanal=agente_info.get('name'),
|
||||
Patente=agente_info.get('license'),
|
||||
NumParte=row[19], # C20 - Clase (NumParte)
|
||||
NumParte=row[48], # C49 - Part Number (from JOIN)
|
||||
DescripcionE=StringHelper.clean_text(row[20]), # C21
|
||||
DescripcionI=StringHelper.clean_text(row[21]), # C22
|
||||
CantidadIE=float(row[22]) if row[22] else 0.0, # C23
|
||||
UniMed=row[23], # C24
|
||||
ValorComercialMN=valor_comercial_mn,
|
||||
ValorMPTemp=valor_mp_temp_mn,
|
||||
TipoCambio=tipo_cambio,
|
||||
PesoNeto=peso_neto,
|
||||
PesoBruto=peso_bruto,
|
||||
OrdenCompraVenta=row[30], # C31 - OrdenCompra
|
||||
FraccionArancelaria=row[31], # C32 - Fraccion
|
||||
Preferencia=row[32], # C33 - TipoFraccion
|
||||
Sector=row[34], # C35 - Sector
|
||||
Sector=row[34], # C35 - Sector (from COALESCE)
|
||||
PaisOrigen=row[36], # C37 - PaisOrigen
|
||||
Aduana=aduana_nombre,
|
||||
Advalorem=to_str(row[39]), # C40 - EsSubPartida (convert bool to str)
|
||||
@@ -337,13 +384,13 @@ class TemporaryImportService:
|
||||
FraccionAmericana=row[46], # C47 - FraccionAme
|
||||
ECCN=row[47], # C48 - ECCN
|
||||
SimboloEx=simbolo_ex,
|
||||
FechaEmision=parse_yyyymmdd_date(row[50]), # C51 - FechaEmision (convert to datetime)
|
||||
FechaEmision=parse_yyyymmdd_date(row[50]), # C51 - FechaEmision
|
||||
BaseDeDatos=filters.database_name,
|
||||
NumGafUni=num_gaf_uni,
|
||||
UsuarioCap=row[51], # C52 - UsuarioCap
|
||||
UsuarioAcr=row[52], # C53 - UsuarioAct
|
||||
Transportista=row[53], # C54 - Transportista
|
||||
NumCaja=row[54], # C55 - Transporte + NumTrasporte
|
||||
Transportista=row[53], # C54 - Carrier ID
|
||||
NumCaja=row[54], # C55 - Transport num
|
||||
Pedimento18=row[55], # C56 - Pedimento18
|
||||
AduanaCru=row[37], # C38 - Aduana_Cruce
|
||||
Lote=row[56] # C57 - LOTE
|
||||
@@ -371,7 +418,7 @@ class TemporaryImportService:
|
||||
if filters.range_type.value == "FF":
|
||||
where_conditions.append(f"ih.invoice_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND ih.invoice_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
else:
|
||||
where_conditions.append(f"log.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND log.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
where_conditions.append(f"pd.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND pd.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
|
||||
|
||||
# Note: Status filter applied at Python level after CASE WHEN in SELECT
|
||||
# because is_updated doesn't directly represent AC/NA status
|
||||
@@ -401,8 +448,7 @@ class TemporaryImportService:
|
||||
COALESCE(SUM(lf.value_mxn), 0)
|
||||
FROM a76.item_line_financials lf
|
||||
JOIN a76.item_lines il ON il.id = lf.item_line_id
|
||||
JOIN a76.items i ON i.id = il.item_id
|
||||
WHERE i.invoice_id = :consecutivo
|
||||
WHERE il.invoice_id = :consecutivo
|
||||
AND COALESCE(il.is_subpartida, false) = false
|
||||
""")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user