REPORTES mexicanos y americanos de facturas corregido
This commit is contained in:
@@ -66,6 +66,10 @@ class PartidaSchema(BaseModel):
|
||||
|
||||
advalorem:Optional[str] = ""
|
||||
preferencia:Optional[str] = ""
|
||||
|
||||
marca: Optional[str] = ""
|
||||
modelo: Optional[str] = ""
|
||||
series: List[str] = []
|
||||
|
||||
cantidad_importacion: Union[float, str]
|
||||
unidad_medida: str
|
||||
|
||||
@@ -23,6 +23,9 @@ from api.v1.modules.a76.pedmientos.models import Pedimentos
|
||||
from api.v1.modules.a76.general_catalogs.company.models import Company
|
||||
from api.v1.modules.a76.customs_brokers.models import CustomsBroker
|
||||
from api.v1.modules.a76.items.models import LineItem
|
||||
from api.v1.modules.a76.items.line_customs.models import LineCustom
|
||||
from api.v1.modules.a76.items.line_descriptions.models import LineDescription
|
||||
from api.v1.modules.a76.items.series.models import Serie
|
||||
|
||||
# --- TRANSPORTATION MODELS ---
|
||||
from api.v1.modules.a76.transportation.transporters.models import Transporter
|
||||
@@ -454,6 +457,13 @@ class FacturaImportacionMexService:
|
||||
)
|
||||
partidas_list = []
|
||||
|
||||
# Initialize raw totals
|
||||
raw_cant = 0.0
|
||||
raw_valor = 0.0
|
||||
raw_peso_n = 0.0
|
||||
raw_peso_b = 0.0
|
||||
raw_bultos = 0
|
||||
|
||||
for line in lines:
|
||||
qty = (
|
||||
db.query(LineQuantity)
|
||||
@@ -465,6 +475,21 @@ class FacturaImportacionMexService:
|
||||
.filter(LineFinancial.item_line_id == line.id)
|
||||
.first()
|
||||
)
|
||||
customs = (
|
||||
db.query(LineCustom)
|
||||
.filter(LineCustom.item_line_id == line.id)
|
||||
.first()
|
||||
)
|
||||
desc_obj = (
|
||||
db.query(LineDescription)
|
||||
.filter(LineDescription.item_line_id == line.id)
|
||||
.first()
|
||||
)
|
||||
series_objs = (
|
||||
db.query(Serie)
|
||||
.filter(Serie.line_item_id == line.id)
|
||||
.all()
|
||||
)
|
||||
part_master = db.query(Part).filter(Part.id == line.part_number_id).first()
|
||||
|
||||
desc_final = "S/D"
|
||||
@@ -484,6 +509,10 @@ class FacturaImportacionMexService:
|
||||
# Fetch Origin from Master Catalog (FaPart)
|
||||
if part_master.fa_data and part_master.fa_data.origin_country:
|
||||
origen_final = part_master.fa_data.origin_country
|
||||
|
||||
# Prioritize description from LineDescription (specific to this invoice)
|
||||
if desc_obj:
|
||||
desc_final = desc_obj.description_spanish or desc_obj.description_english or desc_final
|
||||
|
||||
fraccion_limpia = fraccion_raw.replace(".", "").strip()
|
||||
if fraccion_limpia:
|
||||
@@ -498,21 +527,36 @@ class FacturaImportacionMexService:
|
||||
|
||||
preferencia_txt = "General"
|
||||
advalorem_txt = "0%"
|
||||
fraccion_imprimir = fraccion_raw
|
||||
|
||||
if fraccion_db:
|
||||
# Si el valor en BD es None, "0", o vacío, dejarlo como "0%" o "EXENTO"
|
||||
# 1. Prioridad: Datos específicos de la partida (LineCustom)
|
||||
if customs:
|
||||
if customs.fraction_type:
|
||||
preferencia_txt = str(customs.fraction_type).upper()
|
||||
|
||||
if customs.advalorem:
|
||||
adv_val = customs.advalorem.strip()
|
||||
if adv_val not in ["0", "0.0", "0.00", ""]:
|
||||
advalorem_txt = adv_val if "%" in adv_val else f"{adv_val}%"
|
||||
|
||||
# 2. Fallback: Datos de la fracción en catálogo (TariffFraction) si no hay en la partida
|
||||
elif fraccion_db:
|
||||
adv_db = fraccion_db.adv_impo
|
||||
if adv_db and adv_db.strip() not in ["0", "0.0", "0.00", ""]:
|
||||
advalorem_txt = adv_db if "%" in adv_db else f"{adv_db}%"
|
||||
else:
|
||||
advalorem_txt = "0%"
|
||||
|
||||
# 3. Formatear Fracción para imprimir
|
||||
if fraccion_db:
|
||||
fraccion_imprimir = fraccion_db.fraction or fraccion_raw
|
||||
else:
|
||||
|
||||
fraccion_imprimir = self._format_fraccion_fallback(fraccion_limpia)
|
||||
|
||||
# 4. Datos de Marca, Modelo y Series
|
||||
marca_val = desc_obj.brand if desc_obj else ""
|
||||
modelo_val = desc_obj.model if desc_obj else ""
|
||||
series_list = [s.serial_numbers for s in series_objs if s.serial_numbers]
|
||||
|
||||
# Logic to determine values - Prioritize Specific Currency Columns
|
||||
v_unitario = 0.0
|
||||
v_total = 0.0
|
||||
@@ -544,6 +588,13 @@ class FacturaImportacionMexService:
|
||||
elif v_total > 0 and v_unitario == 0:
|
||||
v_unitario = v_total / cantidad
|
||||
|
||||
# Accumulate raw totals
|
||||
raw_cant += float(qty.quantity) if qty and qty.quantity else 0.0
|
||||
raw_valor += v_total
|
||||
raw_peso_n += float(qty.net_weight) if qty and qty.net_weight else 0.0
|
||||
raw_peso_b += float(qty.gross_weight) if qty and qty.gross_weight else 0.0
|
||||
raw_bultos += int(qty.package_quantity) if qty and qty.package_quantity else 0
|
||||
|
||||
# Obtener descripción de la unidad de medida desde la tabla a76.item_lines
|
||||
unidad_desc = ""
|
||||
if line.unit_of_measure:
|
||||
@@ -568,6 +619,9 @@ class FacturaImportacionMexService:
|
||||
origen=origen_final,
|
||||
advalorem=advalorem_txt,
|
||||
preferencia=preferencia_txt,
|
||||
marca=marca_val,
|
||||
modelo=modelo_val,
|
||||
series=series_list,
|
||||
cantidad_importacion=self.formatear_numero(
|
||||
qty.quantity if qty else 0
|
||||
),
|
||||
@@ -588,7 +642,13 @@ class FacturaImportacionMexService:
|
||||
)
|
||||
|
||||
totales = self.calcular_totales(
|
||||
partidas_list, Decimal(factura_schema.tipo_cambio)
|
||||
partidas_list,
|
||||
Decimal(factura_schema.tipo_cambio),
|
||||
raw_cant=raw_cant,
|
||||
raw_valor=raw_valor,
|
||||
raw_peso_n=raw_peso_n,
|
||||
raw_peso_b=raw_peso_b,
|
||||
raw_bultos=raw_bultos
|
||||
)
|
||||
|
||||
return FacturaImportacionCompleta(
|
||||
@@ -605,26 +665,29 @@ class FacturaImportacionMexService:
|
||||
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
|
||||
|
||||
def calcular_totales(
|
||||
self, partidas: List[PartidaSchema], tipo_cambio: Decimal
|
||||
self,
|
||||
partidas: List[PartidaSchema],
|
||||
tipo_cambio: Decimal,
|
||||
raw_cant: float = 0,
|
||||
raw_valor: float = 0,
|
||||
raw_peso_n: float = 0,
|
||||
raw_peso_b: float = 0,
|
||||
raw_bultos: int = 0
|
||||
) -> TotalesSchema:
|
||||
cant = sum(p.cantidad_importacion for p in partidas)
|
||||
valor = sum(p.valor_total for p in partidas)
|
||||
peso_n = sum(p.peso_neto for p in partidas)
|
||||
peso_b = sum(p.peso_bruto for p in partidas)
|
||||
bultos = sum(p.cantidad_bultos for p in partidas)
|
||||
# Use raw values passed from obtener_datos to avoid TypeError with formatted strings
|
||||
claves = [p.clave_bultos for p in partidas if p.clave_bultos]
|
||||
clave_comun = max(set(claves), key=claves.count) if claves else ""
|
||||
if bultos > 1 and clave_comun and not clave_comun.endswith("S"):
|
||||
if raw_bultos > 1 and clave_comun and not clave_comun.endswith("S"):
|
||||
clave_comun += "S"
|
||||
tc = float(tipo_cambio) if tipo_cambio else 1.0
|
||||
return TotalesSchema(
|
||||
cantidad_total=self.formatear_numero(cant),
|
||||
bultos_total=bultos,
|
||||
cantidad_total=self.formatear_numero(raw_cant),
|
||||
bultos_total=raw_bultos,
|
||||
clave_bultos=clave_comun,
|
||||
peso_neto_total=self.formatear_numero(peso_n),
|
||||
peso_bruto_total=self.formatear_numero(peso_b),
|
||||
valor_total_total=self.formatear_numero(valor),
|
||||
valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0),
|
||||
peso_neto_total=self.formatear_numero(raw_peso_n),
|
||||
peso_bruto_total=self.formatear_numero(raw_peso_b),
|
||||
valor_total_total=self.formatear_numero(raw_valor),
|
||||
valor_total_dolares=self.formatear_numero(raw_valor / tc if tc > 0 else 0),
|
||||
)
|
||||
|
||||
def generar_factura_completa(self, db: Session, invoice_id: int, company_id: int, formato: str = "pdf", progress_callback: Optional[Callable] = None, currency_code: str = 'ORIGINAL') -> Tuple[bytes, str, str]:
|
||||
|
||||
@@ -505,9 +505,8 @@
|
||||
<td class="border" rowspan="2">
|
||||
<p class="tiny-bold p-t-5 center">Línea</p>
|
||||
</td>
|
||||
<td class="border" rowspan="2">
|
||||
<p class="tiny-bold p-l-2 line-10">Número de Parte</p>
|
||||
<p class="tiny-bold p-l-2 line-10">Descripción</p>
|
||||
<td class="border" rowspan="2" style="width: 180pt;">
|
||||
<p class="tiny-bold p-l-2 line-10">Descripción de la Mercancía</p>
|
||||
</td>
|
||||
<td class="border" colspan="3">
|
||||
<p class="tiny-bold center line-9">Comercial</p>
|
||||
@@ -554,13 +553,15 @@
|
||||
<p class="mini p-t-3 center">{{ loop.index }}</p>
|
||||
</td>
|
||||
<td class="border">
|
||||
<p class="mini p-t-1" style="font-weight: bold;">{{ partida.numero_parte }}</p>
|
||||
<p class="mini">{{ partida.descripcion }}</p>
|
||||
<p class="mini">Frac: {{ partida.fraccion }} / Orig: {{ partida.origen or 'MEX' }}</p>
|
||||
<p class="mini">
|
||||
{% if partida.advalorem %}ADV: {{ partida.advalorem }}{% endif %}
|
||||
{% if partida.preferencia %} / PREF: {{ partida.preferencia }}{% endif %}
|
||||
<p class="mini p-t-1">
|
||||
{{ partida.descripcion }} / Origen: {{ partida.origen or 'MEX' }} / Fracción: {{ partida.fraccion }} / Preferencia: {{ partida.preferencia }} / Advalorem: {{ partida.advalorem }}
|
||||
</p>
|
||||
{% if partida.marca %}<p class="mini">Marca: {{ partida.marca }}</p>{% endif %}
|
||||
{% if partida.modelo %}<p class="mini">Modelo: {{ partida.modelo }}</p>{% endif %}
|
||||
{% if partida.series %}
|
||||
<p class="mini p-t-1">- SERIE(S):</p>
|
||||
<p class="mini">Serie: {{ partida.series|join(', ') }}</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="border" colspan="2">
|
||||
<p class="mini p-t-2 center">{{ partida.cantidad_importacion }}</p>
|
||||
|
||||
@@ -456,9 +456,8 @@
|
||||
<td class="border" rowspan="2">
|
||||
<p class="tiny-bold p-t-5 center">Line</p>
|
||||
</td>
|
||||
<td class="border" rowspan="2">
|
||||
<p class="tiny-bold p-l-2 line-10">Part Number</p>
|
||||
<p class="tiny-bold p-l-2 line-10">Description</p>
|
||||
<td class="border" rowspan="2" style="width: 180pt;">
|
||||
<p class="tiny-bold p-l-2 line-10">Description of raw material</p>
|
||||
</td>
|
||||
<td class="border" colspan="3">
|
||||
<p class="tiny-bold center line-9">Commercial</p>
|
||||
@@ -505,10 +504,15 @@
|
||||
<p class="mini p-t-3 center">{{ loop.index }}</p>
|
||||
</td>
|
||||
<td class="border">
|
||||
<p class="mini p-t-1" style="font-weight: bold;">{{ partida.numero_parte }}</p>
|
||||
<p class="mini">{{ partida.descripcion }}</p>
|
||||
<p class="mini">HTS Code: {{ partida.fraccion }} / Orig: {{ partida.origen or 'MEX' }}</p>
|
||||
|
||||
<p class="mini p-t-1">
|
||||
{{ partida.descripcion }} / HTS Code: {{ partida.fraccion }} / Origin: {{ partida.origen or 'MEX' }} / Preference: {{ partida.preferencia }} / Advalorem: {{ partida.advalorem }}
|
||||
</p>
|
||||
{% if partida.marca %}<p class="mini">Brand: {{ partida.marca }}</p>{% endif %}
|
||||
{% if partida.modelo %}<p class="mini">Model: {{ partida.modelo }}</p>{% endif %}
|
||||
{% if partida.series %}
|
||||
<p class="mini p-t-1">- SERIAL(S):</p>
|
||||
<p class="mini">Serial: {{ partida.series|join(', ') }}</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="border" colspan="2">
|
||||
<p class="mini p-t-2 center">{{ partida.cantidad_importacion }}</p>
|
||||
|
||||
@@ -23,6 +23,9 @@ from api.v1.modules.a76.pedmientos.models import Pedimentos
|
||||
from api.v1.modules.a76.general_catalogs.company.models import Company
|
||||
from api.v1.modules.a76.customs_brokers.models import CustomsBroker
|
||||
from api.v1.modules.a76.items.models import LineItem
|
||||
from api.v1.modules.a76.items.line_customs.models import LineCustom
|
||||
from api.v1.modules.a76.items.line_descriptions.models import LineDescription
|
||||
from api.v1.modules.a76.items.series.models import Serie
|
||||
|
||||
# --- TRANSPORTATION MODELS ---
|
||||
from api.v1.modules.a76.transportation.transporters.models import Transporter
|
||||
@@ -455,6 +458,13 @@ class FacturaImportacionUsaService:
|
||||
lines = db.query(LineItem).filter(LineItem.invoice_id == header.id).all()
|
||||
partidas_list = []
|
||||
|
||||
# Initialize raw totals
|
||||
raw_cant = 0.0
|
||||
raw_valor = 0.0
|
||||
raw_peso_n = 0.0
|
||||
raw_peso_b = 0.0
|
||||
raw_bultos = 0
|
||||
|
||||
for line in lines:
|
||||
qty = (
|
||||
db.query(LineQuantity)
|
||||
@@ -466,6 +476,21 @@ class FacturaImportacionUsaService:
|
||||
.filter(LineFinancial.item_line_id == line.id)
|
||||
.first()
|
||||
)
|
||||
customs = (
|
||||
db.query(LineCustom)
|
||||
.filter(LineCustom.item_line_id == line.id)
|
||||
.first()
|
||||
)
|
||||
desc_obj = (
|
||||
db.query(LineDescription)
|
||||
.filter(LineDescription.item_line_id == line.id)
|
||||
.first()
|
||||
)
|
||||
series_objs = (
|
||||
db.query(Serie)
|
||||
.filter(Serie.line_item_id == line.id)
|
||||
.all()
|
||||
)
|
||||
part_master = (
|
||||
db.query(Part).filter(Part.id == line.part_number_id).first()
|
||||
)
|
||||
@@ -491,6 +516,10 @@ class FacturaImportacionUsaService:
|
||||
if part_master.fa_data and part_master.fa_data.origin_country:
|
||||
origen_final = part_master.fa_data.origin_country
|
||||
|
||||
# Prioritize description from LineDescription (specific to this invoice)
|
||||
if desc_obj:
|
||||
desc_final = desc_obj.description_english or desc_obj.description_spanish or desc_final
|
||||
|
||||
# FRACTION LOGIC: Use US Fraction (us_fraction) if available, otherwise blank
|
||||
fraccion_imprimir = ""
|
||||
|
||||
@@ -498,14 +527,25 @@ class FacturaImportacionUsaService:
|
||||
if part_master and part_master.us_fraction:
|
||||
fraccion_imprimir = part_master.us_fraction.strip()
|
||||
|
||||
# Optional: Format if needed, but raw is usually fine for US HTS
|
||||
# If valid US fraction logic requires looking up in DB, we could add that here.
|
||||
# For now, per requirement: "Si no tiene, pues de queda en blanco"
|
||||
|
||||
# Default "General" and "0%" if no specific logic for US duties yet
|
||||
# Preference and Advalorem logic
|
||||
preferencia_txt = "General"
|
||||
advalorem_txt = "0%"
|
||||
|
||||
# 1. Prioridad: Datos específicos de la partida (LineCustom)
|
||||
if customs:
|
||||
if customs.fraction_type:
|
||||
preferencia_txt = str(customs.fraction_type).upper()
|
||||
|
||||
if customs.advalorem:
|
||||
adv_val = customs.advalorem.strip()
|
||||
if adv_val not in ["0", "0.0", "0.00", ""]:
|
||||
advalorem_txt = adv_val if "%" in adv_val else f"{adv_val}%"
|
||||
|
||||
# 2. Marca, Modelo y Series
|
||||
marca_val = desc_obj.brand if desc_obj else ""
|
||||
modelo_val = desc_obj.model if desc_obj else ""
|
||||
series_list = [s.serial_numbers for s in series_objs if s.serial_numbers]
|
||||
|
||||
# Prioritize USD for American Invoice logic if available?
|
||||
# Sticking to same logic as Mex for now but could prioritize USD columns.
|
||||
# Actually, duplicate logic from mex service for now to ensure consistency.
|
||||
@@ -537,6 +577,13 @@ class FacturaImportacionUsaService:
|
||||
elif v_total > 0 and v_unitario == 0:
|
||||
v_unitario = v_total / cantidad
|
||||
|
||||
# Accumulate raw totals
|
||||
raw_cant += float(qty.quantity) if qty and qty.quantity else 0.0
|
||||
raw_valor += v_total
|
||||
raw_peso_n += float(qty.net_weight) if qty and qty.net_weight else 0.0
|
||||
raw_peso_b += float(qty.gross_weight) if qty and qty.gross_weight else 0.0
|
||||
raw_bultos += int(qty.package_quantity) if qty and qty.package_quantity else 0
|
||||
|
||||
# UOM Mapping for English context
|
||||
uom_raw = line.unit_of_measure_info.code if line.unit_of_measure_info else "PCS"
|
||||
if uom_raw == "PZA":
|
||||
@@ -550,6 +597,9 @@ class FacturaImportacionUsaService:
|
||||
origen=origen_final,
|
||||
advalorem=advalorem_txt,
|
||||
preferencia=preferencia_txt,
|
||||
marca=marca_val,
|
||||
modelo=modelo_val,
|
||||
series=series_list,
|
||||
cantidad_importacion=self.formatear_numero(
|
||||
qty.quantity if qty else 0
|
||||
),
|
||||
@@ -572,7 +622,13 @@ class FacturaImportacionUsaService:
|
||||
)
|
||||
|
||||
totales = self.calcular_totales(
|
||||
partidas_list, Decimal(factura_schema.tipo_cambio)
|
||||
partidas_list,
|
||||
Decimal(factura_schema.tipo_cambio),
|
||||
raw_cant=raw_cant,
|
||||
raw_valor=raw_valor,
|
||||
raw_peso_n=raw_peso_n,
|
||||
raw_peso_b=raw_peso_b,
|
||||
raw_bultos=raw_bultos
|
||||
)
|
||||
|
||||
return FacturaImportacionCompleta(
|
||||
@@ -589,13 +645,16 @@ class FacturaImportacionUsaService:
|
||||
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
|
||||
|
||||
def calcular_totales(
|
||||
self, partidas: List[PartidaSchema], tipo_cambio: Decimal
|
||||
self,
|
||||
partidas: List[PartidaSchema],
|
||||
tipo_cambio: Decimal,
|
||||
raw_cant: float = 0,
|
||||
raw_valor: float = 0,
|
||||
raw_peso_n: float = 0,
|
||||
raw_peso_b: float = 0,
|
||||
raw_bultos: int = 0
|
||||
) -> TotalesSchema:
|
||||
cant = sum(p.cantidad_importacion for p in partidas)
|
||||
valor = sum(p.valor_total for p in partidas)
|
||||
peso_n = sum(p.peso_neto for p in partidas)
|
||||
peso_b = sum(p.peso_bruto for p in partidas)
|
||||
bultos = sum(p.cantidad_bultos for p in partidas)
|
||||
# Use raw values passed from obtener_datos to avoid TypeError with formatted strings
|
||||
claves = [p.clave_bultos for p in partidas if p.clave_bultos]
|
||||
clave_comun = max(set(claves), key=claves.count) if claves else ""
|
||||
# if bultos > 1 and clave_comun and not clave_comun.endswith("S"): clave_comun += "S"
|
||||
@@ -603,13 +662,13 @@ class FacturaImportacionUsaService:
|
||||
|
||||
tc = float(tipo_cambio) if tipo_cambio else 1.0
|
||||
return TotalesSchema(
|
||||
cantidad_total=self.formatear_numero(cant),
|
||||
bultos_total=bultos,
|
||||
cantidad_total=self.formatear_numero(raw_cant),
|
||||
bultos_total=raw_bultos,
|
||||
clave_bultos=clave_comun,
|
||||
peso_neto_total=self.formatear_numero(peso_n),
|
||||
peso_bruto_total=self.formatear_numero(peso_b),
|
||||
valor_total_total=self.formatear_numero(valor),
|
||||
valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0),
|
||||
peso_neto_total=self.formatear_numero(raw_peso_n),
|
||||
peso_bruto_total=self.formatear_numero(raw_peso_b),
|
||||
valor_total_total=self.formatear_numero(raw_valor),
|
||||
valor_total_dolares=self.formatear_numero(raw_valor / tc if tc > 0 else 0),
|
||||
)
|
||||
|
||||
def generar_factura_completa(
|
||||
|
||||
@@ -280,6 +280,14 @@ class PackingListService:
|
||||
lines = db.query(LineItem).filter(LineItem.invoice_id == header.id).all()
|
||||
partidas_list = []
|
||||
|
||||
# Initialize raw totals
|
||||
raw_cant = 0.0
|
||||
raw_peso_n = 0.0
|
||||
raw_peso_b = 0.0
|
||||
raw_peso_n_lb = 0.0
|
||||
raw_peso_b_lb = 0.0
|
||||
raw_bultos = 0
|
||||
|
||||
for line in lines:
|
||||
weight_type = db.query(InvoiceLogistics.weight_type).filter(InvoiceLogistics.invoice_id == line.invoice_id).scalar()
|
||||
qty = db.query(LineQuantity).filter(LineQuantity.item_line_id == line.id).first()
|
||||
@@ -306,6 +314,14 @@ class PackingListService:
|
||||
peso_bruto_lb = raw_gross * 2.20462
|
||||
# --------------------------------
|
||||
|
||||
# Accumulate raw totals
|
||||
raw_cant += float(qty.quantity) if qty and qty.quantity else 0.0
|
||||
raw_peso_n += peso_neto_kg
|
||||
raw_peso_b += peso_bruto_kg
|
||||
raw_peso_n_lb += peso_neto_lb
|
||||
raw_peso_b_lb += peso_bruto_lb
|
||||
raw_bultos += int(qty.package_quantity) if qty and qty.package_quantity else 0
|
||||
|
||||
custom_obj = db.query(LineCustom).filter(LineCustom.item_line_id == line.id).first()
|
||||
part_master = db.query(Part).filter(Part.id == line.part_number_id).first()
|
||||
|
||||
@@ -361,7 +377,16 @@ class PackingListService:
|
||||
valor_total=v_total # Hidden
|
||||
))
|
||||
|
||||
totales = self.calcular_totales(partidas_list, Decimal(factura_schema.tipo_cambio))
|
||||
totales = self.calcular_totales(
|
||||
partidas_list,
|
||||
Decimal(factura_schema.tipo_cambio),
|
||||
raw_cant=raw_cant,
|
||||
raw_peso_n=raw_peso_n,
|
||||
raw_peso_b=raw_peso_b,
|
||||
raw_peso_n_lbs=raw_peso_n_lb,
|
||||
raw_peso_b_lbs=raw_peso_b_lb,
|
||||
raw_bultos=raw_bultos
|
||||
)
|
||||
|
||||
return PackingListSchema(
|
||||
cliente_proveedor=cliente_proveedor, cliente_vendido=cliente_vendido,
|
||||
@@ -376,24 +401,25 @@ class PackingListService:
|
||||
print(f"Error Service A76: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
|
||||
|
||||
def calcular_totales(self, partidas: List[PartidaSchema], tipo_cambio: Decimal) -> TotalesSchema:
|
||||
cant = sum(float(p.cantidad_importacion) for p in partidas)
|
||||
# Financial totals hidden
|
||||
peso_n = sum(float(p.peso_neto) for p in partidas)
|
||||
peso_b = sum(float(p.peso_bruto) for p in partidas)
|
||||
peso_n_lbs = sum(float(p.peso_neto_lbs) for p in partidas)
|
||||
peso_b_lbs = sum(float(p.peso_bruto_lbs) for p in partidas)
|
||||
|
||||
bultos = sum(p.cantidad_bultos for p in partidas)
|
||||
|
||||
def calcular_totales(self,
|
||||
partidas: List[PartidaSchema],
|
||||
tipo_cambio: Decimal,
|
||||
raw_cant: float = 0,
|
||||
raw_peso_n: float = 0,
|
||||
raw_peso_b: float = 0,
|
||||
raw_peso_n_lbs: float = 0,
|
||||
raw_peso_b_lbs: float = 0,
|
||||
raw_bultos: int = 0
|
||||
) -> TotalesSchema:
|
||||
# Use raw values to avoid ValueError/TypeError with formatted strings
|
||||
claves = [p.clave_bultos for p in partidas if p.clave_bultos]
|
||||
clave_comun = max(set(claves), key=claves.count) if claves else ""
|
||||
if bultos > 1 and clave_comun and not clave_comun.endswith("S"): clave_comun += "S"
|
||||
if raw_bultos > 1 and clave_comun and not clave_comun.endswith("S"): clave_comun += "S"
|
||||
|
||||
return TotalesSchema(
|
||||
cantidad_total=self.formatear_numero(cant), bultos_total=bultos, clave_bultos=clave_comun,
|
||||
peso_neto_total=self.formatear_numero(peso_n), peso_bruto_total=self.formatear_numero(peso_b),
|
||||
peso_neto_total_lbs=self.formatear_numero(peso_n_lbs), peso_bruto_total_lbs=self.formatear_numero(peso_b_lbs),
|
||||
cantidad_total=self.formatear_numero(raw_cant), bultos_total=raw_bultos, clave_bultos=clave_comun,
|
||||
peso_neto_total=self.formatear_numero(raw_peso_n), peso_bruto_total=self.formatear_numero(raw_peso_b),
|
||||
peso_neto_total_lbs=self.formatear_numero(raw_peso_n_lbs), peso_bruto_total_lbs=self.formatear_numero(raw_peso_b_lbs),
|
||||
valor_total_total="", valor_total_dolares=""
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user