From 7c8b972899a4fd09a8a5168d8d7500cde8198866 Mon Sep 17 00:00:00 2001 From: AlexeerCT Date: Fri, 19 Dec 2025 13:48:32 -0600 Subject: [PATCH] feat: enhance invoice models with additional fields and relationships for improved data handling --- backend/api/v1/modules/a76/invoices/models.py | 388 +++++++++++------- 1 file changed, 245 insertions(+), 143 deletions(-) diff --git a/backend/api/v1/modules/a76/invoices/models.py b/backend/api/v1/modules/a76/invoices/models.py index 7f787def..c005f38d 100644 --- a/backend/api/v1/modules/a76/invoices/models.py +++ b/backend/api/v1/modules/a76/invoices/models.py @@ -10,74 +10,97 @@ from ....common.base_models import TenantScopedMixin, TimestampMixin 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" # Ninguno - TRANSPORT = "transport" # Transporte - BOX = "box" # Caja - PLATES = "licence plates" # Placas - TRUCK = "truck" # Camión - VESSEL = "vessel" # Buque - BARGE = "rail barge" # Ferrobarcaza - CONTAINER = "container" # Contenedor - AIRPLANE = "airplane" # Avión - GONDOLA = "gondola" # Góndola - FLATBED = "flatbed" # Plataforma + 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"}, - ) + __table_args__ = ({"schema": "a76"},) - id: Mapped[int] = mapped_column( - BigInteger, primary_key=True, autoincrement=True) + id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) # Identifiers - operation_type: Mapped[OperationType] = mapped_column( - String(3)) # TIPOMOVIMIENTO / Clasifica imp/exp - invoice_type: Mapped[Optional[str]] = mapped_column(ForeignKey( - "public.invoice_types.key")) # TIPOFACTURA (invoice_types) - invoice_number: Mapped[Optional[str]] = mapped_column( - String(20)) # FACTURAIMPO/FACTURAEXPO/FACTURAREMISION - 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) + operation_type: Mapped[OperationType] = mapped_column(String(10)) # TIPOMOVIMIENTO / Clasifica imp/exp/sm/ctm + invoice_type: Mapped[Optional[str]] = mapped_column(ForeignKey("public.invoice_types.key")) # TIPOFACTURA / TIPODOC + invoice_number: Mapped[Optional[str]] = mapped_column(String(20)) # 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[Optional[datetime] - ] = mapped_column(Date) # FECHAFACTURA - capture_date: Mapped[datetime] = mapped_column( - TIMESTAMP(timezone=False), default=datetime.now) # FECHACAPTURA + HORAACTUAL + invoice_date: Mapped[Optional[datetime]] = mapped_column(Date) # FECHAFACTURA + capture_date: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=False), default=datetime.now) # FECHACAPTURA + HORAACTUAL + emission_date: Mapped[Optional[datetime]] = mapped_column(Date) # FECHAEMISION # Status & Control - is_updated: Mapped[Optional[str]] = mapped_column(Boolean) # ESTATUS - updated_date: Mapped[Optional[datetime]] = mapped_column(TIMESTAMP(timezone=False)) # FECHAACTUALIZACION - who_updated: Mapped[Optional[str]] = mapped_column(String(20)) # QUIENA ACTUALIZO - + is_updated: Mapped[Optional[bool]] = mapped_column(Boolean) # ESTATUS + 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 + status_rec: Mapped[Optional[int]] = mapped_column(Integer) # ESTATUSREC / Estatus de recepción + status_rep: Mapped[Optional[str]] = mapped_column(String(2)) # ESTATUSREP / Estatus de reporte - # Comments - observation_es: Mapped[Optional[str]] = mapped_column(Text) #OBSERVACIONE - observation_en: Mapped[Optional[str]] = mapped_column(Text) #OBSERVACIONI - comments_status: Mapped[Optional[str]] = mapped_column(Text) #COMENTARIOSESTATUS + # 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 - # Relationships (Para navegacion ORM) - compliance_mx: Mapped["InvoiceComplianceMx"] = relationship( - back_populates="header", cascade="all, delete-orphan") - financials: Mapped["InvoiceFinancials"] = relationship( - back_populates="header", cascade="all, delete-orphan") + # 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[str]] = mapped_column(String(1)) # GENERAID + generate_desc_parties: Mapped[Optional[str]] = mapped_column(String(12)) # GENDESCPARTIDAS / Generar descripción de partidas + apply_manual_discount: Mapped[Optional[str]] = mapped_column(String(1)) # 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( @@ -89,79 +112,149 @@ class InvoiceHeader(Base, TenantScopedMixin, TimestampMixin): # --- 2. Compliance MX (invoice_compliance_mx) --- class InvoiceComplianceMx(Base, TenantScopedMixin, TimestampMixin): __tablename__ = "invoice_compliance_mx" - __table_args__ = ( - {"schema": "a76"}, - ) + __table_args__ = ({"schema": "a76"},) - invoice_id: Mapped[int] = mapped_column( - ForeignKey("a76.invoice_header.id"), primary_key=True) + invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id"), primary_key=True) # Core Customs Data - pedimento: Mapped[Optional[str]] = mapped_column( - String(19)) # PEDIMENTO/PEDIMENTOIMPO/EXPO - pedimento_code: Mapped[Optional[str]] = mapped_column( - String(5)) # PEDIMENTOR1, K1 - remesa: Mapped[Optional[int]] = mapped_column(Integer) + pedimento: Mapped[Optional[str]] = mapped_column(String(19)) # PEDIMENTO/PEDIMENTOIMPO/EXPO + pedimento_code: Mapped[Optional[str]] = mapped_column(String(5)) # PEDIMENTOR1 + pedimento_k1: Mapped[Optional[str]] = mapped_column(String(15)) # 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_header: Mapped[Optional[str]] = mapped_column(String(20)) # PROVEEDOREXPORTADOR provider_id: Mapped[Optional[str]] = 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[str]] = 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[str]] = mapped_column(ForeignKey("a76.clients_and_providers.id")) # ENVIADOA + shipped_to_id: Mapped[Optional[str]] = 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[str]] = mapped_column(ForeignKey("a76.clients_and_providers.id")) # VENDIDOPOR + shipped_by_id: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.clients_and_providers.id")) # VENDIDOPOR/ENVIADOPOR + customs_broker_id: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.customs_brokers.id")) # AADUANAL / Agente aduanal + customs_broker_us_id: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.customs_brokers.id")) # AADUANALAME / Agente aduanal americano - customs_broker_id: Mapped[Optional[str]] = mapped_column(ForeignKey("a76.customs_brokers.id")) # AADUANAL + # 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 - waste_type: Mapped[Optional[str]] = mapped_column(String(1)) # TIPODESPERDICIO - appendix_17: Mapped[Optional[int]] = mapped_column(Integer) # APENDICE17 + 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[str]] = mapped_column(String(1)) # 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 + + # Ownership & Balances + is_owner_of_goods: Mapped[Optional[str]] = mapped_column(String(2)) # ESDUENOMCIA / Es dueño de mercancía + generate_balances: Mapped[Optional[str]] = mapped_column(String(2)) # 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 - electronic_signature: Mapped[Optional[str]] = mapped_column(String(999)) # FIRMAELECTRONICA - sem_id: Mapped[Optional[int]] = mapped_column(Integer) # SEM (de SFacEntradaSM/SFacSalidaSM) + 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[str]] = mapped_column(String(19)) # 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(10)) # CLAVEFIRMA / Clave de firma + + # SM specific + sem_id: Mapped[Optional[int]] = mapped_column(Integer) # SEM / ID SEM (de SFacEntradaSM/SFacSalidaSM) # Relationship - header: Mapped["InvoiceHeader"] = relationship( - back_populates="compliance_mx") + header: Mapped["InvoiceHeader"] = relationship(back_populates="compliance_mx") # --- 3. Financials (invoice_financials) --- class InvoiceFinancials(Base, TenantScopedMixin, TimestampMixin): __tablename__ = "invoice_financials" - __table_args__ = ( - {"schema": "a76"}, - ) + __table_args__ = ({"schema": "a76"},) - id: Mapped[int] = mapped_column( - BigInteger, primary_key=True, autoincrement=True) + id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id")) - currency: Mapped[Optional[str]] = mapped_column(String(3)) # CLAVEMONEDA - currency_type: Mapped[Optional[str]] = mapped_column(ForeignKey("public.currency_types.code")) # TIPOCLAVEMONEDA - exchange_rate: Mapped[Optional[float]] = mapped_column(Numeric(13, 6)) # TIPOCAMBIO + # Currency + currency: Mapped[Optional[str]] = mapped_column(String(3)) # 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 - value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORIMPOMN/EXPOMN - value_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) - customs_value_mn: Mapped[Optional[float]] = mapped_column( Numeric(23, 8), default=0) # VALORADUANASMN + # Merchandise Values (MN = National Currency, ME = Foreign Currency, MC = Third Currency) + value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORIMPOMN/VALOREXPOMN/VALORENTMN/VALORSALMN + value_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORIMPOME/VALOREXPOME/VALORENTME/VALORSALME + value_mc: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORIMPOMC/VALOREXPOMC + + # Customs Value + customs_value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORADUANASMN / Valor en aduanas MN + customs_value_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORADUANASME / Valor en aduanas ME - # Costs & Taxes - freight: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # FLETE - insurance: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # VALSEGUROS/SEGUROS - iva_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # IVAEXPOMN / VALORIVAMN - iva_factor: Mapped[Optional[float]] = mapped_column(Numeric(17, 4)) # FACTORIVA + # Raw Materials + raw_material_value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORMPMN / Valor materia prima MN + raw_material_value_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORMPME / Valor materia prima ME + + # Aggregate Value + aggregate_value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORAGREMN / Valor agregado MN + aggregate_value_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORAGREME / Valor agregado ME + aggregate_value_mc: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORAGREMC / Valor agregado MC + + # Mexican Merchandise Value + mexican_value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORVMEXMN / Valor mercancía mexicana MN + mexican_value_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORVMEXME / Valor mercancía mexicana ME + mexican_value_mc: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORVMEXMC / Valor mercancía mexicana MC + + # National Packaging + national_packaging_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALEMPAQUENACMN / Valor empaque nacional MN + national_packaging_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALEMPAQUENACME / Valor empaque nacional ME + national_packaging_mc: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALEMPAQUENACMC / Valor empaque nacional MC + + # Costs & Increments + freight: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # FLETE / Flete + insurance: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # SEGUROS / Seguros + insurance_value: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # VALSEGUROS / Valor seguros + packaging: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # EMBALAJES / Embalajes + other_increments: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # OTROSINCREMENTA / Otros incrementables + total_increments_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # TOTALINCREMMN / Total incrementables MN + total_increments_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # TOTALINCREMME / Total incrementables ME + + # Taxes + iva_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # IVAEXPOMN/VALORIVAMN / IVA en MN + iva_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # IVAEXPOME/VALORIVAME / IVA en ME + iva_mc: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), 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) # 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 - gross_weight: Mapped[Optional[float]] = mapped_column(Numeric(19, 8)) # PESOBRUTO - net_weight: Mapped[Optional[float]] = mapped_column(Numeric(19, 8)) # PESONETO - bundle_count: Mapped[Optional[int]] = mapped_column(Integer) # CANTBULTOS + 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") @@ -170,38 +263,65 @@ class InvoiceFinancials(Base, TenantScopedMixin, TimestampMixin): # --- 4. Logistics (invoice_logistics) --- class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin): __tablename__ = "invoice_logistics" - __table_args__ = ( - {"schema": "a76"}, - ) + __table_args__ = ({"schema": "a76"},) - id: Mapped[int] = mapped_column( - BigInteger, primary_key=True, autoincrement=True) + 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 - transport_type: Mapped[TransportType] = mapped_column( - String(15), default="none") # TRANSPORTE - transport_mode: Mapped[Optional[str]] = mapped_column( - String(15)) # MODTRANS - driver_name: Mapped[Optional[str]] = mapped_column(String(80)) # CONDUCTOR - is_rail: Mapped[Optional[str]] = mapped_column(String(2)) # ESFERROCARRIL - rail_id: Mapped[Optional[str]] = mapped_column( - String(31)) # IDFERRORCARRIL + carrier_id: Mapped[Optional[str]] = mapped_column(String(10)) # TRANSPORTISTA / Transportista + carrier_us_id: Mapped[Optional[str]] = mapped_column(String(10)) # TRANSPORTISTAAME / Transportista americano + transport_type: Mapped[TransportType] = mapped_column(String(15), default="none") # TRANSPORTE / Tipo 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[str]] = mapped_column(String(2)) # 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 / NUMTRAILER - license_plate: Mapped[Optional[str]] = mapped_column( - String(20)) # NUMTRASPORTE - seal_number: Mapped[Optional[str]] = mapped_column(String(15)) # PRECINTO - guide_number: Mapped[Optional[str]] = mapped_column( - String(20)) # NUMEROGUIA + 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[Optional[str]] = mapped_column(String(6)) # 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 + 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[str]] = mapped_column(String(2)) # 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[str]] = mapped_column(String(2)) # SETRATAPROCESOCTM / Se trata de proceso CTM # Relationship header: Mapped["InvoiceHeader"] = relationship(back_populates="logistics") @@ -210,25 +330,18 @@ class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin): # --- 5. Sales Order Details (invoice_sales_details) --- class InvoiceSalesDetails(Base, TenantScopedMixin, TimestampMixin): __tablename__ = "invoice_sales_details" - __table_args__ = ( - {"schema": "a76"}, - ) + __table_args__ = ({"schema": "a76"},) - id: Mapped[int] = mapped_column( - BigInteger, primary_key=True, autoincrement=True) + 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 - sales_order: Mapped[Optional[str]] = mapped_column( - String(20)) # ORDENVENTA + 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 - square_color_code: Mapped[Optional[str]] = mapped_column( - String(1)) # COLORCUADRITO - line_bundles: Mapped[Optional[int]] = mapped_column( - Integer) # CANTBULTOS (de la linea) + 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") @@ -237,23 +350,12 @@ class InvoiceSalesDetails(Base, TenantScopedMixin, TimestampMixin): # --- 6. Collections (invoice_collections) --- class InvoiceCollections(Base, TenantScopedMixin, TimestampMixin): __tablename__ = "invoice_collections" - __table_args__ = ( - {"schema": "a76"}, - ) + __table_args__ = ({"schema": "a76"},) - id: Mapped[int] = mapped_column( - BigInteger, primary_key=True, autoincrement=True) + id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) invoice_id: Mapped[int] = mapped_column(ForeignKey("a76.invoice_header.id")) - concept: Mapped[Optional[str]] = mapped_column(String(100)) # CONCEPTO - is_collected: Mapped[Optional[int]] = mapped_column(Integer) # COBRADO - collection_date: Mapped[Optional[datetime] - ] = mapped_column(Date) # FECHACOBRANZA - amount: Mapped[Optional[float]] = mapped_column(Numeric(23, 8)) # VALOR - - collector_user: Mapped[Optional[str]] = mapped_column( - String(20)) # FACTCOBRADOR - - # Relationship - header: Mapped["InvoiceHeader"] = relationship( - back_populates="collections") + 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 / Conce \ No newline at end of file