refactor: streamline item validation functions and enhance number formatting in summary section
This commit is contained in:
@@ -3,36 +3,31 @@ from core.exceptions import ErrorCollector
|
||||
from ..line_items import models
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
def item_exists(
|
||||
db: Session,
|
||||
item_line: int,
|
||||
tenant_id: int,
|
||||
company_id: int
|
||||
):
|
||||
|
||||
def item_exists(db: Session, item_line: int, tenant_id: int, company_id: int):
|
||||
item_exists = (
|
||||
db.query(models.LineItem.id)
|
||||
db.query(models.LineItem)
|
||||
.filter(
|
||||
models.LineItem.line_number == item_line,
|
||||
models.LineItem.tenant_id == tenant_id,
|
||||
models.LineItem.company_id == company_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
return item_exists
|
||||
|
||||
|
||||
def count_items(db: Session, invoice_id: int, tenant_id: int, company_id: int):
|
||||
count = (
|
||||
db.query(func.count())
|
||||
.select_from(models.Item)
|
||||
.filter(
|
||||
models.Item.invoice_id == invoice_id,
|
||||
models.Item.tenant_id == tenant_id,
|
||||
models.Item.company_id == company_id,
|
||||
)
|
||||
.scalar()
|
||||
)
|
||||
|
||||
if item_exists:
|
||||
return item_exists
|
||||
return None
|
||||
|
||||
def count_items(
|
||||
db: Session,
|
||||
invoice_id: int,
|
||||
tenant_id: int,
|
||||
company_id: int
|
||||
):
|
||||
count = db.query(func.count()).select_from(models.Item).filter(
|
||||
models.Item.invoice_id == invoice_id,
|
||||
models.Item.tenant_id == tenant_id,
|
||||
models.Item.company_id == company_id,
|
||||
).scalar()
|
||||
|
||||
return count
|
||||
return count
|
||||
|
||||
@@ -42,9 +42,7 @@ def validate_common(
|
||||
invoice: InvoiceHeader = invoice_exists_by_id(
|
||||
db, invoice_id, tenant_id, company_id, errors
|
||||
)
|
||||
line_item: LineItem = item_exists(
|
||||
db, line.line_number, tenant_id, company_id
|
||||
)
|
||||
line_item: LineItem = item_exists(db, line.line_number, tenant_id, company_id)
|
||||
|
||||
fecha_factura = invoice.invoice_date if invoice else None
|
||||
fraction = None
|
||||
@@ -181,13 +179,15 @@ def validate_common(
|
||||
fraction = line.customs.fraction if line.customs.fraction else fraction
|
||||
|
||||
country = line.customs.origin_country
|
||||
if line_item:
|
||||
if line_item and line_item.customs:
|
||||
country = (
|
||||
line_item.customs.fraction if line_item.customs.origin_country else country
|
||||
line_item.customs.origin_country
|
||||
if line_item.customs.origin_country
|
||||
else country
|
||||
)
|
||||
|
||||
fraction_type = line.customs.fraction_type.upper()
|
||||
if line_item:
|
||||
if line_item and line_item.customs:
|
||||
fraction_type = (
|
||||
line_item.customs.fraction_type
|
||||
if line_item.customs.fraction_type
|
||||
@@ -195,7 +195,7 @@ def validate_common(
|
||||
)
|
||||
|
||||
sector = line.customs.sector
|
||||
if line_item:
|
||||
if line_item and line_item.customs:
|
||||
sector = line_item.customs.sector if line_item.customs.sector else sector
|
||||
|
||||
country_m3 = db.query(Country.m3_key).filter(Country.m3_key == country).scalar()
|
||||
|
||||
@@ -206,8 +206,8 @@ def validate_create(
|
||||
net_weight_input = line.quantity.net_weight or Decimal("0")
|
||||
|
||||
# Determinar si la unidad de medida es de peso
|
||||
unit_is_kgs = line.unit_of_measure and line.unit_of_measure.upper() == "KGS"
|
||||
unit_is_lbs = line.unit_of_measure and line.unit_of_measure.upper() == "LB"
|
||||
unit_is_kgs = line.unit_of_measure and line.unit_of_measure == "24" #KGS
|
||||
unit_is_lbs = line.unit_of_measure and line.unit_of_measure == "25" #LBS
|
||||
|
||||
# Calcular peso neto en kilogramos (estándar interno)
|
||||
if unit_is_kgs:
|
||||
@@ -237,11 +237,11 @@ def validate_create(
|
||||
package_weight_unit = Decimal("0")
|
||||
|
||||
# Obtener peso unitario del bulto si existe
|
||||
if line.quantity.package_key:
|
||||
if line.quantity.package_id:
|
||||
package: Package = (
|
||||
db.query(Package)
|
||||
.filter(
|
||||
Package.key == line.quantity.package_key,
|
||||
Package.id == line.quantity.package_id,
|
||||
Package.tenant_id == tenant_id,
|
||||
Package.company_id == company_id,
|
||||
)
|
||||
@@ -278,22 +278,22 @@ def validate_create(
|
||||
# ==========================================
|
||||
# ASIGNAR DESCRIPCIÓN DE BULTOS
|
||||
# ==========================================
|
||||
if package_quantity and package_quantity > 0 and line.quantity.package_key:
|
||||
if package_quantity and package_quantity > 0 and line.quantity.package_id:
|
||||
package: Package = (
|
||||
db.query(Package)
|
||||
.filter(
|
||||
Package.key == line.quantity.package_key,
|
||||
Package.id == line.quantity.package_id,
|
||||
Package.tenant_id == tenant_id,
|
||||
Package.company_id == company_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if package:
|
||||
line.quantity.package_description = package.description_es
|
||||
line.description.package_description = package.description_es
|
||||
else:
|
||||
line.quantity.package_quantity = 0
|
||||
line.quantity.package_key = None
|
||||
line.quantity.package_description = None
|
||||
line.quantity.package_id = None
|
||||
line.description.package_description = None
|
||||
|
||||
# ==========================================
|
||||
# ASIGNAR FRACCIÓN AMERICANA POR DEFECTO
|
||||
|
||||
@@ -24,7 +24,8 @@ class LineDescription(Base):
|
||||
description_english: Mapped[Optional[str]] = mapped_column(String(4999)) # DESCRIPCIONI
|
||||
extra_description: Mapped[Optional[str]] = mapped_column(Text) # DESCRIPCIONEEXTRA
|
||||
part_description: Mapped[Optional[str]] = mapped_column(String(500)) # DESCRIPCIONPARTE
|
||||
class_description: Mapped[Optional[str]] = mapped_column(String(500)) # DESCRIPCIONCLASE
|
||||
class_description: Mapped[Optional[str]] = mapped_column(String(500)) # DESCRIPCIONCLASE
|
||||
package_description: Mapped[Optional[str]] = mapped_column(String(500)) # DESCRIPCIONBULTO
|
||||
|
||||
# Product attributes
|
||||
brand: Mapped[Optional[str]] = mapped_column(String(50)) # MARCA
|
||||
|
||||
@@ -13,6 +13,7 @@ class LineDescriptionBase(BaseModel):
|
||||
extra_description: Optional[str] = Field(None, description="Extra description (DESCRIPCIONEEXTRA)")
|
||||
part_description: Optional[str] = Field(None, max_length=500, description="Part description (DESCRIPCIONPARTE)")
|
||||
class_description: Optional[str] = Field(None, max_length=500, description="Class description (DESCRIPCIONCLASE)")
|
||||
package_description: Optional[str] = Field(None, max_length=500, description="Package description (DESCRIPCIONBULTO)")
|
||||
|
||||
# Product attributes
|
||||
brand: Optional[str] = Field(None, max_length=50, description="Brand (MARCA)")
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
import type { LineFinancials, LineQuantities } from '$lib/api/dashboard/a76/items';
|
||||
|
||||
let { financials = $bindable(), quantities = $bindable() }: { financials: LineFinancials; quantities: LineQuantities } = $props();
|
||||
|
||||
// Helper function to safely format numbers
|
||||
function formatNumber(value: any, decimals: number = 8): string {
|
||||
const num = Number(value);
|
||||
return isNaN(num) ? '0.00000000' : num.toFixed(decimals);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
@@ -10,18 +16,18 @@
|
||||
|
||||
<div class="text-xs font-semibold">RETURN QUANTITY SUB-ITEMS</div>
|
||||
<div class="grid grid-cols-2 gap-2 text-xs">
|
||||
<div>Temporary: <span class="text-gray-900 dark:text-gray-100">{quantities.quantity_temp_export?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div>Temporary: <span class="text-gray-900 dark:text-gray-100">{formatNumber(quantities.quantity_temp_export)}</span></div>
|
||||
<div>Replacement or Change: <span class="text-gray-900 dark:text-gray-100">0.00000000</span></div>
|
||||
<div>Definitive: <span class="text-gray-900 dark:text-gray-100">{quantities.quantity_returned?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div>Returned Values: <span class="text-gray-900 dark:text-gray-100">{financials.value_returned_usd?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div class="col-span-2">Returned Values: <span class="text-gray-900 dark:text-gray-100">{financials.value_returned_mxn?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div>Definitive: <span class="text-gray-900 dark:text-gray-100">{formatNumber(quantities.quantity_returned)}</span></div>
|
||||
<div>Returned Values: <span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.value_returned_usd)}</span></div>
|
||||
<div class="col-span-2">Returned Values: <span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.value_returned_mxn)}</span></div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-2 text-xs pt-2 border-t">
|
||||
<div class="font-semibold">WEIGHTS (KILOS)</div>
|
||||
<div class="font-semibold">WEIGHTS (Pounds)</div>
|
||||
<div>Net: <span class="text-gray-900 dark:text-gray-100">{quantities.net_weight?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div>Net: <span class="text-gray-900 dark:text-gray-100">{formatNumber(quantities.net_weight)}</span></div>
|
||||
<div><span class="text-gray-900 dark:text-gray-100">0.00000000</span></div>
|
||||
<div>Whole: <span class="text-gray-900 dark:text-gray-100">{quantities.gross_weight?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div>Whole: <span class="text-gray-900 dark:text-gray-100">{formatNumber(quantities.gross_weight)}</span></div>
|
||||
<div><span class="text-gray-900 dark:text-gray-100">0.00000000</span></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
@@ -33,13 +39,13 @@
|
||||
<div class="grid grid-cols-2 gap-2 text-xs">
|
||||
<div class="font-semibold">(Dollars)</div>
|
||||
<div class="font-semibold">(Pesos)</div>
|
||||
<div>Cost: <span class="text-gray-900 dark:text-gray-100">{financials.unit_cost_usd?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div><span class="text-gray-900 dark:text-gray-100">{financials.unit_cost_mxn?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div>Value: <span class="text-gray-900 dark:text-gray-100">{financials.value_usd?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div><span class="text-gray-900 dark:text-gray-100">{financials.value_mxn?.toFixed(8) || '0.00000000'}</span></div>
|
||||
<div class="text-xs">Capture Cost: <span class="text-gray-900 dark:text-gray-100">{financials.unit_cost_capture?.toFixed(8) || '0.00000000'}</span> <span class="text-gray-900 dark:text-gray-100">USD</span></div>
|
||||
<div class="text-xs">Capture Value: <span class="text-gray-900 dark:text-gray-100">{financials.value_usd?.toFixed(8) || '0.00000000'}</span> <span class="text-gray-900 dark:text-gray-100">USD</span></div>
|
||||
<div class="text-xs">Customs Value: <span class="text-gray-900 dark:text-gray-100">{financials.customs_value_usd?.toFixed(8) || '0.00000000'}</span> <span class="text-gray-900 dark:text-gray-100">USD</span></div>
|
||||
<div>Cost: <span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.unit_cost_usd)}</span></div>
|
||||
<div><span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.unit_cost_mxn)}</span></div>
|
||||
<div>Value: <span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.value_usd)}</span></div>
|
||||
<div><span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.value_mxn)}</span></div>
|
||||
<div class="text-xs">Capture Cost: <span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.unit_cost_capture)}</span> <span class="text-gray-900 dark:text-gray-100">USD</span></div>
|
||||
<div class="text-xs">Capture Value: <span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.value_usd)}</span> <span class="text-gray-900 dark:text-gray-100">USD</span></div>
|
||||
<div class="text-xs">Customs Value: <span class="text-gray-900 dark:text-gray-100">{formatNumber(financials.customs_value_usd)}</span> <span class="text-gray-900 dark:text-gray-100">USD</span></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user