From 376ff23b3eaf093dcc4022639c88088a7eb2b76f Mon Sep 17 00:00:00 2001 From: Jose Antonio Medina Date: Thu, 26 Mar 2026 17:57:20 -0600 Subject: [PATCH] Added lading support --- ...jemplos-factura-carta-porte-referencias.py | 3399 ++++++++++++++++ .../ejemplos-factura-carta-porte-valores.py | 3624 +++++++++++++++++ fiscalapi/__init__.py | 45 + fiscalapi/models/__init__.py | 44 + fiscalapi/models/bill_of_lading_models.py | 306 ++ fiscalapi/models/fiscalapi_models.py | 9 +- setup.py | 2 +- 7 files changed, 7421 insertions(+), 8 deletions(-) create mode 100644 examples/ejemplos-factura-carta-porte-referencias.py create mode 100644 examples/ejemplos-factura-carta-porte-valores.py create mode 100644 fiscalapi/models/bill_of_lading_models.py diff --git a/examples/ejemplos-factura-carta-porte-referencias.py b/examples/ejemplos-factura-carta-porte-referencias.py new file mode 100644 index 0000000..cf9377f --- /dev/null +++ b/examples/ejemplos-factura-carta-porte-referencias.py @@ -0,0 +1,3399 @@ +# ============================================================================ +# CONFIGURACION +# ============================================================================ + +from datetime import datetime +from decimal import Decimal + +# Configuracion del cliente +from fiscalapi.models.common_models import FiscalApiSettings +from fiscalapi.services.fiscalapi_client import FiscalApiClient +from fiscalapi.models.fiscalapi_models import ( + Invoice, + InvoiceComplement, + InvoiceIssuer, + InvoiceRecipient, + InvoiceItem, + ItemTax, +) +from fiscalapi.models.bill_of_lading_models import ( + LadingComplement, + Ubicacion, + Domicilio, + Mercancia, + CantidadTransporta, + Autotransporte, + Remolque, + TipoFigura, + RegimenAduanero, + DocumentoAduanero, + TransporteFerroviario, + DerechoDePaso, + Carro, + TransporteAereo, + ParteTransporte, + TransporteMaritimo, + ContenedorMaritimo, + RemolqueCCP, + DetalleMercancia, +) + + +settings = FiscalApiSettings( + # api_url="https://test.fiscalapi.com", + # api_key="", + # tenant="" +) + +client = FiscalApiClient(settings=settings) + + + + +# Helper: standard autotransporte with one remolque +def _autotransporte(): + return Autotransporte( + perm_sct_id="TPAF01", + num_permiso_sct="NumPermisoSCT1", + config_vehicular_id="VL", + peso_bruto_vehicular=Decimal("1"), + placa_vm="plac892", + anio_modelo_vm=2020, + asegura_resp_civil="AseguraRespCivil", + poliza_resp_civil="123456789", + remolques=[Remolque(sub_tipo_rem_id="CTR004", placa="VL45K98")], + ) + + +# Helper: standard mercancia (sin documentacion aduanera) +def _mercancia_base(cantidad_transporta=None, documentacion_aduanera=None, tipo_materia_id=None, descripcion_materia=None): + return Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + fraccion_arancelaria_id="6309000100", + tipo_materia_id=tipo_materia_id, + descripcion_materia=descripcion_materia, + documentacion_aduanera=documentacion_aduanera, + cantidad_transporta=cantidad_transporta or [ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + ) + + +# ============================================================================ +# 1. FACTURA INGRESO AUTOTRANSPORTE NACIONAL (sin impuestos) +# ============================================================================ +def create_factura_autotransporte_nacional(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[_mercancia_base()], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="URE180429TM6", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="NumeroExterior1", + numero_interior="NumeroInterior1", + colonia_id="Colonia1", + localidad_id="Localidad1", + referencia="Referencia1", + municipio_id="Municipio1", + estado_id="Estado1", + pais_id="AFG", + codigo_postal_id="CodigoPosta1", + ), + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# 2. FACTURA INGRESO AUTOTRANSPORTE NACIONAL CON IMPUESTOS +# ============================================================================ +def create_factura_autotransporte_nacional_con_impuestos(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("26232.75"), + discount=Decimal("0"), + tax_object_code="02", + item_taxes=[ + ItemTax(tax_code="002", tax_type_code="Tasa", tax_rate=Decimal("0.160000"), tax_flag_code="T"), + ItemTax(tax_code="002", tax_type_code="Tasa", tax_rate=Decimal("0.040000"), tax_flag_code="R"), + ], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[_mercancia_base()], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="URE180429TM6", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="NumeroExterior1", + numero_interior="NumeroInterior1", + colonia_id="Colonia1", + localidad_id="Localidad1", + referencia="Referencia1", + municipio_id="Municipio1", + estado_id="Estado1", + pais_id="AFG", + codigo_postal_id="CodigoPosta1", + ), + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# 3. FACTURA INGRESO AUTOTRANSPORTE EXTRANJERO (salida) +# ============================================================================ +def create_factura_autotransporte_extranjero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + _mercancia_base(tipo_materia_id="05", descripcion_materia="otramateria") + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# 4. FACTURA INGRESO AUTOTRANSPORTE INTERNACIONAL ADUANERO (entrada) +# ============================================================================ +def create_factura_autotransporte_internacional_aduanero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + _mercancia_base( + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS FERROVIARIO +# ============================================================================ +def _transporte_ferroviario() -> TransporteFerroviario: + return TransporteFerroviario( + tipo_de_servicio_id="TS01", + tipo_de_trafico_id="TT01", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + derechos_de_paso=[ + DerechoDePaso( + tipo_derecho_de_paso_id="CDP114", + kilometraje_pagado=Decimal("100"), + ) + ], + carros=[ + Carro( + tipo_carro_id="TC08", + matricula_carro="A00012", + guia_carro="123ASD", + toneladas_netas_carro=Decimal("10"), + ) + ], + ) + + +def _figura_ferroviario() -> TipoFigura: + return TipoFigura( + tipo_figura_id="02", + rfc_figura="EKU9003173C9", + nombre_figura="NombreFigura", + partes_transporte=[ParteTransporte(parte_transporte_id="PT02")], + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ) + + +# ============================================================================ +# EJEMPLO 5: TRANSPORTE FERROVIARIO NACIONAL +# ============================================================================ +def create_factura_ferroviario_nacional(): + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("500"), + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T11:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97001", + nombre_estacion="MONTERREY", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97002", + nombre_estacion="GUADALAJARA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T13:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97003", + nombre_estacion="QUERETARO", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T14:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97004", + nombre_estacion="TOLUCA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T15:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + ], + mercancias=[ + _mercancia_base( + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + documentacion_aduanera=None, + tipo_materia_id=None, + descripcion_materia=None, + ) + ], + transporte_ferroviario=_transporte_ferroviario(), + tipos_figura=[_figura_ferroviario()], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura ferroviario nacional creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 6: TRANSPORTE FERROVIARIO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_ferroviario_extranjero(): + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T11:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97001", + nombre_estacion="MONTERREY", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97002", + nombre_estacion="GUADALAJARA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T13:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97003", + nombre_estacion="QUERETARO", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T14:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97004", + nombre_estacion="TOLUCA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="DESTINATARIO EXTRANJERO", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2024-11-12T15:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="Main Street", + numero_exterior="100", + municipio_id="City", + estado_id="TX", + pais_id="USA", + codigo_postal_id="78500", + ), + ), + ], + mercancias=[ + _mercancia_base( + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + documentacion_aduanera=None, + tipo_materia_id="05", + descripcion_materia="otramateria", + ) + ], + transporte_ferroviario=_transporte_ferroviario(), + tipos_figura=[_figura_ferroviario()], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura ferroviario extranjero (salida) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 7: TRANSPORTE FERROVIARIO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_ferroviario_internacional_aduanero(): + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T11:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97001", + nombre_estacion="MONTERREY", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97002", + nombre_estacion="GUADALAJARA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T13:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97003", + nombre_estacion="QUERETARO", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T14:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97004", + nombre_estacion="TOLUCA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T15:00:00", + distancia_recorrida=Decimal("100"), + nombre_estacion="HUEHUETOCA", + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0203", + localidad_id="01", + referencia="casa blanca", + municipio_id="006", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25900", + ), + ), + ], + mercancias=[ + _mercancia_base( + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + documentacion_aduanera=[ + DocumentoAduanero( + tipo_doc_aduanero_id="01", + num_pedimento_aduanero="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + tipo_materia_id="05", + descripcion_materia="otramateria", + ) + ], + transporte_ferroviario=_transporte_ferroviario(), + tipos_figura=[_figura_ferroviario()], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura ferroviario intl aduanero (entrada) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 8: TRANSPORTE AÉREO NACIONAL +# ============================================================================ +def create_factura_aereo_nacional(): + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + tipo_estacion_id="02", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + tipo_estacion_id="02", + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("100"), + clave_unidad_id="H87", + peso_en_kg=Decimal("10"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura aéreo nacional creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# HELPERS MARITIMO +# ============================================================================ +def _transporte_maritimo_base() -> TransporteMaritimo: + return TransporteMaritimo( + perm_sct_id="TPAF01", + num_permiso_sct="NumPermisoSCT1", + nombre_aseg="NombreAseg1", + num_poliza_seguro="NumPolizaSeguro1", + tipo_embarcacion_id="B01", + matricula="Matricula1", + numero_omi="IMO1234567", + anio_embarcacion=2003, + nombre_embarc="NombreEmbarc1", + nacionalidad_embarc_id="AFG", + unidades_de_arq_bruto=Decimal("0.001"), + tipo_carga_id="CGS", + eslora=Decimal("0.01"), + manga=Decimal("0.01"), + calado=Decimal("0.01"), + puntal=Decimal("0.01"), + linea_naviera="LineaNaviera1", + nombre_agente_naviero="NombreAgenteNaviero1", + num_autorizacion_naviero_id="ANC001/2022", + num_viaje="NumViaje1", + num_conoc_embarc="NumConocEmbarc1", + permiso_temp_navegacion="PermisoTempNavegac1", + contenedores=[ + ContenedorMaritimo( + tipo_contenedor_id="CM011", + id_ccp_relacionado="CCCBCD94-870A-4332-A52A-A52AA52AA52A", + placa_vm_ccp="JNG7683", + fecha_certificacion_ccp="2024-06-20T11:11:00", + remolques_ccp=[ + RemolqueCCP( + sub_tipo_rem_ccp_id="CTR001", + placa_ccp="JNG7636", + ) + ], + ) + ], + ) + + +# ============================================================================ +# EJEMPLO 9: TRANSPORTE AÉREO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_aereo_extranjero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="EA0143", + nombre_estacion="Phoenix-Mesa Gateway", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12344", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura aéreo extranjero (salida) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 10: TRANSPORTE AÉREO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_aereo_internacional_aduanero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura aéreo intl aduanero (entrada) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 11: TRANSPORTE MARÍTIMO NACIONAL +# ============================================================================ +def create_factura_maritimo_nacional(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="Tu", + peso_bruto=Decimal("1"), + peso_neto=Decimal("1"), + peso_tara=Decimal("0.001"), + num_piezas=1, + ), + ) + ], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura marítimo nacional creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 12: TRANSPORTE MARÍTIMO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_maritimo_extranjero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="02", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="PM120", + nombre_estacion="NombreEstacion", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12345", + colonia_id="N/A", + referencia="N/A", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="Tu", + peso_bruto=Decimal("1"), + peso_neto=Decimal("1"), + peso_tara=Decimal("0.001"), + num_piezas=1, + ), + ) + ], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura marítimo extranjero (salida) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 13: TRANSPORTE MARÍTIMO INTERNACIONAL ADUANERO (ENTRADA) - INGRESO +# ============================================================================ +def create_factura_maritimo_internacional_aduanero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="CP3.1", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="01", + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[ + RegimenAduanero(regimen_aduanero_id="IMD"), + RegimenAduanero(regimen_aduanero_id="IMD"), + ], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T04:00:01", + tipo_estacion_id="02", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1.50"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + fraccion_arancelaria_id="6309000100", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + cves_transporte_id="02", + ) + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="X1A", + peso_bruto=Decimal("1.50"), + peso_neto=Decimal("1.00"), + peso_tara=Decimal("0.50"), + ), + ) + ], + transporte_maritimo=TransporteMaritimo( + perm_sct_id="TPAF01", + num_permiso_sct="NumPermisoSCT1", + nombre_aseg="NombreAseg1", + num_poliza_seguro="NumPolizaSeguro1", + tipo_embarcacion_id="B01", + matricula="Matricula1", + numero_omi="IMO1234567", + anio_embarcacion=2003, + nombre_embarc="NombreEmbarc1", + nacionalidad_embarc_id="AFG", + unidades_de_arq_bruto=Decimal("0.001"), + tipo_carga_id="CGS", + eslora=Decimal("0.01"), + manga=Decimal("0.01"), + calado=Decimal("0.01"), + puntal=Decimal("0.01"), + linea_naviera="LineaNaviera1", + nombre_agente_naviero="NombreAgenteNaviero1", + num_autorizacion_naviero_id="ANC001/2022", + num_viaje="NumViaje1", + num_conoc_embarc="NumConocEmbarc1", + permiso_temp_navegacion="PermisoTempNavegac1", + contenedores=[ + ContenedorMaritimo( + tipo_contenedor_id="CM011", + id_ccp_relacionado="CCCBCD94-870A-4332-A52A-A52AA52AA52A", + placa_vm_ccp="JNG7683", + fecha_certificacion_ccp="2024-06-20T11:11:00", + remolques_ccp=[ + RemolqueCCP( + sub_tipo_rem_ccp_id="CTR001", + placa_ccp="JNG7636", + ) + ], + ) + ], + ), + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="NumeroExterior1", + numero_interior="NumeroInterior1", + colonia_id="Colonia1", + localidad_id="Localidad1", + referencia="Referencia1", + municipio_id="Municipio1", + estado_id="Estado1", + pais_id="AFG", + codigo_postal_id="CodigoPosta1", + ), + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 14: TRASLADO AUTOTRANSPORTE NACIONAL +# ============================================================================ +def create_factura_traslado_autotransporte_nacional(): + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 15: TRASLADO AUTOTRANSPORTE EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_autotransporte_extranjero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + fraccion_arancelaria_id="6309000100", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 16: TRASLADO AUTOTRANSPORTE INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_autotransporte_internacional_aduanero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + fraccion_arancelaria_id="6309000100", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS FERROVIARIO TRASLADO +# ============================================================================ +def _ubicaciones_ferroviario_traslado_nacional(): + return [ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="Q0736", + nombre_estacion="SANTO NINO", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="SC283", + nombre_estacion="HUAXTITLA", + fecha_hora_salida_llegada="2023-08-01T01:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="TG0", + nombre_estacion="NAVOJOA", + fecha_hora_salida_llegada="2023-08-01T02:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="E0029", + nombre_estacion="TRES JAGUEYES", + fecha_hora_salida_llegada="2023-08-01T03:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="TI032", + nombre_estacion="NAVOLATO", + fecha_hora_salida_llegada="2023-08-01T04:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + ] + + +def _transporte_ferroviario_traslado() -> TransporteFerroviario: + return TransporteFerroviario( + tipo_de_servicio_id="TS01", + tipo_de_trafico_id="TT01", + derechos_de_paso=[ + DerechoDePaso(tipo_derecho_de_paso_id="CDP114", kilometraje_pagado=Decimal("100")) + ], + carros=[ + Carro( + tipo_carro_id="TC08", + matricula_carro="A00012", + guia_carro="123ASD", + toneladas_netas_carro=Decimal("10"), + ) + ], + ) + + +def _figura_traslado_ferroviario() -> TipoFigura: + return TipoFigura( + tipo_figura_id="02", + rfc_figura="EKU9003173C9", + nombre_figura="NombreFigura", + partes_transporte=[ParteTransporte(parte_transporte_id="PT02")], + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ) + + +def _invoice_traslado_ferroviario_base(lading: LadingComplement) -> Invoice: + return Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement(lading=lading), + ) + + +# ============================================================================ +# EJEMPLO 17: TRASLADO FERROVIARIO NACIONAL +# ============================================================================ +def create_factura_traslado_ferroviario_nacional(): + destino_final = Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="JM047", + nombre_estacion="HUEHUETOCA", + fecha_hora_salida_llegada="2023-08-01T05:00:01", + tipo_estacion_id="03", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ) + + lading = LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("500"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + ubicaciones=_ubicaciones_ferroviario_traslado_nacional() + [destino_final], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202025") + ], + ) + ], + transporte_ferroviario=_transporte_ferroviario_traslado(), + tipos_figura=[_figura_traslado_ferroviario()], + ) + + invoice = _invoice_traslado_ferroviario_base(lading) + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 18: TRASLADO FERROVIARIO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_ferroviario_extranjero(): + destino_final = Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="EF0001", + nombre_estacion="NombreEstacion", + fecha_hora_salida_llegada="2023-08-01T05:00:01", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="ST", + numero_exterior="1234", + colonia_id="1234", + referencia="WHITE HOUSE", + municipio_id="1234", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ) + + lading = LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=_ubicaciones_ferroviario_traslado_nacional() + [destino_final], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202025") + ], + ) + ], + transporte_ferroviario=_transporte_ferroviario_traslado(), + tipos_figura=[_figura_traslado_ferroviario()], + ) + + invoice = _invoice_traslado_ferroviario_base(lading) + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 19: TRASLADO FERROVIARIO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_ferroviario_internacional_aduanero(): + destino_final = Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="JM047", + nombre_estacion="HUEHUETOCA", + fecha_hora_salida_llegada="2023-08-01T05:00:01", + tipo_estacion_id="03", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ) + + lading = LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=_ubicaciones_ferroviario_traslado_nacional() + [destino_final], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202025") + ], + ) + ], + transporte_ferroviario=_transporte_ferroviario_traslado(), + tipos_figura=[_figura_traslado_ferroviario()], + ) + + invoice = _invoice_traslado_ferroviario_base(lading) + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 20: TRASLADO AÉREO NACIONAL +# ============================================================================ +def create_factura_traslado_aereo_nacional(): + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS TRASLADO AÉREO / MARÍTIMO +# ============================================================================ +def _transporte_aereo_base() -> TransporteAereo: + return TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ) + + +def _invoice_traslado_base(lading: LadingComplement) -> Invoice: + return Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer(id="0e82a655-5f0c-4e07-abab-8f322e4123ef"), + recipient=InvoiceRecipient(id="37f7c342-d9a6-4881-9620-0da769b50ce5"), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement(lading=lading), + ) + + +# ============================================================================ +# EJEMPLO 21: TRASLADO AÉREO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_aereo_extranjero(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="EA0143", + nombre_estacion="Phoenix-Mesa Gateway", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12344", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + ) + ], + transporte_aereo=_transporte_aereo_base(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 22: TRASLADO AÉREO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_aereo_internacional_aduanero(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + ) + ], + transporte_aereo=_transporte_aereo_base(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS TRASLADO MARÍTIMO +# ============================================================================ +def _ubicaciones_maritimo_nacional(): + return [ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ] + + +def _mercancia_maritimo_traslado(documentacion_aduanera=None, tipo_materia_id=None, descripcion_materia=None): + return Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id=tipo_materia_id, + descripcion_materia=descripcion_materia, + documentacion_aduanera=documentacion_aduanera, + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="Tu", + peso_bruto=Decimal("1"), + peso_neto=Decimal("1"), + peso_tara=Decimal("0.001"), + num_piezas=1, + ), + ) + + +# ============================================================================ +# EJEMPLO 23: TRASLADO MARÍTIMO NACIONAL +# ============================================================================ +def create_factura_traslado_maritimo_nacional(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="No", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + ubicaciones=_ubicaciones_maritimo_nacional(), + mercancias=[_mercancia_maritimo_traslado()], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 24: TRASLADO MARÍTIMO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_maritimo_extranjero(): + ubicaciones = [ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="PM120", + nombre_estacion="NombreEstacion", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12345", + colonia_id="N/A", + referencia="N/A", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ] + + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="02", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=ubicaciones, + mercancias=[_mercancia_maritimo_traslado(tipo_materia_id="05", descripcion_materia="otramateria")], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 25: TRASLADO MARÍTIMO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_maritimo_internacional_aduanero(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="02", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[ + RegimenAduanero(regimen_aduanero_id="IMD"), + RegimenAduanero(regimen_aduanero_id="IMD"), + ], + ubicaciones=_ubicaciones_maritimo_nacional(), + mercancias=[ + _mercancia_maritimo_traslado( + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + ) + ], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJECUCION +# ============================================================================ +if __name__ == "__main__": + print("=== 1. Autotransporte Nacional ===") + create_factura_autotransporte_nacional() + + print("\n=== 2. Autotransporte Nacional con Impuestos ===") + create_factura_autotransporte_nacional_con_impuestos() + + print("\n=== 3. Autotransporte Extranjero (Salida) ===") + create_factura_autotransporte_extranjero() + + print("\n=== 4. Autotransporte Internacional Aduanero (Entrada) ===") + create_factura_autotransporte_internacional_aduanero() + + print("\n=== 5. Ferroviario Nacional ===") + create_factura_ferroviario_nacional() + + print("\n=== 6. Ferroviario Extranjero (Salida) ===") + create_factura_ferroviario_extranjero() + + print("\n=== 7. Ferroviario Internacional Aduanero (Entrada) ===") + create_factura_ferroviario_internacional_aduanero() + + print("\n=== 8. Aéreo Nacional ===") + create_factura_aereo_nacional() + + print("\n=== 9. Aéreo Extranjero (Salida) ===") + create_factura_aereo_extranjero() + + print("\n=== 10. Aéreo Internacional Aduanero (Entrada) ===") + create_factura_aereo_internacional_aduanero() + + print("\n=== 11. Marítimo Nacional ===") + create_factura_maritimo_nacional() + + print("\n=== 12. Marítimo Extranjero (Salida) ===") + create_factura_maritimo_extranjero() + + print("\n=== 13. Marítimo Internacional Aduanero (Entrada) - Ingreso ===") + create_factura_maritimo_internacional_aduanero() + + print("\n=== 14. Traslado Autotransporte Nacional ===") + create_factura_traslado_autotransporte_nacional() + + print("\n=== 15. Traslado Autotransporte Extranjero (Salida) ===") + create_factura_traslado_autotransporte_extranjero() + + print("\n=== 16. Traslado Autotransporte Internacional Aduanero (Entrada) ===") + create_factura_traslado_autotransporte_internacional_aduanero() + + print("\n=== 17. Traslado Ferroviario Nacional ===") + create_factura_traslado_ferroviario_nacional() + + print("\n=== 18. Traslado Ferroviario Extranjero (Salida) ===") + create_factura_traslado_ferroviario_extranjero() + + print("\n=== 19. Traslado Ferroviario Internacional Aduanero (Entrada) ===") + create_factura_traslado_ferroviario_internacional_aduanero() + + print("\n=== 20. Traslado Aéreo Nacional ===") + create_factura_traslado_aereo_nacional() + + print("\n=== 21. Traslado Aéreo Extranjero (Salida) ===") + create_factura_traslado_aereo_extranjero() + + print("\n=== 22. Traslado Aéreo Internacional Aduanero (Entrada) ===") + create_factura_traslado_aereo_internacional_aduanero() + + print("\n=== 23. Traslado Marítimo Nacional ===") + create_factura_traslado_maritimo_nacional() + + print("\n=== 24. Traslado Marítimo Extranjero (Salida) ===") + create_factura_traslado_maritimo_extranjero() + + print("\n=== 25. Traslado Marítimo Internacional Aduanero (Entrada) ===") + create_factura_traslado_maritimo_internacional_aduanero() diff --git a/examples/ejemplos-factura-carta-porte-valores.py b/examples/ejemplos-factura-carta-porte-valores.py new file mode 100644 index 0000000..929f9d5 --- /dev/null +++ b/examples/ejemplos-factura-carta-porte-valores.py @@ -0,0 +1,3624 @@ +# ============================================================================ +# CONFIGURACION +# ============================================================================ + +from datetime import datetime +from decimal import Decimal + +# Configuracion del cliente +from fiscalapi.models.common_models import FiscalApiSettings +from fiscalapi.services.fiscalapi_client import FiscalApiClient +from fiscalapi.models.fiscalapi_models import ( + Invoice, + InvoiceComplement, + InvoiceIssuer, + InvoiceRecipient, + InvoiceItem, + ItemTax, + TaxCredential, +) +from fiscalapi.models.bill_of_lading_models import ( + LadingComplement, + Ubicacion, + Domicilio, + Mercancia, + CantidadTransporta, + Autotransporte, + Remolque, + TipoFigura, + RegimenAduanero, + DocumentoAduanero, + TransporteFerroviario, + DerechoDePaso, + Carro, + TransporteAereo, + ParteTransporte, + TransporteMaritimo, + ContenedorMaritimo, + RemolqueCCP, + DetalleMercancia, +) + + +settings = FiscalApiSettings( + # api_url="https://test.fiscalapi.com", + # api_key="", + # tenant="" +) + +client = FiscalApiClient(settings=settings) + +# Certificados en base64 +escuela_kemper_urgate_base64_cer = "MIIFsDCCA5igAwIBAgIUMzAwMDEwMDAwMDA1MDAwMDM0MTYwDQYJKoZIhvcNAQELBQAwggErMQ8wDQYDVQQDDAZBQyBVQVQxLjAsBgNVBAoMJVNFUlZJQ0lPIERFIEFETUlOSVNUUkFDSU9OIFRSSUJVVEFSSUExGjAYBgNVBAsMEVNBVC1JRVMgQXV0aG9yaXR5MSgwJgYJKoZIhvcNAQkBFhlvc2Nhci5tYXJ0aW5lekBzYXQuZ29iLm14MR0wGwYDVQQJDBQzcmEgY2VycmFkYSBkZSBjYWxpejEOMAwGA1UEEQwFMDYzNzAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBDSVVEQUQgREUgTUVYSUNPMREwDwYDVQQHDAhDT1lPQUNBTjERMA8GA1UELRMIMi41LjQuNDUxJTAjBgkqhkiG9w0BCQITFnJlc3BvbnNhYmxlOiBBQ0RNQS1TQVQwHhcNMjMwNTE4MTE0MzUxWhcNMjcwNTE4MTE0MzUxWjCB1zEnMCUGA1UEAxMeRVNDVUVMQSBLRU1QRVIgVVJHQVRFIFNBIERFIENWMScwJQYDVQQpEx5FU0NVRUxBIEtFTVBFUiBVUkdBVEUgU0EgREUgQ1YxJzAlBgNVBAoTHkVTQ1VFTEEgS0VNUEVSIFVSR0FURSBTQSBERSBDVjElMCMGA1UELRMcRUtVOTAwMzE3M0M5IC8gVkFEQTgwMDkyN0RKMzEeMBwGA1UEBRMVIC8gVkFEQTgwMDkyN0hTUlNSTDA1MRMwEQYDVQQLEwpTdWN1cnNhbCAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtmecO6n2GS0zL025gbHGQVxznPDICoXzR2uUngz4DqxVUC/w9cE6FxSiXm2ap8Gcjg7wmcZfm85EBaxCx/0J2u5CqnhzIoGCdhBPuhWQnIh5TLgj/X6uNquwZkKChbNe9aeFirU/JbyN7Egia9oKH9KZUsodiM/pWAH00PCtoKJ9OBcSHMq8Rqa3KKoBcfkg1ZrgueffwRLws9yOcRWLb02sDOPzGIm/jEFicVYt2Hw1qdRE5xmTZ7AGG0UHs+unkGjpCVeJ+BEBn0JPLWVvDKHZAQMj6s5Bku35+d/MyATkpOPsGT/VTnsouxekDfikJD1f7A1ZpJbqDpkJnss3vQIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQsFAAOCAgEAFaUgj5PqgvJigNMgtrdXZnbPfVBbukAbW4OGnUhNrA7SRAAfv2BSGk16PI0nBOr7qF2mItmBnjgEwk+DTv8Zr7w5qp7vleC6dIsZFNJoa6ZndrE/f7KO1CYruLXr5gwEkIyGfJ9NwyIagvHHMszzyHiSZIA850fWtbqtythpAliJ2jF35M5pNS+YTkRB+T6L/c6m00ymN3q9lT1rB03YywxrLreRSFZOSrbwWfg34EJbHfbFXpCSVYdJRfiVdvHnewN0r5fUlPtR9stQHyuqewzdkyb5jTTw02D2cUfL57vlPStBj7SEi3uOWvLrsiDnnCIxRMYJ2UA2ktDKHk+zWnsDmaeleSzonv2CHW42yXYPCvWi88oE1DJNYLNkIjua7MxAnkNZbScNw01A6zbLsZ3y8G6eEYnxSTRfwjd8EP4kdiHNJftm7Z4iRU7HOVh79/lRWB+gd171s3d/mI9kte3MRy6V8MMEMCAnMboGpaooYwgAmwclI2XZCczNWXfhaWe0ZS5PmytD/GDpXzkX0oEgY9K/uYo5V77NdZbGAjmyi8cE2B2ogvyaN2XfIInrZPgEffJ4AB7kFA2mwesdLOCh0BLD9itmCve3A1FGR4+stO2ANUoiI3w3Tv2yQSg4bjeDlJ08lXaaFCLW2peEXMXjQUk7fmpb5MNuOUTW6BE=" +escuela_kemper_urgate_base64_key = "MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIAgEAAoIBAQACAggAMBQGCCqGSIb3DQMHBAgwggS/AgEAMASCBMh4EHl7aNSCaMDA1VlRoXCZ5UUmqErAbucoZQObOaLUEm+I+QZ7Y8Giupo+F1XWkLvAsdk/uZlJcTfKLJyJbJwsQYbSpLOCLataZ4O5MVnnmMbfG//NKJn9kSMvJQZhSwAwoGLYDm1ESGezrvZabgFJnoQv8Si1nAhVGTk9FkFBesxRzq07dmZYwFCnFSX4xt2fDHs1PMpQbeq83aL/PzLCce3kxbYSB5kQlzGtUYayiYXcu0cVRu228VwBLCD+2wTDDoCmRXtPesgrLKUR4WWWb5N2AqAU1mNDC+UEYsENAerOFXWnmwrcTAu5qyZ7GsBMTpipW4Dbou2yqQ0lpA/aB06n1kz1aL6mNqGPaJ+OqoFuc8Ugdhadd+MmjHfFzoI20SZ3b2geCsUMNCsAd6oXMsZdWm8lzjqCGWHFeol0ik/xHMQvuQkkeCsQ28PBxdnUgf7ZGer+TN+2ZLd2kvTBOk6pIVgy5yC6cZ+o1Tloql9hYGa6rT3xcMbXlW+9e5jM2MWXZliVW3ZhaPjptJFDbIfWxJPjz4QvKyJk0zok4muv13Iiwj2bCyefUTRz6psqI4cGaYm9JpscKO2RCJN8UluYGbbWmYQU+Int6LtZj/lv8p6xnVjWxYI+rBPdtkpfFYRp+MJiXjgPw5B6UGuoruv7+vHjOLHOotRo+RdjZt7NqL9dAJnl1Qb2jfW6+d7NYQSI/bAwxO0sk4taQIT6Gsu/8kfZOPC2xk9rphGqCSS/4q3Os0MMjA1bcJLyoWLp13pqhK6bmiiHw0BBXH4fbEp4xjSbpPx4tHXzbdn8oDsHKZkWh3pPC2J/nVl0k/yF1KDVowVtMDXE47k6TGVcBoqe8PDXCG9+vjRpzIidqNo5qebaUZu6riWMWzldz8x3Z/jLWXuDiM7/Yscn0Z2GIlfoeyz+GwP2eTdOw9EUedHjEQuJY32bq8LICimJ4Ht+zMJKUyhwVQyAER8byzQBwTYmYP5U0wdsyIFitphw+/IH8+v08Ia1iBLPQAeAvRfTTIFLCs8foyUrj5Zv2B/wTYIZy6ioUM+qADeXyo45uBLLqkN90Rf6kiTqDld78NxwsfyR5MxtJLVDFkmf2IMMJHTqSfhbi+7QJaC11OOUJTD0v9wo0X/oO5GvZhe0ZaGHnm9zqTopALuFEAxcaQlc4R81wjC4wrIrqWnbcl2dxiBtD73KW+wcC9ymsLf4I8BEmiN25lx/OUc1IHNyXZJYSFkEfaxCEZWKcnbiyf5sqFSSlEqZLc4lUPJFAoP6s1FHVcyO0odWqdadhRZLZC9RCzQgPlMRtji/OXy5phh7diOBZv5UYp5nb+MZ2NAB/eFXm2JLguxjvEstuvTDmZDUb6Uqv++RdhO5gvKf/AcwU38ifaHQ9uvRuDocYwVxZS2nr9rOwZ8nAh+P2o4e0tEXjxFKQGhxXYkn75H3hhfnFYjik/2qunHBBZfcdG148MaNP6DjX33M238T9Zw/GyGx00JMogr2pdP4JAErv9a5yt4YR41KGf8guSOUbOXVARw6+ybh7+meb7w4BeTlj3aZkv8tVGdfIt3lrwVnlbzhLjeQY6PplKp3/a5Kr5yM0T4wJoKQQ6v3vSNmrhpbuAtKxpMILe8CQoo=" +password = "12345678a" + + +# Helper: build the standard EKU tax credentials (cer + key) +def _kemper_credentials(): + return [ + TaxCredential(base64_file=escuela_kemper_urgate_base64_cer, file_type=0, password=password), + TaxCredential(base64_file=escuela_kemper_urgate_base64_key, file_type=1, password=password), + ] + + +# Helper: standard autotransporte with one remolque +def _autotransporte(): + return Autotransporte( + perm_sct_id="TPAF01", + num_permiso_sct="NumPermisoSCT1", + config_vehicular_id="VL", + peso_bruto_vehicular=Decimal("1"), + placa_vm="plac892", + anio_modelo_vm=2020, + asegura_resp_civil="AseguraRespCivil", + poliza_resp_civil="123456789", + remolques=[Remolque(sub_tipo_rem_id="CTR004", placa="VL45K98")], + ) + + +# Helper: standard mercancia (sin documentacion aduanera) +def _mercancia_base(cantidad_transporta=None, documentacion_aduanera=None, tipo_materia_id=None, descripcion_materia=None): + return Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + fraccion_arancelaria_id="6309000100", + tipo_materia_id=tipo_materia_id, + descripcion_materia=descripcion_materia, + documentacion_aduanera=documentacion_aduanera, + cantidad_transporta=cantidad_transporta or [ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + ) + + +# ============================================================================ +# 1. FACTURA INGRESO AUTOTRANSPORTE NACIONAL (sin impuestos) +# ============================================================================ +def create_factura_autotransporte_nacional(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="URE180429TM6", + legal_name="UNIVERSIDAD ROBOTICA ESPAÑOLA", + zip_code="86991", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[_mercancia_base()], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="URE180429TM6", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="NumeroExterior1", + numero_interior="NumeroInterior1", + colonia_id="Colonia1", + localidad_id="Localidad1", + referencia="Referencia1", + municipio_id="Municipio1", + estado_id="Estado1", + pais_id="AFG", + codigo_postal_id="CodigoPosta1", + ), + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# 2. FACTURA INGRESO AUTOTRANSPORTE NACIONAL CON IMPUESTOS +# ============================================================================ +def create_factura_autotransporte_nacional_con_impuestos(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="URE180429TM6", + legal_name="UNIVERSIDAD ROBOTICA ESPAÑOLA", + zip_code="86991", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("26232.75"), + discount=Decimal("0"), + tax_object_code="02", + item_taxes=[ + ItemTax(tax_code="002", tax_type_code="Tasa", tax_rate=Decimal("0.160000"), tax_flag_code="T"), + ItemTax(tax_code="002", tax_type_code="Tasa", tax_rate=Decimal("0.040000"), tax_flag_code="R"), + ], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="URE180429TM6", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[_mercancia_base()], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="URE180429TM6", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="NumeroExterior1", + numero_interior="NumeroInterior1", + colonia_id="Colonia1", + localidad_id="Localidad1", + referencia="Referencia1", + municipio_id="Municipio1", + estado_id="Estado1", + pais_id="AFG", + codigo_postal_id="CodigoPosta1", + ), + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# 3. FACTURA INGRESO AUTOTRANSPORTE EXTRANJERO (salida) +# ============================================================================ +def create_factura_autotransporte_extranjero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + _mercancia_base(tipo_materia_id="05", descripcion_materia="otramateria") + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# 4. FACTURA INGRESO AUTOTRANSPORTE INTERNACIONAL ADUANERO (entrada) +# ============================================================================ +def create_factura_autotransporte_internacional_aduanero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + _mercancia_base( + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS FERROVIARIO +# ============================================================================ +def _transporte_ferroviario() -> TransporteFerroviario: + return TransporteFerroviario( + tipo_de_servicio_id="TS01", + tipo_de_trafico_id="TT01", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + derechos_de_paso=[ + DerechoDePaso( + tipo_derecho_de_paso_id="CDP114", + kilometraje_pagado=Decimal("100"), + ) + ], + carros=[ + Carro( + tipo_carro_id="TC08", + matricula_carro="A00012", + guia_carro="123ASD", + toneladas_netas_carro=Decimal("10"), + ) + ], + ) + + +def _figura_ferroviario() -> TipoFigura: + return TipoFigura( + tipo_figura_id="02", + rfc_figura="EKU9003173C9", + nombre_figura="NombreFigura", + partes_transporte=[ParteTransporte(parte_transporte_id="PT02")], + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ) + + +# ============================================================================ +# EJEMPLO 5: TRANSPORTE FERROVIARIO NACIONAL +# ============================================================================ +def create_factura_ferroviario_nacional(): + credentials = _kemper_credentials() + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + ), + recipient=InvoiceRecipient( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + tax_zip_code="99080", + cfdi_use_id="CP01", + ), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + tax_credentials=credentials, + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("500"), + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T11:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97001", + nombre_estacion="MONTERREY", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97002", + nombre_estacion="GUADALAJARA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T13:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97003", + nombre_estacion="QUERETARO", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T14:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97004", + nombre_estacion="TOLUCA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T15:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + ], + mercancias=[ + _mercancia_base( + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + documentacion_aduanera=None, + tipo_materia_id=None, + descripcion_materia=None, + ) + ], + transporte_ferroviario=_transporte_ferroviario(), + tipos_figura=[_figura_ferroviario()], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura ferroviario nacional creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 6: TRANSPORTE FERROVIARIO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_ferroviario_extranjero(): + credentials = _kemper_credentials() + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + ), + recipient=InvoiceRecipient( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + tax_zip_code="99080", + cfdi_use_id="CP01", + ), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + tax_credentials=credentials, + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T11:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97001", + nombre_estacion="MONTERREY", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97002", + nombre_estacion="GUADALAJARA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T13:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97003", + nombre_estacion="QUERETARO", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T14:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97004", + nombre_estacion="TOLUCA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="DESTINATARIO EXTRANJERO", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2024-11-12T15:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="Main Street", + numero_exterior="100", + municipio_id="City", + estado_id="TX", + pais_id="USA", + codigo_postal_id="78500", + ), + ), + ], + mercancias=[ + _mercancia_base( + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + documentacion_aduanera=None, + tipo_materia_id="05", + descripcion_materia="otramateria", + ) + ], + transporte_ferroviario=_transporte_ferroviario(), + tipos_figura=[_figura_ferroviario()], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura ferroviario extranjero (salida) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 7: TRANSPORTE FERROVIARIO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_ferroviario_internacional_aduanero(): + credentials = _kemper_credentials() + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + ), + recipient=InvoiceRecipient( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + tax_zip_code="99080", + cfdi_use_id="CP01", + ), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + tax_credentials=credentials, + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T11:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97001", + nombre_estacion="MONTERREY", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97002", + nombre_estacion="GUADALAJARA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T13:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97003", + nombre_estacion="QUERETARO", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T14:00:00", + distancia_recorrida=Decimal("100"), + num_estacion_id="97004", + nombre_estacion="TOLUCA", + tipo_estacion_id="01", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T15:00:00", + distancia_recorrida=Decimal("100"), + nombre_estacion="HUEHUETOCA", + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0203", + localidad_id="01", + referencia="casa blanca", + municipio_id="006", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25900", + ), + ), + ], + mercancias=[ + _mercancia_base( + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + documentacion_aduanera=[ + DocumentoAduanero( + tipo_doc_aduanero_id="01", + num_pedimento_aduanero="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + tipo_materia_id="05", + descripcion_materia="otramateria", + ) + ], + transporte_ferroviario=_transporte_ferroviario(), + tipos_figura=[_figura_ferroviario()], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura ferroviario intl aduanero (entrada) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 8: TRANSPORTE AÉREO NACIONAL +# ============================================================================ +def create_factura_aereo_nacional(): + credentials = _kemper_credentials() + + invoice = Invoice( + series="Serie", + date=datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), + payment_form_id="01", + currency_id="MXN", + payment_method_id="PPD", + expedition_zip_code="99080", + cfdi_type_id="T", + tax_object_id="01", + issuer=InvoiceIssuer( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + ), + recipient=InvoiceRecipient( + tax_id="EKU9003173C9", + tax_name="ESCUELA KEMPER URGATE", + tax_regime_id="601", + tax_zip_code="99080", + cfdi_use_id="CP01", + ), + items=[ + InvoiceItem( + quantity=Decimal("1"), + unit_id="E48", + unit_price=Decimal("0"), + description="Flete", + product_id="78101801", + tax_object_id="01", + ) + ], + tax_credentials=credentials, + complements=[ + InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + peso_neto_total=Decimal("10"), + unidad_peso_id="XBX", + ubicaciones=[ + Ubicacion( + tipo_ubicacion_id="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T10:00:00", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + tipo_estacion_id="02", + ), + Ubicacion( + tipo_ubicacion_id="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="ESCUELA KEMPER URGATE", + fecha_hora_salida_llegada="2024-11-12T12:00:00", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + tipo_estacion_id="02", + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("100"), + clave_unidad_id="H87", + peso_en_kg=Decimal("10"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("100"), + id_origen="OR101010", + id_destino="DE202025", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ) + ], + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura aéreo nacional creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# HELPERS MARITIMO +# ============================================================================ +def _transporte_maritimo_base() -> TransporteMaritimo: + return TransporteMaritimo( + perm_sct_id="TPAF01", + num_permiso_sct="NumPermisoSCT1", + nombre_aseg="NombreAseg1", + num_poliza_seguro="NumPolizaSeguro1", + tipo_embarcacion_id="B01", + matricula="Matricula1", + numero_omi="IMO1234567", + anio_embarcacion=2003, + nombre_embarc="NombreEmbarc1", + nacionalidad_embarc_id="AFG", + unidades_de_arq_bruto=Decimal("0.001"), + tipo_carga_id="CGS", + eslora=Decimal("0.01"), + manga=Decimal("0.01"), + calado=Decimal("0.01"), + puntal=Decimal("0.01"), + linea_naviera="LineaNaviera1", + nombre_agente_naviero="NombreAgenteNaviero1", + num_autorizacion_naviero_id="ANC001/2022", + num_viaje="NumViaje1", + num_conoc_embarc="NumConocEmbarc1", + permiso_temp_navegacion="PermisoTempNavegac1", + contenedores=[ + ContenedorMaritimo( + tipo_contenedor_id="CM011", + id_ccp_relacionado="CCCBCD94-870A-4332-A52A-A52AA52AA52A", + placa_vm_ccp="JNG7683", + fecha_certificacion_ccp="2024-06-20T11:11:00", + remolques_ccp=[ + RemolqueCCP( + sub_tipo_rem_ccp_id="CTR001", + placa_ccp="JNG7636", + ) + ], + ) + ], + ) + + +# ============================================================================ +# EJEMPLO 9: TRANSPORTE AÉREO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_aereo_extranjero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="EA0143", + nombre_estacion="Phoenix-Mesa Gateway", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12344", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura aéreo extranjero (salida) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 10: TRANSPORTE AÉREO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_aereo_internacional_aduanero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura aéreo intl aduanero (entrada) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 11: TRANSPORTE MARÍTIMO NACIONAL +# ============================================================================ +def create_factura_maritimo_nacional(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="Tu", + peso_bruto=Decimal("1"), + peso_neto=Decimal("1"), + peso_tara=Decimal("0.001"), + num_piezas=1, + ), + ) + ], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura marítimo nacional creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 12: TRANSPORTE MARÍTIMO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_maritimo_extranjero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="02", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="PM120", + nombre_estacion="NombreEstacion", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12345", + colonia_id="N/A", + referencia="N/A", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="Tu", + peso_bruto=Decimal("1"), + peso_neto=Decimal("1"), + peso_tara=Decimal("0.001"), + num_piezas=1, + ), + ) + ], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ), + ) + + client = FiscalApiClient(settings=settings) + response = client.invoices.create(invoice) + if response.succeeded: + print("Factura marítimo extranjero (salida) creada:", response.data) + else: + print("Error:", response.message) + + +# ============================================================================ +# EJEMPLO 13: TRANSPORTE MARÍTIMO INTERNACIONAL ADUANERO (ENTRADA) - INGRESO +# ============================================================================ +def create_factura_maritimo_internacional_aduanero(): + invoice = Invoice( + version_code="4.0", + payment_form_code="01", + payment_method_code="PUE", + currency_code="MXN", + type_code="I", + expedition_zip_code="42501", + series="CP3.1", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="01", + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[ + RegimenAduanero(regimen_aduanero_id="IMD"), + RegimenAduanero(regimen_aduanero_id="IMD"), + ], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T04:00:01", + tipo_estacion_id="02", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1.50"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + fraccion_arancelaria_id="6309000100", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + cves_transporte_id="02", + ) + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="X1A", + peso_bruto=Decimal("1.50"), + peso_neto=Decimal("1.00"), + peso_tara=Decimal("0.50"), + ), + ) + ], + transporte_maritimo=TransporteMaritimo( + perm_sct_id="TPAF01", + num_permiso_sct="NumPermisoSCT1", + nombre_aseg="NombreAseg1", + num_poliza_seguro="NumPolizaSeguro1", + tipo_embarcacion_id="B01", + matricula="Matricula1", + numero_omi="IMO1234567", + anio_embarcacion=2003, + nombre_embarc="NombreEmbarc1", + nacionalidad_embarc_id="AFG", + unidades_de_arq_bruto=Decimal("0.001"), + tipo_carga_id="CGS", + eslora=Decimal("0.01"), + manga=Decimal("0.01"), + calado=Decimal("0.01"), + puntal=Decimal("0.01"), + linea_naviera="LineaNaviera1", + nombre_agente_naviero="NombreAgenteNaviero1", + num_autorizacion_naviero_id="ANC001/2022", + num_viaje="NumViaje1", + num_conoc_embarc="NumConocEmbarc1", + permiso_temp_navegacion="PermisoTempNavegac1", + contenedores=[ + ContenedorMaritimo( + tipo_contenedor_id="CM011", + id_ccp_relacionado="CCCBCD94-870A-4332-A52A-A52AA52AA52A", + placa_vm_ccp="JNG7683", + fecha_certificacion_ccp="2024-06-20T11:11:00", + remolques_ccp=[ + RemolqueCCP( + sub_tipo_rem_ccp_id="CTR001", + placa_ccp="JNG7636", + ) + ], + ) + ], + ), + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="NumeroExterior1", + numero_interior="NumeroInterior1", + colonia_id="Colonia1", + localidad_id="Localidad1", + referencia="Referencia1", + municipio_id="Municipio1", + estado_id="Estado1", + pais_id="AFG", + codigo_postal_id="CodigoPosta1", + ), + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 14: TRASLADO AUTOTRANSPORTE NACIONAL +# ============================================================================ +def create_factura_traslado_autotransporte_nacional(): + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 15: TRASLADO AUTOTRANSPORTE EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_autotransporte_extranjero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + fraccion_arancelaria_id="6309000100", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 16: TRASLADO AUTOTRANSPORTE INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_autotransporte_internacional_aduanero(): + domicilio_usa = Domicilio( + calle="ST", + numero_exterior="214", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="N/A", + ) + + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="SerieCCP31", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="USA", + via_entrada_salida_id="01", + total_dist_rec=Decimal("1"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + logistica_inversa_recoleccion_devolucion_id="Sí", + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=domicilio_usa, + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + distancia_recorrida=Decimal("1"), + domicilio=domicilio_usa, + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2003-04-02T00:00:00", + lote_medicamento="LoteMedic1", + forma_farmaceutica_id="01", + condiciones_esp_transp_id="01", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + fraccion_arancelaria_id="6309000100", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + autotransporte=_autotransporte(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="NumLicencia1", + nombre_figura="NombreFigura1", + domicilio=domicilio_usa, + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS FERROVIARIO TRASLADO +# ============================================================================ +def _ubicaciones_ferroviario_traslado_nacional(): + return [ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="Q0736", + nombre_estacion="SANTO NINO", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202021", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="SC283", + nombre_estacion="HUAXTITLA", + fecha_hora_salida_llegada="2023-08-01T01:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202022", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="TG0", + nombre_estacion="NAVOJOA", + fecha_hora_salida_llegada="2023-08-01T02:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202023", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="E0029", + nombre_estacion="TRES JAGUEYES", + fecha_hora_salida_llegada="2023-08-01T03:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202024", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="TI032", + nombre_estacion="NAVOLATO", + fecha_hora_salida_llegada="2023-08-01T04:00:01", + tipo_estacion_id="02", + distancia_recorrida=Decimal("100"), + ), + ] + + +def _transporte_ferroviario_traslado() -> TransporteFerroviario: + return TransporteFerroviario( + tipo_de_servicio_id="TS01", + tipo_de_trafico_id="TT01", + derechos_de_paso=[ + DerechoDePaso(tipo_derecho_de_paso_id="CDP114", kilometraje_pagado=Decimal("100")) + ], + carros=[ + Carro( + tipo_carro_id="TC08", + matricula_carro="A00012", + guia_carro="123ASD", + toneladas_netas_carro=Decimal("10"), + ) + ], + ) + + +def _figura_traslado_ferroviario() -> TipoFigura: + return TipoFigura( + tipo_figura_id="02", + rfc_figura="EKU9003173C9", + nombre_figura="NombreFigura", + partes_transporte=[ParteTransporte(parte_transporte_id="PT02")], + domicilio=Domicilio( + calle="calle", + numero_exterior="211", + colonia_id="0814", + localidad_id="01", + referencia="casa blanca", + municipio_id="010", + estado_id="ZAC", + pais_id="MEX", + codigo_postal_id="99080", + ), + ) + + +def _invoice_traslado_ferroviario_base(lading: LadingComplement) -> Invoice: + return Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement(lading=lading), + ) + + +# ============================================================================ +# EJEMPLO 17: TRASLADO FERROVIARIO NACIONAL +# ============================================================================ +def create_factura_traslado_ferroviario_nacional(): + destino_final = Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="JM047", + nombre_estacion="HUEHUETOCA", + fecha_hora_salida_llegada="2023-08-01T05:00:01", + tipo_estacion_id="03", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ) + + lading = LadingComplement( + transp_internac_id="No", + total_dist_rec=Decimal("500"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + ubicaciones=_ubicaciones_ferroviario_traslado_nacional() + [destino_final], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202025") + ], + ) + ], + transporte_ferroviario=_transporte_ferroviario_traslado(), + tipos_figura=[_figura_traslado_ferroviario()], + ) + + invoice = _invoice_traslado_ferroviario_base(lading) + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 18: TRASLADO FERROVIARIO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_ferroviario_extranjero(): + destino_final = Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="EF0001", + nombre_estacion="NombreEstacion", + fecha_hora_salida_llegada="2023-08-01T05:00:01", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="ST", + numero_exterior="1234", + colonia_id="1234", + referencia="WHITE HOUSE", + municipio_id="1234", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ) + + lading = LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=_ubicaciones_ferroviario_traslado_nacional() + [destino_final], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202025") + ], + ) + ], + transporte_ferroviario=_transporte_ferroviario_traslado(), + tipos_figura=[_figura_traslado_ferroviario()], + ) + + invoice = _invoice_traslado_ferroviario_base(lading) + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 19: TRASLADO FERROVIARIO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_ferroviario_internacional_aduanero(): + destino_final = Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202025", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="JM047", + nombre_estacion="HUEHUETOCA", + fecha_hora_salida_llegada="2023-08-01T05:00:01", + tipo_estacion_id="03", + distancia_recorrida=Decimal("100"), + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ) + + lading = LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="04", + total_dist_rec=Decimal("500"), + registro_istmo_id="Sí", + ubicacion_polo_origen_id="01", + ubicacion_polo_destino_id="01", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=_ubicaciones_ferroviario_traslado_nacional() + [destino_final], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202025") + ], + ) + ], + transporte_ferroviario=_transporte_ferroviario_traslado(), + tipos_figura=[_figura_traslado_ferroviario()], + ) + + invoice = _invoice_traslado_ferroviario_base(lading) + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 20: TRASLADO AÉREO NACIONAL +# ============================================================================ +def create_factura_traslado_aereo_nacional(): + invoice = Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement( + lading=LadingComplement( + transp_internac_id="No", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + cantidad_transporta=[ + CantidadTransporta( + cantidad=Decimal("1"), + id_origen="OR101010", + id_destino="DE202020", + ) + ], + ) + ], + transporte_aereo=TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ), + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS TRASLADO AÉREO / MARÍTIMO +# ============================================================================ +def _transporte_aereo_base() -> TransporteAereo: + return TransporteAereo( + perm_sct_id="TPAF01", + num_permiso_sct="Demo", + matricula_aeronave="61E5-WZ", + nombre_aseg="NombreAseg", + num_poliza_seguro="NumPolizaSeguro", + numero_guia="acUbYlBVTmlzx", + lugar_contrato="LugarContrato", + codigo_transportista_id="CA001", + rfc_embarcador="EKU9003173C9", + nombre_embarcador="Embarcador", + ) + + +def _invoice_traslado_base(lading: LadingComplement) -> Invoice: + return Invoice( + version_code="4.0", + currency_code="XXX", + type_code="T", + expedition_zip_code="42501", + series="Serie", + date=datetime.now(), + exchange_rate=Decimal("1"), + export_code="01", + issuer=InvoiceIssuer( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + tax_regime_code="601", + tax_credentials=_kemper_credentials(), + ), + recipient=InvoiceRecipient( + tin="EKU9003173C9", + legal_name="ESCUELA KEMPER URGATE", + zip_code="42501", + tax_regime_code="601", + cfdi_use_code="S01", + ), + items=[ + InvoiceItem( + item_code="78101800", + item_sku="UT421511", + quantity=Decimal("1"), + unit_of_measurement_code="H87", + description="Transporte de carga por carretera", + unit_price=Decimal("100.00"), + discount=Decimal("0"), + tax_object_code="01", + item_taxes=[], + ) + ], + complement=InvoiceComplement(lading=lading), + ) + + +# ============================================================================ +# EJEMPLO 21: TRASLADO AÉREO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_aereo_extranjero(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="EA0143", + nombre_estacion="Phoenix-Mesa Gateway", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12344", + colonia_id="N/A", + referencia="WHITE HOUSE", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + ) + ], + transporte_aereo=_transporte_aereo_base(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 22: TRASLADO AÉREO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_aereo_internacional_aduanero(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="03", + unidad_peso_id="XBX", + peso_neto_total=Decimal("10"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="IMD")], + ubicaciones=[ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="EA0417", + nombre_estacion="Loreto", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="EA0418", + nombre_estacion="Los Cabos", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ], + mercancias=[ + Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + ) + ], + transporte_aereo=_transporte_aereo_base(), + tipos_figura=[ + TipoFigura( + tipo_figura_id="01", + rfc_figura="EKU9003173C9", + num_licencia="a234567890", + nombre_figura="NombreFigura", + ) + ], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# HELPERS TRASLADO MARÍTIMO +# ============================================================================ +def _ubicaciones_maritimo_nacional(): + return [ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + tipo_estacion_id="03", + domicilio=Domicilio( + calle="Calle2", + numero_exterior="214", + numero_interior="215", + colonia_id="0347", + localidad_id="23", + referencia="casa negra", + municipio_id="004", + estado_id="COA", + pais_id="MEX", + codigo_postal_id="25350", + ), + ), + ] + + +def _mercancia_maritimo_traslado(documentacion_aduanera=None, tipo_materia_id=None, descripcion_materia=None): + return Mercancia( + bienes_transp_id="11121900", + descripcion="Accesorios de equipo de telefonía", + cantidad=Decimal("1.0"), + clave_unidad_id="XBX", + material_peligroso_id="No", + denominacion_generica_prod="DenominacionGenericaProd1", + denominacion_distintiva_prod="DenominacionDistintivaProd1", + fabricante="Fabricante1", + fecha_caducidad="2028-01-01T00:00:00", + lote_medicamento="LoteMedic1", + registro_sanitario_folio_autorizacion="RegistroSanita1", + peso_en_kg=Decimal("1"), + valor_mercancia=Decimal("100"), + moneda_id="MXN", + tipo_materia_id=tipo_materia_id, + descripcion_materia=descripcion_materia, + documentacion_aduanera=documentacion_aduanera, + cantidad_transporta=[ + CantidadTransporta(cantidad=Decimal("1"), id_origen="OR101010", id_destino="DE202020") + ], + detalle_mercancia=DetalleMercancia( + unidad_peso_merc_id="Tu", + peso_bruto=Decimal("1"), + peso_neto=Decimal("1"), + peso_tara=Decimal("0.001"), + num_piezas=1, + ), + ) + + +# ============================================================================ +# EJEMPLO 23: TRASLADO MARÍTIMO NACIONAL +# ============================================================================ +def create_factura_traslado_maritimo_nacional(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="No", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + ubicaciones=_ubicaciones_maritimo_nacional(), + mercancias=[_mercancia_maritimo_traslado()], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 24: TRASLADO MARÍTIMO EXTRANJERO (SALIDA) +# ============================================================================ +def create_factura_traslado_maritimo_extranjero(): + ubicaciones = [ + Ubicacion( + tipo_ubicacion="Origen", + id_ubicacion="OR101010", + rfc_remitente_destinatario="EKU9003173C9", + nombre_remitente_destinatario="NombreRemitenteDestinatario1", + num_estacion_id="PM001", + nombre_estacion="Rosarito", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:00", + tipo_estacion_id="01", + domicilio=Domicilio( + calle="Calle1", + numero_exterior="211", + numero_interior="212", + colonia_id="1957", + localidad_id="13", + referencia="casa blanca", + municipio_id="011", + estado_id="CMX", + pais_id="MEX", + codigo_postal_id="13250", + ), + ), + Ubicacion( + tipo_ubicacion="Destino", + id_ubicacion="DE202020", + rfc_remitente_destinatario="XEXX010101000", + nombre_remitente_destinatario="NombreRemitenteDestinatario2", + num_reg_id_trib="01010101", + residencia_fiscal_id="USA", + num_estacion_id="PM120", + nombre_estacion="NombreEstacion", + navegacion_trafico_id="Altura", + fecha_hora_salida_llegada="2023-08-01T00:00:01", + domicilio=Domicilio( + calle="ST", + numero_exterior="12345", + colonia_id="N/A", + referencia="N/A", + municipio_id="N/A", + estado_id="TX", + pais_id="USA", + codigo_postal_id="12345", + ), + ), + ] + + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Salida", + pais_origen_destino_id="USA", + via_entrada_salida_id="02", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[RegimenAduanero(regimen_aduanero_id="EXD")], + ubicaciones=ubicaciones, + mercancias=[_mercancia_maritimo_traslado(tipo_materia_id="05", descripcion_materia="otramateria")], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJEMPLO 25: TRASLADO MARÍTIMO INTERNACIONAL ADUANERO (ENTRADA) +# ============================================================================ +def create_factura_traslado_maritimo_internacional_aduanero(): + invoice = _invoice_traslado_base( + LadingComplement( + transp_internac_id="Sí", + entrada_salida_merc_id="Entrada", + pais_origen_destino_id="AFG", + via_entrada_salida_id="02", + unidad_peso_id="XBX", + peso_neto_total=Decimal("1"), + regimen_aduaneros=[ + RegimenAduanero(regimen_aduanero_id="IMD"), + RegimenAduanero(regimen_aduanero_id="IMD"), + ], + ubicaciones=_ubicaciones_maritimo_nacional(), + mercancias=[ + _mercancia_maritimo_traslado( + tipo_materia_id="05", + descripcion_materia="otramateria", + documentacion_aduanera=[ + DocumentoAduanero( + tipo_documento_id="01", + num_pedimento="23 43 0472 8000448", + rfc_impo="EKU9003173C9", + ) + ], + ) + ], + transporte_maritimo=_transporte_maritimo_base(), + tipos_figura=[_figura_ferroviario()], + ) + ) + + response = client.invoices.create(invoice) + if response.succeeded: + print(response.data) + else: + print(response.message) + print(response.details) + + +# ============================================================================ +# EJECUCION +# ============================================================================ +if __name__ == "__main__": + print("=== 1. Autotransporte Nacional ===") + create_factura_autotransporte_nacional() + + print("\n=== 2. Autotransporte Nacional con Impuestos ===") + create_factura_autotransporte_nacional_con_impuestos() + + print("\n=== 3. Autotransporte Extranjero (Salida) ===") + create_factura_autotransporte_extranjero() + + print("\n=== 4. Autotransporte Internacional Aduanero (Entrada) ===") + create_factura_autotransporte_internacional_aduanero() + + print("\n=== 5. Ferroviario Nacional ===") + create_factura_ferroviario_nacional() + + print("\n=== 6. Ferroviario Extranjero (Salida) ===") + create_factura_ferroviario_extranjero() + + print("\n=== 7. Ferroviario Internacional Aduanero (Entrada) ===") + create_factura_ferroviario_internacional_aduanero() + + print("\n=== 8. Aéreo Nacional ===") + create_factura_aereo_nacional() + + print("\n=== 9. Aéreo Extranjero (Salida) ===") + create_factura_aereo_extranjero() + + print("\n=== 10. Aéreo Internacional Aduanero (Entrada) ===") + create_factura_aereo_internacional_aduanero() + + print("\n=== 11. Marítimo Nacional ===") + create_factura_maritimo_nacional() + + print("\n=== 12. Marítimo Extranjero (Salida) ===") + create_factura_maritimo_extranjero() + + print("\n=== 13. Marítimo Internacional Aduanero (Entrada) - Ingreso ===") + create_factura_maritimo_internacional_aduanero() + + print("\n=== 14. Traslado Autotransporte Nacional ===") + create_factura_traslado_autotransporte_nacional() + + print("\n=== 15. Traslado Autotransporte Extranjero (Salida) ===") + create_factura_traslado_autotransporte_extranjero() + + print("\n=== 16. Traslado Autotransporte Internacional Aduanero (Entrada) ===") + create_factura_traslado_autotransporte_internacional_aduanero() + + print("\n=== 17. Traslado Ferroviario Nacional ===") + create_factura_traslado_ferroviario_nacional() + + print("\n=== 18. Traslado Ferroviario Extranjero (Salida) ===") + create_factura_traslado_ferroviario_extranjero() + + print("\n=== 19. Traslado Ferroviario Internacional Aduanero (Entrada) ===") + create_factura_traslado_ferroviario_internacional_aduanero() + + print("\n=== 20. Traslado Aéreo Nacional ===") + create_factura_traslado_aereo_nacional() + + print("\n=== 21. Traslado Aéreo Extranjero (Salida) ===") + create_factura_traslado_aereo_extranjero() + + print("\n=== 22. Traslado Aéreo Internacional Aduanero (Entrada) ===") + create_factura_traslado_aereo_internacional_aduanero() + + print("\n=== 23. Traslado Marítimo Nacional ===") + create_factura_traslado_maritimo_nacional() + + print("\n=== 24. Traslado Marítimo Extranjero (Salida) ===") + create_factura_traslado_maritimo_extranjero() + + print("\n=== 25. Traslado Marítimo Internacional Aduanero (Entrada) ===") + create_factura_traslado_maritimo_internacional_aduanero() diff --git a/fiscalapi/__init__.py b/fiscalapi/__init__.py index 6800484..f11d672 100644 --- a/fiscalapi/__init__.py +++ b/fiscalapi/__init__.py @@ -21,6 +21,30 @@ ValidationFailure, ) +# Modelos de Carta Porte (Bill of Lading) +from .models.bill_of_lading_models import ( + Domicilio, + RegimenAduanero, + Ubicacion, + DocumentoAduanero, + CantidadTransporta, + DetalleMercancia, + Mercancia, + Remolque, + Autotransporte, + RemolqueCCP, + ContenedorMaritimo, + TransporteMaritimo, + TransporteAereo, + DerechoDePaso, + ContenedorFerroviario, + Carro, + TransporteFerroviario, + ParteTransporte, + TipoFigura, + LadingComplement, +) + # Modelos de dominio from .models.fiscalapi_models import ( # Product models @@ -171,6 +195,27 @@ "PayrollComplement", "LadingComplement", "InvoiceComplement", + # Bill of Lading models + "Domicilio", + "RegimenAduanero", + "Ubicacion", + "DocumentoAduanero", + "CantidadTransporta", + "DetalleMercancia", + "Mercancia", + "Remolque", + "Autotransporte", + "RemolqueCCP", + "ContenedorMaritimo", + "TransporteMaritimo", + "TransporteAereo", + "DerechoDePaso", + "ContenedorFerroviario", + "Carro", + "TransporteFerroviario", + "ParteTransporte", + "TipoFigura", + "LadingComplement", # Invoice models "InvoiceResponse", "Invoice", diff --git a/fiscalapi/models/__init__.py b/fiscalapi/models/__init__.py index 26498df..6c9b435 100644 --- a/fiscalapi/models/__init__.py +++ b/fiscalapi/models/__init__.py @@ -8,6 +8,29 @@ PagedList, ValidationFailure, ) +from .bill_of_lading_models import ( + # Bill of Lading models + Domicilio, + RegimenAduanero, + Ubicacion, + DocumentoAduanero, + CantidadTransporta, + DetalleMercancia, + Mercancia, + Remolque, + Autotransporte, + RemolqueCCP, + ContenedorMaritimo, + TransporteMaritimo, + TransporteAereo, + DerechoDePaso, + ContenedorFerroviario, + Carro, + TransporteFerroviario, + ParteTransporte, + TipoFigura, + LadingComplement, +) from .fiscalapi_models import ( # Product models ProductTax, @@ -90,6 +113,27 @@ __all__ = [ # common_models "ApiResponse", + # Bill of Lading models + "Domicilio", + "RegimenAduanero", + "Ubicacion", + "DocumentoAduanero", + "CantidadTransporta", + "DetalleMercancia", + "Mercancia", + "Remolque", + "Autotransporte", + "RemolqueCCP", + "ContenedorMaritimo", + "TransporteMaritimo", + "TransporteAereo", + "DerechoDePaso", + "ContenedorFerroviario", + "Carro", + "TransporteFerroviario", + "ParteTransporte", + "TipoFigura", + "LadingComplement", "BaseDto", "CatalogDto", "FiscalApiSettings", diff --git a/fiscalapi/models/bill_of_lading_models.py b/fiscalapi/models/bill_of_lading_models.py new file mode 100644 index 0000000..100c2ae --- /dev/null +++ b/fiscalapi/models/bill_of_lading_models.py @@ -0,0 +1,306 @@ +"""Modelos de Carta Porte (Bill of Lading) para complemento de factura CFDI 4.0.""" + +from decimal import Decimal +from typing import Optional + +from pydantic import BaseModel, ConfigDict, Field + + +# ===== Domicilio ===== + +class Domicilio(BaseModel): + """Domicilio asociado a una ubicación o figura de transporte.""" + calle: Optional[str] = Field(default=None, alias="calle") + numero_exterior: Optional[str] = Field(default=None, alias="numeroExterior") + numero_interior: Optional[str] = Field(default=None, alias="numeroInterior") + colonia_id: Optional[str] = Field(default=None, alias="coloniaId") + localidad_id: Optional[str] = Field(default=None, alias="localidadId") + referencia: Optional[str] = Field(default=None, alias="referencia") + municipio_id: Optional[str] = Field(default=None, alias="municipioId") + estado_id: Optional[str] = Field(default=None, alias="estadoId") + pais_id: Optional[str] = Field(default=None, alias="paisId") + codigo_postal_id: Optional[str] = Field(default=None, alias="codigoPostalId") + + model_config = ConfigDict(populate_by_name=True) + + +# ===== Regimen Aduanero ===== + +class RegimenAduanero(BaseModel): + """Régimen aduanero aplicable al transporte internacional.""" + regimen_aduanero_id: Optional[str] = Field(default=None, alias="regimenAduaneroId") + + model_config = ConfigDict(populate_by_name=True) + + +# ===== Ubicacion ===== + +class Ubicacion(BaseModel): + """Ubicación de origen o destino de la mercancía.""" + tipo_ubicacion: Optional[str] = Field(default=None, alias="tipoUbicacion") + id_ubicacion: Optional[str] = Field(default=None, alias="idUbicacion") + rfc_remitente_destinatario: Optional[str] = Field(default=None, alias="rfcRemitenteDestinatario") + num_reg_id_trib: Optional[str] = Field(default=None, alias="numRegIdTrib") + residencia_fiscal_id: Optional[str] = Field(default=None, alias="residenciaFiscalId") + nombre_remitente_destinatario: Optional[str] = Field(default=None, alias="nombreRemitenteDestinatario") + num_estacion_id: Optional[str] = Field(default=None, alias="numEstacionId") + nombre_estacion: Optional[str] = Field(default=None, alias="nombreEstacion") + navegacion_trafico_id: Optional[str] = Field(default=None, alias="navegacionTraficoId") + tipo_estacion_id: Optional[str] = Field(default=None, alias="tipoEstacionId") + fecha_hora_salida_llegada: Optional[str] = Field(default=None, alias="fechaHoraSalidaLlegada") + distancia_recorrida: Optional[Decimal] = Field(default=None, alias="distanciaRecorrida") + domicilio: Optional[Domicilio] = Field(default=None, alias="domicilio") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +# ===== Mercancia ===== + +class DocumentoAduanero(BaseModel): + """Documento aduanero asociado a una mercancía.""" + tipo_documento_id: Optional[str] = Field(default=None, alias="tipoDocumentoId") + num_pedimento: Optional[str] = Field(default=None, alias="numPedimento") + rfc_impo: Optional[str] = Field(default=None, alias="rfcImpo") + + model_config = ConfigDict(populate_by_name=True) + + +class CantidadTransporta(BaseModel): + """Cantidad transportada entre ubicaciones.""" + cantidad: Decimal = Field(default=..., alias="cantidad") + id_origen: Optional[str] = Field(default=None, alias="idOrigen") + id_destino: Optional[str] = Field(default=None, alias="idDestino") + cves_transporte_id: Optional[str] = Field(default=None, alias="cvesTransporteId") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +class DetalleMercancia(BaseModel): + """Detalle adicional de la mercancía transportada.""" + unidad_peso_merc_id: Optional[str] = Field(default=None, alias="unidadPesoMercId") + peso_bruto: Decimal = Field(default=..., alias="pesoBruto") + peso_neto: Decimal = Field(default=..., alias="pesoNeto") + peso_tara: Decimal = Field(default=..., alias="pesoTara") + num_piezas: Optional[int] = Field(default=None, alias="numPiezas") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +class Mercancia(BaseModel): + """Mercancía transportada en la carta porte.""" + bienes_transp_id: Optional[str] = Field(default=None, alias="bienesTranspId") + descripcion: Optional[str] = Field(default=None, alias="descripcion") + cantidad: Decimal = Field(default=..., alias="cantidad") + clave_unidad_id: Optional[str] = Field(default=None, alias="claveUnidadId") + material_peligroso_id: Optional[str] = Field(default=None, alias="materialPeligrosoId") + denominacion_generica_prod: Optional[str] = Field(default=None, alias="denominacionGenericaProd") + denominacion_distintiva_prod: Optional[str] = Field(default=None, alias="denominacionDistintivaProd") + fabricante: Optional[str] = Field(default=None, alias="fabricante") + fecha_caducidad: Optional[str] = Field(default=None, alias="fechaCaducidad") + lote_medicamento: Optional[str] = Field(default=None, alias="loteMedicamento") + forma_farmaceutica_id: Optional[str] = Field(default=None, alias="formaFarmaceuticaId") + condiciones_esp_transp_id: Optional[str] = Field(default=None, alias="condicionesEspTranspId") + registro_sanitario_folio_autorizacion: Optional[str] = Field(default=None, alias="registroSanitarioFolioAutorizacion") + peso_en_kg: Decimal = Field(default=..., alias="pesoEnKg") + fraccion_arancelaria_id: Optional[str] = Field(default=None, alias="fraccionArancelariaId") + tipo_materia_id: Optional[str] = Field(default=None, alias="tipoMateriaId") + descripcion_materia: Optional[str] = Field(default=None, alias="descripcionMateria") + valor_mercancia: Optional[Decimal] = Field(default=None, alias="valorMercancia") + moneda_id: Optional[str] = Field(default=None, alias="monedaId") + documentacion_aduanera: Optional[list[DocumentoAduanero]] = Field(default=None, alias="documentacionAduanera") + cantidad_transporta: Optional[list[CantidadTransporta]] = Field(default=None, alias="cantidadTransporta") + detalle_mercancia: Optional[DetalleMercancia] = Field(default=None, alias="detalleMercancia") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +# ===== Autotransporte ===== + +class Remolque(BaseModel): + """Remolque del autotransporte.""" + sub_tipo_rem_id: Optional[str] = Field(default=None, alias="subTipoRemId") + placa: Optional[str] = Field(default=None, alias="placa") + + model_config = ConfigDict(populate_by_name=True) + + +class Autotransporte(BaseModel): + """Datos del autotransporte federal.""" + perm_sct_id: Optional[str] = Field(default=None, alias="permSCTId") + num_permiso_sct: Optional[str] = Field(default=None, alias="numPermisoSCT") + config_vehicular_id: Optional[str] = Field(default=None, alias="configVehicularId") + peso_bruto_vehicular: Decimal = Field(default=..., alias="pesoBrutoVehicular") + placa_vm: Optional[str] = Field(default=None, alias="placaVM") + anio_modelo_vm: int = Field(default=..., alias="anioModeloVM") + asegura_resp_civil: Optional[str] = Field(default=None, alias="aseguraRespCivil") + poliza_resp_civil: Optional[str] = Field(default=None, alias="polizaRespCivil") + remolques: Optional[list[Remolque]] = Field(default=None, alias="remolques") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +# ===== Transporte Maritimo ===== + +class RemolqueCCP(BaseModel): + """Remolque del contenedor marítimo.""" + sub_tipo_rem_ccp_id: Optional[str] = Field(default=None, alias="subTipoRemCCPId") + placa_ccp: Optional[str] = Field(default=None, alias="placaCCP") + + model_config = ConfigDict(populate_by_name=True) + + +class ContenedorMaritimo(BaseModel): + """Contenedor para transporte marítimo.""" + matricula_contenedor: Optional[str] = Field(default=None, alias="matriculaContenedor") + tipo_contenedor_id: Optional[str] = Field(default=None, alias="tipoContenedorId") + num_precinto: Optional[str] = Field(default=None, alias="numPrecinto") + peso_contenedor_vacio: Optional[Decimal] = Field(default=None, alias="pesoContenedorVacio") + peso_neto_mercancia: Optional[Decimal] = Field(default=None, alias="pesoNetoMercancia") + id_ccp_relacionado: Optional[str] = Field(default=None, alias="idCCPRelacionado") + placa_vm_ccp: Optional[str] = Field(default=None, alias="placaVMCCP") + fecha_certificacion_ccp: Optional[str] = Field(default=None, alias="fechaCertificacionCCP") + remolques_ccp: Optional[list[RemolqueCCP]] = Field(default=None, alias="remolquesCCP") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +class TransporteMaritimo(BaseModel): + """Datos del transporte marítimo.""" + perm_sct_id: Optional[str] = Field(default=None, alias="permSCTId") + num_permiso_sct: Optional[str] = Field(default=None, alias="numPermisoSCT") + config_maritima_id: Optional[str] = Field(default=None, alias="configMaritimaId") + nombre_aseg: Optional[str] = Field(default=None, alias="nombreAseg") + num_poliza_seguro: Optional[str] = Field(default=None, alias="numPolizaSeguro") + tipo_embarcacion_id: Optional[str] = Field(default=None, alias="tipoEmbarcacionId") + matricula: Optional[str] = Field(default=None, alias="matricula") + numero_omi: Optional[str] = Field(default=None, alias="numeroOMI") + anio_embarcacion: Optional[int] = Field(default=None, alias="anioEmbarcacion") + nombre_embarc: Optional[str] = Field(default=None, alias="nombreEmbarc") + nacionalidad_embarc_id: Optional[str] = Field(default=None, alias="nacionalidadEmbarcId") + unidades_de_arq_bruto: Optional[Decimal] = Field(default=None, alias="unidadesDeArqBruto") + tipo_carga_id: Optional[str] = Field(default=None, alias="tipoCargaId") + eslora: Optional[Decimal] = Field(default=None, alias="eslora") + manga: Optional[Decimal] = Field(default=None, alias="manga") + calado: Optional[Decimal] = Field(default=None, alias="calado") + puntal: Optional[Decimal] = Field(default=None, alias="puntal") + linea_naviera: Optional[str] = Field(default=None, alias="lineaNaviera") + nombre_agente_naviero: Optional[str] = Field(default=None, alias="nombreAgenteNaviero") + num_cert_itc: Optional[str] = Field(default=None, alias="numCertITC") + nombre_embar_cargador: Optional[str] = Field(default=None, alias="nombreEmbarCargador") + nombre_agente: Optional[str] = Field(default=None, alias="nombreAgente") + num_autorizacion_naviero_id: Optional[str] = Field(default=None, alias="numAutorizacionNavieroId") + num_viaje: Optional[str] = Field(default=None, alias="numViaje") + num_conoc_embarc: Optional[str] = Field(default=None, alias="numConocEmbarc") + permiso_temp_navegacion: Optional[str] = Field(default=None, alias="permisoTempNavegacion") + contenedores: Optional[list[ContenedorMaritimo]] = Field(default=None, alias="contenedores") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +# ===== Transporte Aereo ===== + +class TransporteAereo(BaseModel): + """Datos del transporte aéreo.""" + perm_sct_id: Optional[str] = Field(default=None, alias="permSCTId") + num_permiso_sct: Optional[str] = Field(default=None, alias="numPermisoSCT") + matricula_aeronave: Optional[str] = Field(default=None, alias="matriculaAeronave") + nombre_aseg: Optional[str] = Field(default=None, alias="nombreAseg") + num_poliza_seguro: Optional[str] = Field(default=None, alias="numPolizaSeguro") + numero_guia: Optional[str] = Field(default=None, alias="numeroGuia") + lugar_contrato: Optional[str] = Field(default=None, alias="lugarContrato") + codigo_transportista_id: Optional[str] = Field(default=None, alias="codigoTransportistaId") + rfc_embarcador: Optional[str] = Field(default=None, alias="rfcEmbarcador") + nombre_embarcador: Optional[str] = Field(default=None, alias="nombreEmbarcador") + rfc_transportista: Optional[str] = Field(default=None, alias="rfcTransportista") + + model_config = ConfigDict(populate_by_name=True) + + +# ===== Transporte Ferroviario ===== + +class DerechoDePaso(BaseModel): + """Derecho de paso del transporte ferroviario.""" + tipo_derecho_de_paso_id: Optional[str] = Field(default=None, alias="tipoDerechoDePasoId") + kilometraje_pagado: Decimal = Field(default=..., alias="kilometrajePagado") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +class ContenedorFerroviario(BaseModel): + """Contenedor para transporte ferroviario.""" + tipo_contenedor_id: Optional[str] = Field(default=None, alias="tipoContenedorId") + peso_contenedor_vacio: Optional[Decimal] = Field(default=None, alias="pesoContenedorVacio") + peso_neto_mercancia: Optional[Decimal] = Field(default=None, alias="pesoNetoMercancia") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +class Carro(BaseModel): + """Carro del transporte ferroviario.""" + tipo_carro_id: Optional[str] = Field(default=None, alias="tipoCarroId") + matricula_carro: Optional[str] = Field(default=None, alias="matriculaCarro") + guia_carro: Optional[str] = Field(default=None, alias="guiaCarro") + toneladas_netas_carro: Decimal = Field(default=..., alias="toneladasNetasCarro") + contenedores: Optional[list[ContenedorFerroviario]] = Field(default=None, alias="contenedores") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) + + +class TransporteFerroviario(BaseModel): + """Datos del transporte ferroviario.""" + tipo_de_servicio_id: Optional[str] = Field(default=None, alias="tipoDeServicioId") + tipo_de_trafico_id: Optional[str] = Field(default=None, alias="tipoDeTraficoId") + nombre_aseg: Optional[str] = Field(default=None, alias="nombreAseg") + num_poliza_seguro: Optional[str] = Field(default=None, alias="numPolizaSeguro") + derechos_de_paso: Optional[list[DerechoDePaso]] = Field(default=None, alias="derechosDePaso") + carros: Optional[list[Carro]] = Field(default=None, alias="carros") + + model_config = ConfigDict(populate_by_name=True) + + +# ===== Tipo Figura ===== + +class ParteTransporte(BaseModel): + """Parte de transporte asociada a una figura.""" + parte_transporte_id: Optional[str] = Field(default=None, alias="parteTransporteId") + + model_config = ConfigDict(populate_by_name=True) + + +class TipoFigura(BaseModel): + """Figura de transporte (operador, propietario, arrendatario, notificado).""" + tipo_figura_id: Optional[str] = Field(default=None, alias="tipoFiguraId") + rfc_figura: Optional[str] = Field(default=None, alias="rfcFigura") + num_licencia: Optional[str] = Field(default=None, alias="numLicencia") + nombre_figura: Optional[str] = Field(default=None, alias="nombreFigura") + partes_transporte: Optional[list[ParteTransporte]] = Field(default=None, alias="partesTransporte") + domicilio: Optional[Domicilio] = Field(default=None, alias="domicilio") + + model_config = ConfigDict(populate_by_name=True) + + +# ===== Carta Porte ===== + +class LadingComplement(BaseModel): + """Complemento Carta Porte para transporte de mercancías.""" + transp_internac_id: Optional[str] = Field(default=None, alias="transpInternacId") + entrada_salida_merc_id: Optional[str] = Field(default=None, alias="entradaSalidaMercId") + pais_origen_destino_id: Optional[str] = Field(default=None, alias="paisOrigenDestinoId") + via_entrada_salida_id: Optional[str] = Field(default=None, alias="viaEntradaSalidaId") + total_dist_rec: Optional[Decimal] = Field(default=None, alias="totalDistRec") + peso_neto_total: Optional[Decimal] = Field(default=None, alias="pesoNetoTotal") + registro_istmo_id: Optional[str] = Field(default=None, alias="registroISTMOId") + ubicacion_polo_origen_id: Optional[str] = Field(default=None, alias="ubicacionPoloOrigenId") + ubicacion_polo_destino_id: Optional[str] = Field(default=None, alias="ubicacionPoloDestinoId") + unidad_peso_id: Optional[str] = Field(default=None, alias="unidadPesoId") + logistica_inversa_recoleccion_devolucion_id: Optional[str] = Field(default=None, alias="logisticaInversaRecoleccionDevolucionId") + regimen_aduaneros: Optional[list[RegimenAduanero]] = Field(default=None, alias="regimenAduaneros") + ubicaciones: Optional[list[Ubicacion]] = Field(default=None, alias="ubicaciones") + mercancias: Optional[list[Mercancia]] = Field(default=None, alias="mercancias") + autotransporte: Optional[Autotransporte] = Field(default=None, alias="autotransporte") + transporte_maritimo: Optional[TransporteMaritimo] = Field(default=None, alias="transporteMaritimo") + transporte_aereo: Optional[TransporteAereo] = Field(default=None, alias="transporteAereo") + transporte_ferroviario: Optional[TransporteFerroviario] = Field(default=None, alias="transporteFerroviario") + tipos_figura: Optional[list[TipoFigura]] = Field(default=None, alias="tiposFigura") + + model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) diff --git a/fiscalapi/models/fiscalapi_models.py b/fiscalapi/models/fiscalapi_models.py index 9ce1776..03a1d66 100644 --- a/fiscalapi/models/fiscalapi_models.py +++ b/fiscalapi/models/fiscalapi_models.py @@ -1,6 +1,7 @@ from decimal import Decimal from pydantic import BaseModel, ConfigDict, EmailStr, Field from fiscalapi.models.common_models import BaseDto, CatalogDto +from fiscalapi.models.bill_of_lading_models import LadingComplement from typing import Literal, Optional from datetime import datetime @@ -521,19 +522,13 @@ class PayrollComplement(BaseDto): model_config = ConfigDict(populate_by_name=True, json_encoders={Decimal: str}) -class LadingComplement(BaseDto): - """Modelo para el complemento de carta porte.""" - # Placeholder for carta porte fields - to be expanded as needed - - model_config = ConfigDict(populate_by_name=True) - class InvoiceComplement(BaseDto): """Modelo contenedor de complementos de factura.""" local_taxes: Optional[LocalTaxesComplement] = Field(default=None, alias="localTaxes", description="Complemento de impuestos locales.") payment: Optional[PaymentComplement] = Field(default=None, alias="payment", description="Complemento de pago.") payroll: Optional[PayrollComplement] = Field(default=None, alias="payroll", description="Complemento de nómina.") - lading: Optional[LadingComplement] = Field(default=None, alias="lading", description="Complemento de carta porte.") + lading: Optional[LadingComplement] = Field(default=None, alias="cartaPorte", description="Complemento Carta Porte.") model_config = ConfigDict(populate_by_name=True) diff --git a/setup.py b/setup.py index e32dff1..78b3c6b 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ import os from setuptools import setup, find_packages -VERSION = "4.0.360" +VERSION = "4.0.372" DESCRIPTION = "Genera facturas CFDI válidas ante el SAT consumiendo el API de https://www.fiscalapi.com"