760 lines
29 KiB
Python
760 lines
29 KiB
Python
from enum import Enum
|
|
from typing import Optional, List, TYPE_CHECKING
|
|
from sqlalchemy import (
|
|
BigInteger,
|
|
Boolean,
|
|
Date,
|
|
ForeignKey,
|
|
Integer,
|
|
Numeric,
|
|
String,
|
|
Text,
|
|
TIMESTAMP,
|
|
func,
|
|
)
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
from core.database import Base
|
|
from datetime import datetime
|
|
from ....common.base_models import TenantScopedMixin, TimestampMixin
|
|
|
|
if TYPE_CHECKING:
|
|
from api.v1.modules.a76.pedmientos.models.pedimentos import Pedimentos
|
|
|
|
|
|
class Currency(str, Enum):
|
|
FOREIGN = "foreign"
|
|
LOCAL = "local"
|
|
MANUAL = "manual"
|
|
|
|
|
|
class WeightUnit(str, Enum):
|
|
KGS = "kgs"
|
|
LBS = "lbs"
|
|
|
|
|
|
class DestinationOriginCove(str, Enum):
|
|
EDO_BC_PARC_SON = "edo_bc_parc_son"
|
|
ESTADO_BCS = "estado_bcs"
|
|
ESTADO_ROO = "estado_roo"
|
|
MPIO_SALINA_CRUZ_OAX = "mpio_salina_cruz_oxa"
|
|
FRANJA_FRONT_NORTE = "franja_front_norte"
|
|
INTERIOR_PAIS = "interior_pais"
|
|
MPIO_CABORCA_SON = "mpio_caborca_son"
|
|
|
|
|
|
class OperationType(str, Enum):
|
|
IMP = "imp" # Importación
|
|
EXP = "exp" # Exportación
|
|
SM_IN = "sm_in" # Entrada SM
|
|
SM_OUT = "sm_out" # Salida SM
|
|
CTM_SEND = "ctm_send" # Envío CTM
|
|
CTM_RECEIVE = "ctm_receive" # Recibo CTM
|
|
|
|
|
|
class TransportType(str, Enum):
|
|
NONE = "none"
|
|
TRANSPORT = "transport"
|
|
BOX = "box"
|
|
PLATES = "licence plates"
|
|
TRUCK = "truck"
|
|
VESSEL = "vessel"
|
|
BARGE = "rail_barge"
|
|
CONTAINER = "container"
|
|
AIRPLANE = "airplane"
|
|
GONDOLA = "gondola"
|
|
FLATBED = "flatbed"
|
|
|
|
|
|
# --- 1. Invoice Header (invoice_header) ---
|
|
class InvoiceHeader(Base, TenantScopedMixin, TimestampMixin):
|
|
__tablename__ = "invoice_header"
|
|
__table_args__ = ({"schema": "a76"},)
|
|
|
|
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
|
|
|
|
# Identifiers
|
|
system: Mapped[str] = mapped_column(
|
|
String(12)
|
|
) # SISTEMA / Sistema de origen <-- no tiene campo en la antigua base de datos, sera para fixed_asset(scaf), inventory(scaii)
|
|
operation_type: Mapped[OperationType] = mapped_column(
|
|
String(11)
|
|
) # TIPOMOVIMIENTO / Clasifica imp/exp/sm/ctm
|
|
invoice_type: Mapped[str] = mapped_column(
|
|
ForeignKey("public.invoice_types.key")
|
|
) # TIPOFACTURA / TIPODOC
|
|
document_type: Mapped[Optional[str]] = mapped_column(
|
|
ForeignKey("public.pedimento_regimens.code"), nullable=True
|
|
)
|
|
# CLAVEDOCUMENTO / Clave de documento
|
|
invoice_number: Mapped[str] = mapped_column(
|
|
String(100)
|
|
) # FACTURAIMPO/FACTURAEXPO/FACTURAREMISION/FACTURAENVIO/FACTURASALIDA
|
|
project_number: Mapped[Optional[str]] = mapped_column(String(14)) # NUMPROYECTO
|
|
purchase_order: Mapped[Optional[str]] = mapped_column(String(50)) # ORDENCOMPRA
|
|
related_doc_id: Mapped[Optional[int]] = mapped_column(
|
|
Integer
|
|
) # IDRELDOC / Para Rectificaciones
|
|
alternate_invoice: Mapped[Optional[str]] = mapped_column(
|
|
String(99)
|
|
) # FACTURAALTERNA
|
|
invoice_ref: Mapped[Optional[str]] = mapped_column(String(19)) # FACTURAEXPOREF
|
|
proforma_number: Mapped[Optional[str]] = mapped_column(String(20)) # NUMEROPROFORMA
|
|
|
|
# Dates
|
|
invoice_date: Mapped[datetime] = mapped_column(Date) # FECHAFACTURA
|
|
capture_date: Mapped[datetime] = mapped_column(
|
|
TIMESTAMP(timezone=False), server_default=func.now()
|
|
) # FECHACAPTURA + HORAACTUAL
|
|
emission_date: Mapped[Optional[datetime]] = mapped_column(Date) # FECHAEMISION
|
|
|
|
# Status & Control
|
|
is_updated: Mapped[bool] = mapped_column(Boolean) # ESTATUS
|
|
is_updated_rec: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # ESTATUSREC / Estatus de recepción
|
|
is_updated_rep: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # ESTATUSREP / Estatus de reporte
|
|
updated_date: Mapped[Optional[datetime]] = mapped_column(
|
|
TIMESTAMP(timezone=False)
|
|
) # FECHAACTUALIZACION / FECHAACTUAL
|
|
who_updated: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # USUARIOACT / Quien actualizó
|
|
capture_user: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # USUARIOCAP / Usuario que capturó
|
|
|
|
traffic_light_status: Mapped[Optional[str]] = mapped_column(
|
|
String(50)
|
|
) # SEMAFORO / SEMAFOROEXPO/IMPO
|
|
process_log: Mapped[Optional[str]] = mapped_column(String(300)) # COMOFUEPROCESADA
|
|
|
|
# Comments
|
|
observation_es: Mapped[Optional[str]] = mapped_column(
|
|
Text
|
|
) # OBSERVACIONE / Observaciones en español
|
|
observation_en: Mapped[Optional[str]] = mapped_column(
|
|
Text
|
|
) # OBSERVACIONI / Observaciones en inglés
|
|
comments_status: Mapped[Optional[str]] = mapped_column(Text) # COMENTARIOSESTATUS
|
|
vu_observations: Mapped[Optional[str]] = mapped_column(
|
|
String(500)
|
|
) # OBSERVACIONESVU / Observaciones VUCEM
|
|
|
|
# Digital Archive Links
|
|
cfdi_uuid: Mapped[Optional[str]] = mapped_column(String(100)) # CFDIUUID
|
|
path_pdf: Mapped[Optional[str]] = mapped_column(String(500)) # CFDIPATHPDF
|
|
path_xml: Mapped[Optional[str]] = mapped_column(String(500)) # CFDIPATHXML
|
|
|
|
# Control & Subcompany
|
|
subcompany: Mapped[Optional[str]] = mapped_column(String(5)) # SUBEMPRESA
|
|
party_count: Mapped[Optional[int]] = mapped_column(
|
|
Integer
|
|
) # CANT_PARTIDAS / Cantidad de partidas
|
|
|
|
# Generation flags
|
|
generate_id: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # GENERAID
|
|
generate_desc_parties: Mapped[Optional[str]] = mapped_column(
|
|
String(12)
|
|
) # GENDESCPARTIDAS / Generar descripción de partidas
|
|
apply_manual_discount: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # APLICADESCMANUAL
|
|
|
|
# Bulk & Downloads
|
|
is_bulk: Mapped[Optional[bool]] = mapped_column(Boolean) # ESAGRANEL / Es a granel
|
|
download_substance: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # DESCARGASUST / Descarga de sustancia
|
|
download_class: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # DESCARGACLASE / Descarga de clase
|
|
download_def: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # DESCARGADEF / Descarga definitiva
|
|
|
|
# Additional fields
|
|
payment_terms: Mapped[Optional[str]] = mapped_column(
|
|
String(200)
|
|
) # TERMINOSPAGO / Términos de pago
|
|
handling_fees: Mapped[Optional[float]] = mapped_column(Numeric(19, 8)) # MANIOBRAS
|
|
option_iv18: Mapped[Optional[str]] = mapped_column(String(50)) # OPCIONIV18
|
|
enajenation_goods: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # ENAJENACIONBIENES / Enajenación de bienes
|
|
|
|
# Relationships
|
|
compliance_mx: Mapped[Optional["InvoiceComplianceMx"]] = relationship(
|
|
back_populates="header", cascade="all, delete-orphan", uselist=False
|
|
)
|
|
financials: Mapped[Optional["InvoiceFinancials"]] = relationship(
|
|
back_populates="header", cascade="all, delete-orphan", uselist=False
|
|
)
|
|
details: Mapped[List["InvoiceSalesDetails"]] = relationship(
|
|
back_populates="header", cascade="all, delete-orphan"
|
|
)
|
|
collections: Mapped[List["InvoiceCollections"]] = relationship(
|
|
back_populates="header", cascade="all, delete-orphan"
|
|
)
|
|
logistics: Mapped[Optional["InvoiceLogistics"]] = relationship(
|
|
back_populates="header", cascade="all, delete-orphan", uselist=False
|
|
)
|
|
|
|
|
|
# --- 2. Compliance MX (invoice_compliance_mx) ---
|
|
class InvoiceComplianceMx(Base, TenantScopedMixin, TimestampMixin):
|
|
__tablename__ = "invoice_compliance_mx"
|
|
__table_args__ = ({"schema": "a76"},)
|
|
|
|
invoice_id: Mapped[int] = mapped_column(
|
|
ForeignKey("a76.invoice_header.id"), primary_key=True
|
|
)
|
|
|
|
# Core Customs Data
|
|
pedimento_id: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.pedimentos.id")
|
|
) # PEDIMENTO/PEDIMENTOIMPO/EXPO
|
|
pedimento_r1: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.pedimentos.id")
|
|
) # PEDIMENTOR1
|
|
pedimento_k1: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.pedimentos.id")
|
|
) # PEDIMENTOK1
|
|
remesa: Mapped[Optional[int]] = mapped_column(Integer) # REMESA
|
|
aduana: Mapped[Optional[str]] = mapped_column(
|
|
ForeignKey("public.customs_sections.customs_code")
|
|
) # ADUANA_CRUCE
|
|
port_of_entry: Mapped[Optional[str]] = mapped_column(
|
|
String(6)
|
|
) # PUERTOENTRADA / Puerto de entrada
|
|
destination: Mapped[Optional[str]] = mapped_column(
|
|
String(3)
|
|
) # DESTINO / Código de destino
|
|
manifest_number: Mapped[Optional[str]] = mapped_column(
|
|
String(15)
|
|
) # MANIFIESTO / Número de manifiesto
|
|
|
|
# Clients & Providers
|
|
provider_header: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # PROVEEDOREXPORTADOR
|
|
provider_id: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.clients_and_providers.id")
|
|
) # PROVEEDOR
|
|
sold_to_header: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # VENDIDOCONSIGNADO
|
|
sold_to_id: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.clients_and_providers.id")
|
|
) # VENDIDOA
|
|
shipped_to_header: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # ENVIADOTRANSFERIDO
|
|
shipped_to_id: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.clients_and_providers.id")
|
|
) # ENVIADOA
|
|
shipped_by_header: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # ENVIADOPORVENDIDOPOR
|
|
shipped_by_id: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.clients_and_providers.id")
|
|
) # VENDIDOPOR/ENVIADOPOR
|
|
customs_broker_id: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.customs_brokers.id")
|
|
) # AADUANAL / Agente aduanal
|
|
customs_broker_us_id: Mapped[Optional[int]] = mapped_column(
|
|
ForeignKey("a76.customs_brokers.id")
|
|
) # AADUANALAME / Agente aduanal americano
|
|
|
|
# Broker Invoice
|
|
broker_invoice_num: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # NUMFACTURABROKER / Número factura broker
|
|
broker_invoice_date: Mapped[Optional[datetime]] = mapped_column(
|
|
Date
|
|
) # FECHAFACBROKER / Fecha factura broker
|
|
|
|
# Flags & Specific Regimes
|
|
is_mixed: Mapped[Optional[bool]] = mapped_column(Boolean) # ESMIXTO / Es mixto
|
|
waste_type: Mapped[Optional[str]] = mapped_column(
|
|
String(1)
|
|
) # TIPODESPERDICIO / Tipo de desperdicio
|
|
scrap_type: Mapped[Optional[str]] = mapped_column(
|
|
String(1)
|
|
) # TIPOSCRAP / Tipo de scrap
|
|
appendix_17: Mapped[Optional[int]] = mapped_column(
|
|
Integer
|
|
) # APENDICE17 / Apéndice 17
|
|
is_regime_change: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # ESCAMBIOREGIMEN / Es cambio de régimen
|
|
which_exchange_rate: Mapped[Optional[str]] = mapped_column(
|
|
String(5)
|
|
) # CUALTIPOCAMBIO / Cuál tipo de cambio
|
|
value_method: Mapped[Optional[str]] = mapped_column(
|
|
String(2)
|
|
) # METVALOR / Método de valoración
|
|
act_value: Mapped[Optional[str]] = mapped_column(
|
|
String(5)
|
|
) # ACTVALOR / Actualizar valor
|
|
rule_3121_parties_ii: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # REGLA3121PARTESII / Regla 3.1.21 Partes II
|
|
is_pedimento_pending: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # PED_PENDIENTE_ASIGNAR (Mapear 1 -> True, 0 -> False)
|
|
|
|
# Ownership & Balances
|
|
is_owner_of_goods: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # ESDUENOMCIA / Es dueño de mercancía
|
|
generate_balances: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # GENERARSALDOS / Generar saldos
|
|
was_reviewed_by_company: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # FUEREVISADAMCIA / Fue revisada por la compañía
|
|
|
|
# VUCEM / Digital
|
|
edocument: Mapped[Optional[str]] = mapped_column(
|
|
String(50)
|
|
) # EDOCUMENT / Documento electrónico
|
|
electronic_signature: Mapped[Optional[str]] = mapped_column(
|
|
String(999)
|
|
) # FIRMAELECTRONICA / Firma electrónica
|
|
certificate_number: Mapped[Optional[str]] = mapped_column(
|
|
String(99)
|
|
) # NUMEROCERTIFICADO / Número de certificado
|
|
niu_number: Mapped[Optional[str]] = mapped_column(
|
|
String(19)
|
|
) # NUMERONIU / Número NIU
|
|
bill_of_lading_count: Mapped[Optional[str]] = mapped_column(
|
|
String(12)
|
|
) # CANTGUIASEMBARQUE / Cantidad guías embarque
|
|
addendum_vu: Mapped[Optional[str]] = mapped_column(
|
|
String(204)
|
|
) # ADENDAVU / Adenda VUCEM
|
|
origin_destination_cove: Mapped[Optional[DestinationOriginCove]] = mapped_column(
|
|
String(20)
|
|
) # DESTINOORIGENCOVE / Destino/Origen COVE
|
|
vucem_operation_num: Mapped[Optional[str]] = mapped_column(
|
|
String(19)
|
|
) # NUMOPERACIONVU / Número operación VUCEM
|
|
customs_person_line: Mapped[Optional[int]] = mapped_column(
|
|
Integer
|
|
) # LINEAPERSONAAA / Línea persona agente aduanal
|
|
|
|
# Additional Control
|
|
contingency_mode: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # MODOCONTINGENCIA / Modo contingencia
|
|
enclosure: Mapped[Optional[str]] = mapped_column(
|
|
String(4)
|
|
) # RECINTO / Recinto fiscal
|
|
guide_type_to_identify: Mapped[Optional[str]] = mapped_column(
|
|
String(1)
|
|
) # TIPODEGUIAAIDENTIFICAR / Tipo de guía a identificar
|
|
location: Mapped[Optional[str]] = mapped_column(
|
|
String(200)
|
|
) # LOCALIZACION / Localización
|
|
|
|
# DOT & Official
|
|
dot_code: Mapped[Optional[str]] = mapped_column(String(20)) # CLAVEDOT / Clave DOT
|
|
subdivision: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # SUBDIVISION / Subdivisión
|
|
acts_as: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # FUNGECOMOCO / Funge como
|
|
movement_type: Mapped[Optional[str]] = mapped_column(
|
|
String(31)
|
|
) # TIPOMOV / Tipo de movimiento
|
|
office_document: Mapped[Optional[str]] = mapped_column(
|
|
String(30)
|
|
) # OFICIO / Oficio
|
|
reason_export: Mapped[Optional[str]] = mapped_column(
|
|
String(1)
|
|
) # RAZONEXPORTACION / Razón de exportación
|
|
signature_key: Mapped[Optional[str]] = mapped_column(
|
|
String(100)
|
|
) # CLAVEFIRMA / Clave de firma
|
|
|
|
# SM specific
|
|
sem_id: Mapped[Optional[int]] = mapped_column(
|
|
Integer
|
|
) # SEM / ID SEM (de SFacEntradaSM/SFacSalidaSM)
|
|
|
|
# Relationships
|
|
header: Mapped["InvoiceHeader"] = relationship(back_populates="compliance_mx")
|
|
pedimento: Mapped[Optional["Pedimentos"]] = relationship(
|
|
foreign_keys=[pedimento_id], lazy="joined"
|
|
)
|
|
|
|
|
|
# --- 3. Financials (invoice_financials) ---
|
|
class InvoiceFinancials(Base, TenantScopedMixin, TimestampMixin):
|
|
__tablename__ = "invoice_financials"
|
|
__table_args__ = ({"schema": "a76"},)
|
|
|
|
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
|
|
invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id"))
|
|
|
|
# Currency
|
|
currency: Mapped[Currency] = mapped_column(
|
|
String(7)
|
|
) # CLAVEMONEDA / Clave de moneda
|
|
currency_type: Mapped[Optional[str]] = mapped_column(
|
|
ForeignKey("public.currency_types.code")
|
|
) # TIPOMONEDA / TIPOCLAVEMONEDA
|
|
exchange_rate: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(13, 6)
|
|
) # TIPOCAMBIO / Tipo de cambio
|
|
exchange_rate_mm: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(13, 6)
|
|
) # TIPOCAMBIOMM / Tipo de cambio moneda a moneda
|
|
|
|
# Merchandise Values (MN = National Currency, ME = Foreign Currency, MC = Third Currency)
|
|
value_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORIMPOMN/VALOREXPOMN/VALORENTMN/VALORSALMN
|
|
value_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORIMPOME/VALOREXPOME/VALORENTME/VALORSALME
|
|
value_mc: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORIMPOMC/VALOREXPOMC
|
|
|
|
# Customs Value
|
|
customs_value_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORADUANASMN / Valor en aduanas MN
|
|
customs_value_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORADUANASME / Valor en aduanas ME
|
|
|
|
# Raw Materials
|
|
raw_material_value_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORMPMN / Valor materia prima MN
|
|
raw_material_value_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORMPME / Valor materia prima ME
|
|
|
|
# Aggregate Value
|
|
aggregate_value_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORAGREMN / Valor agregado MN
|
|
aggregate_value_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORAGREME / Valor agregado ME
|
|
aggregate_value_mc: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORAGREMC / Valor agregado MC
|
|
|
|
# Mexican Merchandise Value
|
|
mexican_value_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORVMEXMN / Valor mercancía mexicana MN
|
|
mexican_value_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORVMEXME / Valor mercancía mexicana ME
|
|
mexican_value_mc: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORVMEXMC / Valor mercancía mexicana MC
|
|
|
|
# National Packaging
|
|
national_packaging_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALEMPAQUENACMN / Valor empaque nacional MN
|
|
national_packaging_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALEMPAQUENACME / Valor empaque nacional ME
|
|
national_packaging_mc: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALEMPAQUENACMC / Valor empaque nacional MC
|
|
|
|
# Costs & Increments
|
|
freight: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8), default=0, server_default="0"
|
|
) # FLETE / Flete
|
|
insurance: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8), default=0, server_default="0"
|
|
) # SEGUROS / Seguros
|
|
insurance_value: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8), default=0, server_default="0"
|
|
) # VALSEGUROS / Valor seguros
|
|
packaging: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8), default=0, server_default="0"
|
|
) # EMBALAJES / Embalajes
|
|
other_increments: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8), default=0, server_default="0"
|
|
) # OTROSINCREMENTA / Otros incrementables
|
|
other_deductibles: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8), default=0, server_default="0"
|
|
) # OTROSDEDUCIBLES / Otros deducibles
|
|
total_increments_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # TOTALINCREMMN / Total incrementables MN
|
|
total_increments_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # TOTALINCREMME / Total incrementables ME
|
|
|
|
# Taxes
|
|
iva_mn: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # IVAEXPOMN/VALORIVAMN / IVA en MN
|
|
iva_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # IVAEXPOME/VALORIVAME / IVA en ME
|
|
iva_mc: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # IVAEXPOMC / IVA en MC
|
|
iva_factor: Mapped[Optional[str]] = mapped_column(
|
|
String(10)
|
|
) # FACTORIVA / Factor IVA (puede ser varchar en imports)
|
|
tax_value_me: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(23, 8), default=0, server_default="0"
|
|
) # VALORIMPUESTOME / Valor impuesto ME
|
|
seal_value_2500: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean
|
|
) # SELLOVALOR2500 / Sello valor 2500
|
|
|
|
# Weights & Quantities
|
|
total_quantity: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8)
|
|
) # CANTEXPO/CANTIMPO / Cantidad total
|
|
gross_weight: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8)
|
|
) # PESOBRUTO / Peso bruto
|
|
net_weight: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8)
|
|
) # PESONETO / Peso neto
|
|
bundle_count: Mapped[Optional[int]] = mapped_column(
|
|
Integer
|
|
) # CANTBULTOS / Cantidad de bultos
|
|
weight_factor: Mapped[Optional[float]] = mapped_column(
|
|
Numeric(19, 8)
|
|
) # FACTORPESO / Factor de peso
|
|
|
|
# Relationship
|
|
header: Mapped["InvoiceHeader"] = relationship(back_populates="financials")
|
|
|
|
|
|
# --- 4. Logistics (invoice_logistics) ---
|
|
class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin):
|
|
__tablename__ = "invoice_logistics"
|
|
__table_args__ = ({"schema": "a76"},)
|
|
|
|
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
|
|
invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id"))
|
|
|
|
# Carrier Info
|
|
carrier_id: Mapped[Optional[str]] = mapped_column(
|
|
String(10)
|
|
) # TRANSPORTISTA / Transportista
|
|
transport_id: Mapped[Optional[str]] = mapped_column(
|
|
String(10)
|
|
) # NUMTRAILER / Transportista
|
|
transport_us_id: Mapped[Optional[str]] = mapped_column(
|
|
String(10)
|
|
) # TRANSPORTISTAAME / Transportista americano
|
|
transport_type: Mapped[TransportType] = mapped_column(
|
|
String(15), server_default="none"
|
|
) # TRANSPORTE / Tipo de transporte
|
|
transport_num: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # NUMTRASPORTE / Número de transporte
|
|
transport_mode: Mapped[Optional[str]] = mapped_column(
|
|
String(15)
|
|
) # MODTRANS / Modo de transporte
|
|
driver_name: Mapped[Optional[str]] = mapped_column(
|
|
String(80)
|
|
) # CONDUCTOR / Nombre del conductor
|
|
is_rail: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # ESFERROCARRIL / Es ferrocarril
|
|
rail_id: Mapped[Optional[str]] = mapped_column(
|
|
String(31)
|
|
) # IDFERRORCARRIL / ID ferrocarril
|
|
|
|
# Vehicle & Tracking
|
|
vehicle_num: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # NUMVEHICULO / Número de vehículo
|
|
license_plate: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # NUMTRASPORTE / Número de transporte/placa
|
|
license_plate_complete: Mapped[Optional[str]] = mapped_column(
|
|
String(40)
|
|
) # NUMTRASPORTECOMPLE / Número transporte completo
|
|
trailer_num: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # NUMTRAILER / Número de trailer
|
|
seal_number: Mapped[Optional[str]] = mapped_column(
|
|
String(15)
|
|
) # PRECINTO / Precinto
|
|
guide_number: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # NUMEROGUIA / Número de guía
|
|
bill_number: Mapped[Optional[str]] = mapped_column(
|
|
String(15)
|
|
) # BILLNUMBER / Número de bill
|
|
reference_number: Mapped[Optional[str]] = mapped_column(
|
|
String(14)
|
|
) # NUMREFERENCIA / Número de referencia
|
|
shipment_number: Mapped[Optional[str]] = mapped_column(
|
|
String(19)
|
|
) # NUMEMBARQUE / Número de embarque
|
|
|
|
# Incoterms
|
|
incoterm: Mapped[Optional[str]] = mapped_column(
|
|
String(5)
|
|
) # INCOTERM / Término de comercio internacional
|
|
|
|
# Identifiers & Complements
|
|
identifier_1: Mapped[Optional[str]] = mapped_column(
|
|
String(2)
|
|
) # IDENTIFICADOR / Identificador 1
|
|
complement_1: Mapped[Optional[str]] = mapped_column(
|
|
String(30)
|
|
) # COMPLEMENTO1 / Complemento 1
|
|
identifier_2: Mapped[Optional[str]] = mapped_column(
|
|
String(2)
|
|
) # IDENTIFICADOR2 / Identificador 2
|
|
complement_2: Mapped[Optional[str]] = mapped_column(
|
|
String(30)
|
|
) # COMPLEMENTO2 / Complemento 2
|
|
|
|
# Weight & Container Info
|
|
weight_type: Mapped[WeightUnit] = mapped_column(
|
|
String(3)
|
|
) # TIPOPESO / Tipo de peso
|
|
container_types: Mapped[Optional[str]] = mapped_column(
|
|
String(500)
|
|
) # CONTENEDORESTIPO / Tipos de contenedores
|
|
vehicle_data: Mapped[Optional[str]] = mapped_column(
|
|
String(500)
|
|
) # DATOSVEHICULO / Datos del vehículo
|
|
|
|
# Locations & Routes
|
|
origin_location: Mapped[Optional[str]] = mapped_column(
|
|
String(200)
|
|
) # ORIGENUBICACION / Ubicación de origen
|
|
destination_location: Mapped[Optional[str]] = mapped_column(
|
|
String(200)
|
|
) # DESTINOUBICACION / Ubicación de destino
|
|
transport_itinerary: Mapped[Optional[str]] = mapped_column(
|
|
String(1000)
|
|
) # ITINERARIOTRANPORTE / Itinerario del transporte
|
|
destination_goods: Mapped[Optional[str]] = mapped_column(
|
|
String(50)
|
|
) # DESTINOMCIA / Destino de mercancía
|
|
|
|
# Logistics Dates
|
|
entry_exit_date: Mapped[Optional[datetime]] = mapped_column(
|
|
Date
|
|
) # FECHAENTRADA/FECHAENVIO/FECHARECIBO / Fecha entrada/salida
|
|
delivery_date: Mapped[Optional[datetime]] = mapped_column(
|
|
Date
|
|
) # FECHAENTREGA / Fecha de entrega
|
|
|
|
# Delivery Control
|
|
delivered_status: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # ENTREGADO / Estado de entrega
|
|
received_by: Mapped[Optional[str]] = mapped_column(
|
|
String(50)
|
|
) # RECIBIDOPOR / Recibido por
|
|
|
|
# Payment Info
|
|
payment_date: Mapped[Optional[datetime]] = mapped_column(
|
|
Date
|
|
) # FECHAPAGO / Fecha de pago
|
|
payment_receipt_num: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # NUMRECIBOPAGO / Número de recibo de pago
|
|
|
|
# CTM Process
|
|
is_ctm_process: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False, server_default="false"
|
|
) # SETRATAPROCESOCTM / Se trata de proceso CTM
|
|
|
|
# Continuation Tab Fields
|
|
equipment_reviewed: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Fue revisado el equipo
|
|
is_subdivision: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Sub división
|
|
acts_as_cd: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Funge como CD
|
|
pedimento_arrived: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Llegó el pedimento
|
|
green_light_mx: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Semáforo verde México
|
|
green_light_us: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Semáforo verde USA
|
|
red_light_mx: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Semáforo rojo México
|
|
red_light_us: Mapped[Optional[bool]] = mapped_column(
|
|
Boolean, default=False
|
|
) # Semáforo rojo USA
|
|
|
|
# Relationship
|
|
header: Mapped["InvoiceHeader"] = relationship(back_populates="logistics")
|
|
|
|
|
|
# --- 5. Sales Order Details (invoice_sales_details) ---
|
|
class InvoiceSalesDetails(Base, TenantScopedMixin, TimestampMixin):
|
|
__tablename__ = "invoice_sales_details"
|
|
__table_args__ = ({"schema": "a76"},)
|
|
|
|
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
|
|
invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id"))
|
|
|
|
line_number: Mapped[int] = mapped_column(Integer) # LINEA / Número de línea
|
|
sales_order: Mapped[Optional[str]] = mapped_column(
|
|
String(20)
|
|
) # ORDENVENTA / Orden de venta
|
|
|
|
# Specific Custom Fields
|
|
colors_description: Mapped[Optional[str]] = mapped_column(
|
|
String(49)
|
|
) # COLORES / Descripción de colores
|
|
square_color_code: Mapped[Optional[str]] = mapped_column(
|
|
String(1)
|
|
) # COLORCUADRITO / Código de color cuadrito
|
|
line_bundles: Mapped[Optional[int]] = mapped_column(
|
|
Integer
|
|
) # CANTBULTOS / Cantidad de bultos de la línea
|
|
|
|
# Relationship
|
|
header: Mapped["InvoiceHeader"] = relationship(back_populates="details")
|
|
|
|
|
|
# --- 6. Collections (invoice_collections) ---
|
|
class InvoiceCollections(Base, TenantScopedMixin, TimestampMixin):
|
|
__tablename__ = "invoice_collections"
|
|
__table_args__ = ({"schema": "a76"},)
|
|
|
|
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
|
|
invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id"))
|
|
|
|
line_number: Mapped[int] = mapped_column(Integer) # LINEA / Número de línea
|
|
invoice_number: Mapped[Optional[str]] = mapped_column(
|
|
String(15)
|
|
) # FACTURA / Número de factura
|
|
concept: Mapped[Optional[str]] = mapped_column(String(100)) # CONCEPTO / Concepto
|
|
|
|
# Relationship
|
|
header: Mapped["InvoiceHeader"] = relationship(back_populates="collections")
|
|
concept: Mapped[Optional[str]] = mapped_column(String(100)) # CONCEPTO / Conce
|