Partidas BOM y partes para SCAI

This commit is contained in:
2026-03-11 11:11:36 -05:00
parent 2ac07b55b6
commit 9f3ae8db42
34 changed files with 5101 additions and 1040 deletions

View File

@@ -14,6 +14,7 @@ from sqlalchemy import (
Boolean,
ForeignKeyConstraint
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
@@ -100,9 +101,60 @@ class InvPart(Base, TenantScopedMixin, TimestampMixin):
dtb: Mapped[Optional[str]] = mapped_column(String(19)) # DTB
dtg: Mapped[Optional[str]] = mapped_column(String(19)) # DTG
# --- CAMPOS ADICIONALES FRONTEND ---
substitute_part: Mapped[Optional[str]] = mapped_column(String(70))
complementary_part: Mapped[Optional[str]] = mapped_column(String(70))
preference_part: Mapped[Optional[str]] = mapped_column(String(70))
use_alternate_quantity: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
un_number: Mapped[Optional[str]] = mapped_column(String(30))
shipping_name: Mapped[Optional[str]] = mapped_column(String(200))
hazard_notes: Mapped[Optional[str]] = mapped_column(String(500))
repair_unit_cost: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
repair_added_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
fraction_9801: Mapped[Optional[str]] = mapped_column(String(10))
immex_type: Mapped[Optional[str]] = mapped_column(String(10))
disable_movements: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
pga_program_code: Mapped[Optional[str]] = mapped_column(String(10))
usmca_fraction: Mapped[Optional[str]] = mapped_column(String(10))
scrap_part_number: Mapped[Optional[str]] = mapped_column(String(70))
waste_part_number: Mapped[Optional[str]] = mapped_column(String(70))
scrap_description_en: Mapped[Optional[str]] = mapped_column(String(500))
scrap_description_es: Mapped[Optional[str]] = mapped_column(String(500))
scrap_export_fraction: Mapped[Optional[str]] = mapped_column(String(10))
scrap_us_fraction: Mapped[Optional[str]] = mapped_column(String(10))
equivalent_uom_2: Mapped[Optional[str]] = mapped_column(String(5))
conversion_factor_2: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8))
has_auxiliary: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
auxiliary_uom: Mapped[Optional[str]] = mapped_column(String(5))
auxiliary_conversion: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8))
auxiliary_unit_cost: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
mex_packing: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
sales_order: Mapped[Optional[str]] = mapped_column(String(50))
use_rule_8: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
sector: Mapped[Optional[str]] = mapped_column(String(150))
origin_country: Mapped[Optional[str]] = mapped_column(String(3), default='MEX')
fraction_type: Mapped[Optional[str]] = mapped_column(String(10))
# JSONB para almacenar clientes con restricción de no descarga
non_discharge_clients: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True, default=[])
# --- RELACIÓN ---
# Usamos string "Part" para evitar problemas de carga
master_info: Mapped["Part"] = relationship("Part", back_populates="inv_data")
@property
def bom_items(self):
"""Exponer los BOM items de la parte maestra para Pydantic"""
if self.master_info:
return self.master_info.bom_items
return []
@property
def countries(self):
"""Exponer los países de la parte maestra para Pydantic"""
if self.master_info:
return self.master_info.inv_countries
return []
def __repr__(self) -> str:
return f"<InvPart(id={self.id}, part_type='{self.part_type}')>"