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