- Updated `TimestampMixin` to use `server_default` for `created_at` and `updated_at` fields. - Modified various models in the `fa_classes`, `doc_types_dig`, `ports`, `units_of_measure`, `invoices`, `parts`, `trailers`, `licenses`, `tenants`, and `user_tenant` modules to set `server_default` for boolean fields and other relevant fields. - Adjusted the `trailer_types` model to change the schema from `a76` to `public`. - Implemented database migration execution during application startup in `main.py`. - Removed old Alembic migration execution logic from the entrypoint script. - Updated seed data for units of measure and removed unused seed files.
126 lines
4.5 KiB
Python
126 lines
4.5 KiB
Python
"""
|
|
Modelos ORM para gestión de partes/componentes - Anexo 76 (Master Data)
|
|
"""
|
|
|
|
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 (
|
|
ForeignKeyConstraint,
|
|
Integer,
|
|
Numeric,
|
|
PrimaryKeyConstraint,
|
|
String,
|
|
UniqueConstraint,
|
|
Boolean,
|
|
DateTime,
|
|
)
|
|
|
|
# Importante usar relationship y Mapped
|
|
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.currency_types.models import CurrencyType
|
|
from api.v1.modules.a76.general_catalogs.units_of_measure.models import (
|
|
UnitOfMeasure,
|
|
)
|
|
from api.v1.modules.a24.fa.fa_parts.models import FaPart
|
|
from api.v1.modules.a24.inv.inv_parts.models import InvPart
|
|
|
|
|
|
class Part(Base, TenantScopedMixin, TimestampMixin):
|
|
__tablename__ = "parts"
|
|
__table_args__ = (
|
|
PrimaryKeyConstraint("id", name="parts_pkey"),
|
|
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",
|
|
],
|
|
),
|
|
# Puente hacia la tabla de clases
|
|
ForeignKeyConstraint(
|
|
["part_class", "tenant_id", "company_id"],
|
|
[
|
|
"a76.classes.class_code",
|
|
"a76.classes.tenant_id",
|
|
"a76.classes.company_id",
|
|
],
|
|
name="fk_parts_class",
|
|
),
|
|
UniqueConstraint(
|
|
"tenant_id", "company_id", "part_number", name="client_part_ukey"
|
|
),
|
|
{"schema": "a76"},
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
client_id: Mapped[int] = mapped_column(Integer)
|
|
part_number: Mapped[str] = mapped_column(String(70))
|
|
commercial_part_number: Mapped[Optional[str]] = mapped_column(String(70))
|
|
|
|
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))
|
|
|
|
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))
|
|
|
|
unit_weight: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8))
|
|
weight_type: Mapped[Optional[str]] = mapped_column(String(6))
|
|
|
|
fraction: Mapped[Optional[str]] = mapped_column(String(10))
|
|
us_fraction: Mapped[Optional[str]] = mapped_column(String(16))
|
|
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_code: Mapped[Optional[str]] = mapped_column(String(2))
|
|
exclusion_symbol: Mapped[Optional[str]] = mapped_column(String(19))
|
|
|
|
is_active: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=True, server_default="true"
|
|
)
|
|
part_photo: Mapped[Optional[str]] = mapped_column(String(255))
|
|
|
|
creation_date: Mapped[Optional[int]] = mapped_column()
|
|
modification_date: Mapped[Optional[int]] = mapped_column()
|
|
modification_date_iso: Mapped[Optional[datetime]] = mapped_column(DateTime)
|
|
|
|
# --- RELACIONES ---
|
|
currency: Mapped[Optional["CurrencyType"]] = relationship("CurrencyType")
|
|
unit_of_measure_info: Mapped[Optional["UnitOfMeasure"]] = relationship(
|
|
"UnitOfMeasure"
|
|
)
|
|
part_class_info: Mapped[Optional["Class"]] = relationship(
|
|
"Class", back_populates="parts", overlaps="unit_of_measure_info"
|
|
)
|
|
|
|
# Extensiones Anexo 24
|
|
fa_data: Mapped[Optional["FaPart"]] = relationship(
|
|
"FaPart",
|
|
back_populates="master_info",
|
|
uselist=False,
|
|
cascade="all, delete-orphan",
|
|
)
|
|
inv_data: Mapped[Optional["InvPart"]] = relationship(
|
|
"InvPart",
|
|
back_populates="master_info",
|
|
uselist=False,
|
|
cascade="all, delete-orphan",
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Part(id={self.id}, part_number='{self.part_number}')>"
|