Files
plantillas-proyectos/backend/api/v1/modules/a76/parts/models.py
acazares 6acbd48e9e feat: Implement general catalogs for INPC, Legends, Multi-Currency Types, Packages, Ports, Prevalidators, Signatures, Unit Conversions, and Units of Measure
- Added INPC management page with search functionality.
- Created Legends management page with filters for code and description.
- Implemented Multi-Currency Types management with search capabilities.
- Developed Packages management page with filtering options.
- Introduced Ports management page with authentication and data fetching.
- Added Prevalidators management page with search filters.
- Implemented Signatures management page with search by name and position.
- Created Unit Conversions management page for conversion factors.
- Developed Units of Measure management pages for ACE, American, and OMA with data tables and create/edit dialogs.
2025-12-08 14:17:47 -06:00

134 lines
5.1 KiB
Python

"""
Modelos ORM para gestión de partes/componentes
"""
from datetime import datetime
from decimal import Decimal
from typing import TYPE_CHECKING, Optional
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
ForeignKey,
ForeignKeyConstraint,
Integer,
Numeric,
PrimaryKeyConstraint,
SmallInteger,
String,
UniqueConstraint,
Boolean,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
if TYPE_CHECKING:
from api.v1.modules.a76.classes.models import Class
from api.v1.modules.public.reference_data.countries.models import Country
from api.v1.modules.public.reference_data.currency_types.models import CurrencyType
from api.v1.modules.a76.general_catalogs.units_of_measure.models import UnitOfMeasure
class Part(Base, TenantScopedMixin, TimestampMixin):
"""
Modelo para la tabla GPartes - Información de partes en los sistemas SCAII (N), SCAF (S) Y WINSAAI (W)
"""
__tablename__ = "parts"
__table_args__ = (
PrimaryKeyConstraint("id", name="parts_pkey"),
ForeignKeyConstraint(
["country_of_origin"], ["public.countries.m3_key"], name="fk_parts_country"
),
ForeignKeyConstraint(
["currency_key"], ["public.currency_types.code"], name="fk_parts_currency"
),
ForeignKeyConstraint(
["unit_of_measure", "tenant_id", "company_id"],
["a76.units_of_measure.code", "a76.units_of_measure.tenant_id",
"a76.units_of_measure.company_id"],
),
UniqueConstraint(
"tenant_id", "company_id", "part_number", name="client_part_ukey"
),
{"schema": "a76"},
)
id: Mapped[int] = mapped_column(Integer, primary_key=True)
# Unique constraint compuesta
client_id: Mapped[int] = mapped_column(Integer)
part_number: Mapped[str] = mapped_column(String(49))
# Basic information
fraction: Mapped[Optional[str]] = mapped_column(String(10))
description_spanish: Mapped[Optional[str]] = mapped_column(String(500))
description_english: Mapped[Optional[str]] = mapped_column(String(500))
part_class: Mapped[Optional[str]] = mapped_column(String(8))
unit_of_measure: Mapped[Optional[str]] = mapped_column(
String(5)
)
commercial_part_number: Mapped[Optional[str]] = mapped_column(String(70))
country_of_origin: Mapped[Optional[str]] = mapped_column(String(3))
# Pricing and currency
unit_cost: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
currency_type: Mapped[Optional[str]] = mapped_column(String(2))
currency_key: Mapped[Optional[str]] = mapped_column(String(3))
# Weight information
unit_weight: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8))
weight_type: Mapped[Optional[str]] = mapped_column(String(6))
# Classification and regulatory
us_fraction: Mapped[Optional[str]] = mapped_column(
String(16)) # FRACCIONAME
fda_key: Mapped[Optional[str]] = mapped_column(String(20))
fcc_key: Mapped[Optional[str]] = mapped_column(String(30))
license_code: Mapped[Optional[str]] = mapped_column(String(3))
eccn: Mapped[Optional[str]] = mapped_column(
String(20)
) # Export Control Classification Number
export_code: Mapped[Optional[str]] = mapped_column(String(2))
exclusion_symbol: Mapped[Optional[str]] = mapped_column(
String(19)) # SIMBOLOEXCLIC
# Additional information
supplier: Mapped[Optional[str]] = mapped_column(String(14))
alternate_unit_measure: Mapped[Optional[str]] = mapped_column(String(14))
added_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
# Status and dates
is_active: Mapped[Optional[bool]] = mapped_column(Boolean)
creation_date: Mapped[Optional[int]
] = mapped_column() # FECHACREACIONPARTE
modification_date: Mapped[Optional[int]] = mapped_column() # FECHAMODIFICA
modification_date_iso: Mapped[Optional[datetime]] = (
mapped_column()
) # FECHAMODIFICA_ISO
# Media
part_photo: Mapped[Optional[str]] = mapped_column(String(255))
# Relationships
country: Mapped[Optional["Country"]] = relationship(
foreign_keys=[country_of_origin]
)
currency: Mapped[Optional["CurrencyType"]] = relationship(
foreign_keys=[currency_key]
)
unit_of_measure_info: Mapped[Optional["UnitOfMeasure"]] = relationship(
foreign_keys=[unit_of_measure]
)
# Relationship with Class through composite foreign key
# Note: This requires both client_id and part_class to match client_id and class_code in Class
part_class_info: Mapped[Optional["Class"]] = relationship(
primaryjoin="and_(Part.client_id == Class.client_id, Part.part_class == Class.class_code)",
foreign_keys="[Part.client_id, Part.part_class]",
viewonly=True,
back_populates="parts",
)
def __repr__(self) -> str:
return f"<Part(client_id={self.client_id}, part_number='{self.part_number}', description='{self.description_spanish}')>"