refactor: restructure item interfaces and update related components
- Renamed LineItem interface to Item and adjusted properties accordingly. - Updated CreateItemData and UpdateItemData interfaces to reflect new structure. - Modified components to use the new Item interface, removing nested lines. - Adjusted data binding in item configuration, main data, and other related components. - Simplified item creation and editing logic by removing unnecessary nesting. - Ensured all references to line items are updated to reflect the new structure.
This commit is contained in:
@@ -3,26 +3,45 @@ Normalized Database Schema for SCAF (Fixed Assets) and SCAII (Parts Inventory)
|
||||
SQLAlchemy v2 - Annex 24 Compliance
|
||||
"""
|
||||
|
||||
from typing import Optional, TYPE_CHECKING, List
|
||||
from sqlalchemy import Boolean, String, Integer, ForeignKey
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
from core.database import Base
|
||||
from decimal import Decimal
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
String,
|
||||
Integer,
|
||||
Numeric,
|
||||
SmallInteger,
|
||||
ForeignKey
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
|
||||
from core.database import Base
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .line_items.models import LineItem
|
||||
from api.v1.modules.a76.classes.models import Class
|
||||
from api.v1.modules.a76.general_catalogs.units_of_measure.models import UnitOfMeasure
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .line_financials.models import LineFinancial
|
||||
from .line_quantities.models import LineQuantity
|
||||
from .line_customs.models import LineCustom
|
||||
from .line_descriptions.models import LineDescription
|
||||
from .line_references.models import LineReference
|
||||
from api.v1.modules.a24.fa.fa_item_lines.models import FaLineItem
|
||||
from api.v1.modules.a76.parts.models import Part
|
||||
from api.v1.modules.a76.invoices.models import InvoiceHeader
|
||||
|
||||
# ============================================================================
|
||||
# CORE ENTITIES
|
||||
# ============================================================================
|
||||
|
||||
|
||||
class Item(Base, TenantScopedMixin, TimestampMixin):
|
||||
class LineItem(Base, TenantScopedMixin, TimestampMixin):
|
||||
"""
|
||||
Unified item header table for all import/export operations
|
||||
Consolidates headers from both SCAF and SCAII systems
|
||||
"""
|
||||
__tablename__ = "items"
|
||||
__tablename__ = "item_lines"
|
||||
__table_args__ = {
|
||||
"schema": "a76",
|
||||
}
|
||||
@@ -30,6 +49,129 @@ class Item(Base, TenantScopedMixin, TimestampMixin):
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id")) # CONSECUTIVO
|
||||
|
||||
line_number: Mapped[int] = mapped_column(Integer) # LINEAIMPO/LINEAEXPO/LINEA
|
||||
|
||||
# Part identification
|
||||
part_number_id: Mapped[Optional[int]] = mapped_column(
|
||||
Integer, ForeignKey("a76.parts.id")
|
||||
) # NUMPARTE
|
||||
component_part_number_id: Mapped[Optional[int]] = mapped_column(
|
||||
Integer, ForeignKey("a76.parts.id")
|
||||
) # NUMPARTECOM
|
||||
class_id: Mapped[Optional[int]] = mapped_column(
|
||||
ForeignKey("a76.classes.id")
|
||||
) # CLASE
|
||||
|
||||
# Unit of measure
|
||||
unit_of_measure: Mapped[Optional[int]] = mapped_column(
|
||||
ForeignKey("a76.units_of_measure.id")
|
||||
) # UNIDADMEDIDA/UNIMED
|
||||
alternate_unit: Mapped[Optional[int]] = mapped_column(
|
||||
ForeignKey("a76.units_of_measure.id")
|
||||
) # UNIMEDALTERNA
|
||||
uma_key: Mapped[Optional[str]] = mapped_column(String(2)) # CLAVEUMA
|
||||
auxiliary_unit: Mapped[Optional[str]] = mapped_column(String(5)) # UNIMEDAUXILIAR
|
||||
|
||||
# Permits and certificates
|
||||
permit_number: Mapped[Optional[str]] = mapped_column(String(20)) # NUMPERMISO
|
||||
page_line: Mapped[Optional[str]] = mapped_column(String(10)) # PAGRENGLON
|
||||
has_certificate: Mapped[Optional[bool]] = mapped_column(
|
||||
Boolean
|
||||
) # TIENECO/CERTORIGEN
|
||||
certificate_number: Mapped[Optional[str]] = mapped_column(
|
||||
String(10)
|
||||
) # NOCERTIFICADO
|
||||
octave_permit: Mapped[Optional[str]] = mapped_column(String(20)) # PERMISOROCTAVA
|
||||
permits_ped: Mapped[Optional[str]] = mapped_column(String(500)) # PERMISOSPED
|
||||
|
||||
# FDA
|
||||
has_fda_code: Mapped[Optional[bool]] = mapped_column(Boolean) # LLEVACODFDA
|
||||
fda_key: Mapped[Optional[str]] = mapped_column(String(10)) # CLAVEFDA
|
||||
|
||||
# Special flags
|
||||
is_military_mcia: Mapped[Optional[bool]] = mapped_column(Boolean) # ESMCIAMILITAR
|
||||
|
||||
# IV32 (Tax identification)
|
||||
iv32_type_key: Mapped[Optional[str]] = mapped_column(String(5)) # CLAVETIPOIV32
|
||||
iv32_number: Mapped[Optional[str]] = mapped_column(String(35)) # NUMEROIV32
|
||||
|
||||
# IN CASE OF EXPO
|
||||
scrap_invoice: Mapped[Optional[str]] = mapped_column(String(15)) # FACTURASCRAP
|
||||
consecutive_destination: Mapped[Optional[int]] = mapped_column(
|
||||
Integer
|
||||
) # CONSECUTIVODES
|
||||
ctm_section: Mapped[Optional[str]] = mapped_column(String(3)) # APARTADOCTM
|
||||
|
||||
# Tax payment
|
||||
tax_payment: Mapped[Optional[bool]] = mapped_column(Boolean) # PAGOIMPUESTO
|
||||
payment_method: Mapped[Optional[str]] = mapped_column(
|
||||
String(9)
|
||||
) # FORMAPAGO/FORMAPAGOTIGI
|
||||
igi_amount: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # MONTOIGI
|
||||
igi_payment_method: Mapped[Optional[str]] = mapped_column(
|
||||
String(9)
|
||||
) # FORMAPAGOTIGI
|
||||
|
||||
# FCC
|
||||
fcc_key: Mapped[Optional[str]] = mapped_column(String(30)) # CLAVEFCC
|
||||
|
||||
# Valuation method
|
||||
valuation_method: Mapped[Optional[str]] = mapped_column(String(2)) # METVALOR
|
||||
valuation_determined_value: Mapped[Optional[Decimal]] = mapped_column(
|
||||
Numeric(29, 8)
|
||||
) # METVALORVALORDETERMINADO/METVALORACIONVALORDETERMINADO
|
||||
valuation_reason: Mapped[Optional[str]] = mapped_column(
|
||||
String(500)
|
||||
) # METVALORMOTIVODEUSO/METVALORACIONMOTIVODEUSO
|
||||
|
||||
# Container rules
|
||||
container_rule: Mapped[Optional[str]] = mapped_column(String(50)) # CONTENEDORREGLA
|
||||
container_parts_ii: Mapped[Optional[str]] = mapped_column(
|
||||
String(50)
|
||||
) # CONTENEDORPARTESII
|
||||
|
||||
# APHIS
|
||||
consecutive_aphis: Mapped[Optional[int]] = mapped_column(
|
||||
Integer
|
||||
) # CONSECUTIVOAPHIS
|
||||
|
||||
# BOM/Commercial
|
||||
bom_version: Mapped[Optional[int]] = mapped_column(Integer) # VERSIONBOM
|
||||
bill_version: Mapped[Optional[int]] = mapped_column(Integer) # VERSIONBILL
|
||||
|
||||
# TLCAN value
|
||||
tlcan_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # VALORTLCAN
|
||||
|
||||
# Identifier
|
||||
identifier: Mapped[Optional[str]] = mapped_column(String(2)) # IDENTIFICADOR
|
||||
|
||||
# Validation fields
|
||||
validation_zero: Mapped[Optional[int]] = mapped_column(Integer) # VALIDACIONZERO
|
||||
validation_one: Mapped[Optional[int]] = mapped_column(Integer) # VALIDACIONUNO
|
||||
|
||||
# Material type
|
||||
material_type: Mapped[Optional[str]] = mapped_column(
|
||||
String(50)
|
||||
) # TIPOMAT/TIPODENUMPARTE
|
||||
|
||||
# Order concept
|
||||
order_type: Mapped[Optional[str]] = mapped_column(String(50)) # TIPODEORDEN
|
||||
line_concept: Mapped[Optional[str]] = mapped_column(
|
||||
String(50)
|
||||
) # CONCEPTODELAPARTIDA
|
||||
|
||||
# Review dispatch
|
||||
review_dispatch: Mapped[Optional[str]] = mapped_column(String(10)) # REVISARDESP
|
||||
|
||||
# Take component from PT
|
||||
take_component_pt: Mapped[Optional[int]] = mapped_column(Integer) # TOMARCOMOPT
|
||||
|
||||
# Pallet
|
||||
pallet2: Mapped[Optional[int]] = mapped_column(SmallInteger) # PALLET2
|
||||
|
||||
# Wildcard field
|
||||
wildcard_field: Mapped[Optional[str]] = mapped_column(String(100)) # CAMPOCOMODIN
|
||||
|
||||
# Item references
|
||||
reference_number: Mapped[Optional[str]] = mapped_column(
|
||||
String(20)) # NUMREFERENCIA
|
||||
@@ -48,12 +190,46 @@ class Item(Base, TenantScopedMixin, TimestampMixin):
|
||||
warehouse: Mapped[Optional[str]] = mapped_column(String(30)) # BODEGA
|
||||
location: Mapped[Optional[str]] = mapped_column(
|
||||
String(200)) # LOCALIZACION
|
||||
|
||||
# Relationships (one-to-many)
|
||||
lines: Mapped[List["LineItem"]] = relationship(
|
||||
"LineItem", back_populates="item", cascade="all, delete-orphan")
|
||||
|
||||
invoice: Mapped["InvoiceHeader"] = relationship("InvoiceHeader")
|
||||
|
||||
# Relationships
|
||||
financial: Mapped[Optional["LineFinancial"]] = relationship(
|
||||
back_populates="line", cascade="all, delete-orphan", uselist=False
|
||||
)
|
||||
quantity: Mapped[Optional["LineQuantity"]] = relationship(
|
||||
back_populates="line", cascade="all, delete-orphan", uselist=False
|
||||
)
|
||||
customs: Mapped[Optional["LineCustom"]] = relationship(
|
||||
back_populates="line", cascade="all, delete-orphan", uselist=False
|
||||
)
|
||||
description: Mapped[Optional["LineDescription"]] = relationship(
|
||||
back_populates="line", cascade="all, delete-orphan", uselist=False
|
||||
)
|
||||
reference: Mapped[Optional["LineReference"]] = relationship(
|
||||
back_populates="line", cascade="all, delete-orphan", uselist=False
|
||||
)
|
||||
class_info: Mapped[Optional["Class"]] = relationship(
|
||||
"api.v1.modules.a76.classes.models.Class",
|
||||
foreign_keys=[class_id],
|
||||
viewonly=True,
|
||||
)
|
||||
unit_of_measure_info: Mapped[Optional["UnitOfMeasure"]] = relationship(
|
||||
"api.v1.modules.a76.general_catalogs.units_of_measure.models.UnitOfMeasure",
|
||||
foreign_keys=[unit_of_measure],
|
||||
viewonly=True,
|
||||
)
|
||||
fa_data: Mapped[Optional["FaLineItem"]] = relationship(
|
||||
"FaLineItem",
|
||||
back_populates="master_info",
|
||||
cascade="all, delete-orphan",
|
||||
uselist=False,
|
||||
)
|
||||
part_info: Mapped[Optional["Part"]] = relationship(
|
||||
"Part",
|
||||
foreign_keys=[part_number_id],
|
||||
viewonly=True,
|
||||
)
|
||||
|
||||
# ============================================================================
|
||||
# SUPPORTING TABLES
|
||||
@@ -189,8 +365,8 @@ MIGRATION STRATEGY FROM ORIGINAL TABLES TO NORMALIZED SCHEMA:
|
||||
7. QUERYING EXAMPLES:
|
||||
```python
|
||||
# Get all imports (both systems)
|
||||
session.query(Item).filter(
|
||||
Item.item_type.in_(['IMPORT', 'EQUIPMENT_IMPORT_TEMP', 'EQUIPMENT_IMPORT_DEF'])
|
||||
session.query(LineItem).filter(
|
||||
LineItem.item_type.in_(['IMPORT', 'EQUIPMENT_IMPORT_TEMP', 'EQUIPMENT_IMPORT_DEF'])
|
||||
)
|
||||
|
||||
# Get all lines for a specific part across all items
|
||||
@@ -199,8 +375,8 @@ MIGRATION STRATEGY FROM ORIGINAL TABLES TO NORMALIZED SCHEMA:
|
||||
)
|
||||
|
||||
# Get SCAF equipment with depreciation
|
||||
session.query(Item).join(LineItem).filter(
|
||||
Item.system_origin == 'SCAF',
|
||||
session.query(LineItem).join(LineItem).filter(
|
||||
LineItem.system_origin == 'SCAF',
|
||||
LineItem.value_depreciated_usd.isnot(None)
|
||||
)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user