- Modalidad AÉREO (4ª opción en "¿Cómo desea cotizar?"): en la solicitud muestra la sección aérea con el cálculo en vivo P/Vol = (L×A×H cm × bultos)/6000 y el peso a cobrar = max(peso bruto, P/Vol). Fija el transporte en aéreo. - Utilidad compartida crm/common/pricing.py (air_volumetric_kg / air_chargeable_kg, factor internacional 6000). - Motor de costeo (rates): la rama aérea usa el P/Vol por dimensiones si vienen (CostRequest ahora acepta length/width/height_cm); respaldo m³×167 cuando no. - Cotizador: captura por dimensiones (L×A×H + bultos) en modo aéreo y muestra el P/Vol. - Solicitud→Cotización: si es AÉREO, siembra el concepto de flete con cantidad = peso a cobrar (P/Vol) para capturar la tarifa por kg. - Pruebas: test_pricing (ejemplo del doc → 720; max bruto/volumétrico) + cotización aérea desde solicitud. Suite en verde (108). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
38 lines
1.4 KiB
Python
38 lines
1.4 KiB
Python
"""Cálculos de precio compartidos del proceso comercial.
|
||
|
||
Peso volumétrico / a cobrar de carga aérea (doc maestro de cotización):
|
||
P/Vol = (Largo_cm × Ancho_cm × Alto_cm × cantidad) / 6000
|
||
El peso a cobrar es el mayor entre el peso bruto y el P/Vol (estándar aéreo).
|
||
6000 cm³/kg es el factor internacional (equivale a ~167 kg/m³).
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from decimal import Decimal
|
||
|
||
# Factor internacional de peso volumétrico aéreo (cm³ por kg).
|
||
AIR_VOLUMETRIC_DIVISOR = Decimal("6000")
|
||
|
||
|
||
def _d(value) -> Decimal:
|
||
if value is None:
|
||
return Decimal(0)
|
||
return value if isinstance(value, Decimal) else Decimal(str(value))
|
||
|
||
|
||
def air_volumetric_kg(length_cm, width_cm, height_cm, qty=1) -> Decimal:
|
||
"""Peso volumétrico aéreo a partir de dimensiones (cm) y cantidad de bultos.
|
||
|
||
Devuelve 0 si falta alguna dimensión (no se puede calcular).
|
||
"""
|
||
length, width, height = _d(length_cm), _d(width_cm), _d(height_cm)
|
||
if length <= 0 or width <= 0 or height <= 0:
|
||
return Decimal(0)
|
||
quantity = _d(qty) if _d(qty) > 0 else Decimal(1)
|
||
return (length * width * height * quantity) / AIR_VOLUMETRIC_DIVISOR
|
||
|
||
|
||
def air_chargeable_kg(gross_kg, length_cm, width_cm, height_cm, qty=1) -> Decimal:
|
||
"""Peso a cobrar aéreo: max(peso bruto, peso volumétrico por dimensiones)."""
|
||
return max(_d(gross_kg), air_volumetric_kg(length_cm, width_cm, height_cm, qty))
|