Merge branch 'development' into feature/fraction-API

This commit is contained in:
Galindo97
2026-02-16 12:04:56 -06:00
48 changed files with 697 additions and 461 deletions

View File

@@ -58,7 +58,7 @@ def validate_update(
# Columna A: Pedimento (si no viene en CSV, usar el existente)
if invoice_data.compliance_mx.pedimento_id:
invoice_data.compliance_mx.pedimento_id = clean_str(invoice_data.compliance_mx.pedimento_id)
invoice_data.compliance_mx.pedimento_id = invoice_data.compliance_mx.pedimento_id
else:
invoice_data.compliance_mx.pedimento_id = existing_invoice.compliance_mx.pedimento_id if existing_invoice.compliance_mx else None

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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)")

View File

@@ -17,6 +17,7 @@ from api.v1.modules.public.reference_data.customs_sections.dto import CustomsSec
from api.v1.modules.public.reference_data.code_pedimento_regimens.dto import CodePedimentoRegimenDTO
from api.v1.modules.a76.customs_brokers.dto import CustomsBrokerResponseDTO
from api.v1.modules.a76.clients_and_providers.dto import ClientProviderResponseDTO
from .dtos.pedimentos import PedimentosResponse
from .schemas import PedimentoCatalogsResponse, PedimentoCreationResponse, PedimentoEditionResponse
@@ -111,10 +112,13 @@ class PedimentoCatalogService:
if not pedimento:
return None
# Convert SQLAlchemy object to Pydantic DTO
pedimento_dto = PedimentosResponse.model_validate(pedimento)
return PedimentoEditionResponse(
**catalogs.model_dump(),
is_create=False,
pedimento=pedimento,
pedimento=pedimento_dto,
pedimento_id=pedimento_id
)

View File

@@ -2,7 +2,7 @@
Consolidated schemas for Pedimento catalog responses
"""
from typing import List, Optional, Any
from typing import List, Optional
from pydantic import BaseModel
# Import DTOs for catalog items
@@ -11,6 +11,7 @@ from api.v1.modules.public.reference_data.customs_sections.dto import CustomsSec
from api.v1.modules.public.reference_data.code_pedimento_regimens.dto import CodePedimentoRegimenDTO
from api.v1.modules.a76.customs_brokers.dto import CustomsBrokerResponseDTO
from api.v1.modules.a76.clients_and_providers.dto import ClientProviderResponseDTO
from .dtos.pedimentos import PedimentosResponse
class PedimentoCatalogsResponse(BaseModel):
@@ -33,5 +34,5 @@ class PedimentoEditionResponse(PedimentoCatalogsResponse):
"""Response for editing an existing pedimento (catalogs + pedimento data)"""
is_create: bool = False
pedimento: Optional[Any] = None # Will be PedimentosResponse but avoiding circular import
pedimento: Optional[PedimentosResponse] = None
pedimento_id: Optional[int] = None