From 787c7bc538a9a851e64028ef5bb13d9d579df1ae Mon Sep 17 00:00:00 2001 From: SatCFDI Date: Sat, 30 Mar 2024 23:06:46 -0600 Subject: [PATCH] Updated Catalogs --- satcfdi/catalogs/catalogs.db | Bin 45793280 -> 45793280 bytes satcfdi/create/cfd/catalogos.py | 6 +- satcfdi/create/cfd/cce20.py | 249 ++++++++++++++++++ satcfdi/transform/objectify.py | 185 +++++++++++-- satcfdi/transform/schemas.py | 12 +- .../cadenaoriginal_4_0.xslt | 2 +- .../ComercioExterior20/ComercioExterior20.xsd | 1 + .../ComercioExterior20.xslt | 1 + .../catalogos/CartaPorte/catCartaPorte.xsd | 2 +- .../sitio_internet/cfd/catalogos/catCFDI.xsd | 2 +- satcfdi/transform/xmlify.py | 193 ++++++++++++-- 11 files changed, 610 insertions(+), 43 deletions(-) create mode 100644 satcfdi/create/cfd/cce20.py create mode 100644 satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xsd create mode 100644 satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xslt diff --git a/satcfdi/catalogs/catalogs.db b/satcfdi/catalogs/catalogs.db index a24bbd5478fcf0751d45c524ef2e27b3efaaf781..eabc8568a1603972d51adb95176d6d61a677b47d 100644 GIT binary patch delta 71128 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 MmRY~&j2<8JzfmC{8UO$Q delta 67012 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 Q`8eJy#ujWoZbYv8-`ogt#Q*>R diff --git a/satcfdi/create/cfd/catalogos.py b/satcfdi/create/cfd/catalogos.py index a99074b..05a9dd7 100644 --- a/satcfdi/create/cfd/catalogos.py +++ b/satcfdi/create/cfd/catalogos.py @@ -135,6 +135,7 @@ class ObjetoImp(StrEnum): SI_OBJETO_DE_IMPUESTO = '02' SI_OBJETO_DEL_IMPUESTO_Y_NO_OBLIGADO_AL_DESGLOSE = '03' SI_OBJETO_DEL_IMPUESTO_Y_NO_CAUSA_IMPUESTO = '04' + SI_OBJETO_DEL_IMPUESTO_IVA_CREDITO_PODEBI = '05' class Banco(StrEnum): @@ -155,7 +156,7 @@ class Banco(StrEnum): INVEX = '059' BANSI = '060' AFIRME = '062' - BANORTE_IXE = '072' + BANORTE = '072' THE_ROYAL_BANK = '102' AMERICAN_EXPRESS = '103' BAMSA = '106' @@ -175,7 +176,7 @@ class Banco(StrEnum): ACTINVER = '133' WAL_MART = '134' NAFIN = '135' - INTERCAM_BANCO = '136' + INTERBANCO = '136' BANCOPPEL = '137' ABC_CAPITAL = '138' UBS_BANK = '139' @@ -244,5 +245,6 @@ class Banco(StrEnum): LIBERTAD = '670' CLS = '901' INDEVAL = '902' + NA = '999' diff --git a/satcfdi/create/cfd/cce20.py b/satcfdi/create/cfd/cce20.py new file mode 100644 index 0000000..b108c21 --- /dev/null +++ b/satcfdi/create/cfd/cce20.py @@ -0,0 +1,249 @@ +"""cce20 http://www.sat.gob.mx/ComercioExterior20""" +from decimal import Decimal +from datetime import datetime, date, time +from collections.abc import Sequence +from ...cfdi import CFDI +from ...xelement import XElement +from ...utils import ScalarMap + + +class Domicilio(ScalarMap): + """ + Nodo requerido para expresar el domicilio del destinatario de la mercancía. + + :param calle: Atributo requerido que sirve para precisar la calle en que está ubicado el domicilio del destinatario de la mercancía. + :param estado: Atributo requerido para señalar el estado, entidad, región, comunidad u otra figura análoga en donde se encuentra ubicado el domicilio del destinatario de la mercancía. El catálogo se publica en el Portal del SAT en internet y es conforme con la especificación ISO 3166-2. + :param pais: Atributo requerido que sirve para precisar la clave del país donde se encuentra ubicado el destinatario de la mercancía, conforme con el catálogo c_Pais publicado en el Portal del SAT en internet que está basado en la especificación ISO 3166-1. + :param codigo_postal: Atributo requerido que sirve para registrar el código postal en donde se encuentra ubicado el domicilio del destinatario de la mercancía. + :param numero_exterior: Atributo opcional que sirve para expresar el número exterior en donde se ubica el domicilio del destinatario de la mercancía. + :param numero_interior: Atributo opcional que sirve para expresar el número interior, en caso de existir, en donde se ubica el domicilio del destinatario de la mercancía. + :param colonia: Atributo opcional que sirve para expresar la colonia o dato análogo en donde se ubica el domicilio del destinatario de la mercancía. + :param localidad: Atributo opcional que sirve para precisar la ciudad, población, distrito u otro análogo en donde se ubica el domicilio del destinatario de la mercancía. + :param referencia: Atributo opcional para registrar una referencia geográfica adicional que permita una fácil o precisa ubicación del domicilio del destinatario de la mercancía, por ejemplo las coordenadas GPS. + :param municipio: Atributo opcional que sirve para precisar el municipio, delegación o alcaldía, condado o dato análogo en donde se encuentra ubicado el destinatario de la mercancía. + """ + + def __init__( + self, + calle: str, + estado: str, + pais: str, + codigo_postal: str, + numero_exterior: str = None, + numero_interior: str = None, + colonia: str = None, + localidad: str = None, + referencia: str = None, + municipio: str = None, + ): + super().__init__({ + 'Calle': calle, + 'Estado': estado, + 'Pais': pais, + 'CodigoPostal': codigo_postal, + 'NumeroExterior': numero_exterior, + 'NumeroInterior': numero_interior, + 'Colonia': colonia, + 'Localidad': localidad, + 'Referencia': referencia, + 'Municipio': municipio, + }) + + +class Destinatario(ScalarMap): + """ + Nodo opcional para capturar los datos del destinatario de la mercancía cuando éste sea distinto del receptor del CFDI. + + :param domicilio: Nodo requerido para expresar el domicilio del destinatario de la mercancía. + :param num_reg_id_trib: Atributo opcional para incorporar el número de identificación o registro fiscal del país de residencia para efectos fiscales del destinatario de la mercancía exportada. + :param nombre: Atributo opcional para expresar el nombre completo, denominación o razón social del destinatario de la mercancía exportada. + """ + + def __init__( + self, + domicilio: Domicilio | dict | Sequence[Domicilio | dict], + num_reg_id_trib: str = None, + nombre: str = None, + ): + super().__init__({ + 'Domicilio': domicilio, + 'NumRegIdTrib': num_reg_id_trib, + 'Nombre': nombre, + }) + + +class Receptor(ScalarMap): + """ + Nodo condicional para capturar los datos complementarios del receptor del CFDI. + + :param num_reg_id_trib: Atributo condicional para incorporar el número de identificación o registro fiscal del país de residencia para efectos fiscales del receptor del CFDI. + :param domicilio: Nodo requerido para expresar el domicilio del receptor del comprobante. + """ + + def __init__( + self, + num_reg_id_trib: str = None, + domicilio: Domicilio | dict = None, + ): + super().__init__({ + 'NumRegIdTrib': num_reg_id_trib, + 'Domicilio': domicilio, + }) + + +class Propietario(ScalarMap): + """ + Nodo condicional para capturar los datos del o los propietarios de la mercancía que se traslada y ésta no sea objeto de enajenación o siéndolo sea a título gratuito, cuando el emisor del CFDI es un tercero. + + :param num_reg_id_trib: Atributo requerido para incorporar el número de identificación o registro fiscal del país de residencia para efectos fiscales del propietario de la mercancía trasladada. + :param residencia_fiscal: Atributo requerido para registrar la clave del país de residencia para efectos fiscales del propietario de la mercancía, conforme con el catálogo c_Pais publicado en el Portal del SAT en internet que está basado en la especificación ISO 3166-1. + """ + + def __init__( + self, + num_reg_id_trib: str, + residencia_fiscal: str, + ): + super().__init__({ + 'NumRegIdTrib': num_reg_id_trib, + 'ResidenciaFiscal': residencia_fiscal, + }) + + +class Emisor(ScalarMap): + """ + Nodo opcional para capturar los datos complementarios del emisor del comprobante. + + :param domicilio: Nodo requerido para expresar el domicilio del emisor del comprobante. + :param curp: Atributo condicional para expresar la CURP del emisor del CFDI cuando es una persona física. + """ + + def __init__( + self, + domicilio: Domicilio | dict, + curp: str = None, + ): + super().__init__({ + 'Domicilio': domicilio, + 'Curp': curp, + }) + + +class DescripcionesEspecificas(ScalarMap): + """ + Nodo opcional que indica la lista de descripciones específicas de la mercancía. Una mercancía puede tener más de una descripción específica. + + :param marca: Atributo requerido que indica la marca de la mercancía. + :param modelo: Atributo opcional que indica el modelo de la mercancía. + :param sub_modelo: Atributo opcional que indica el submodelo de la mercancía. + :param numero_serie: Atributo opcional que indica el número de serie de la mercancía. + """ + + def __init__( + self, + marca: str, + modelo: str = None, + sub_modelo: str = None, + numero_serie: str = None, + ): + super().__init__({ + 'Marca': marca, + 'Modelo': modelo, + 'SubModelo': sub_modelo, + 'NumeroSerie': numero_serie, + }) + + +class Mercancia(ScalarMap): + """ + Nodo requerido para capturar la información de la declaración de cada mercancía exportada. + + :param no_identificacion: Atributo requerido que sirve para expresar el número de parte, la clave de identificación que asigna la empresa o el número de serie de la mercancía exportada. + :param valor_dolares: Atributo requerido que indica el valor total en dólares de Estados Unidos de América (USD). + :param fraccion_arancelaria: Atributo condicional que sirve para expresar la clave de la fracción arancelaria correspondiente a la descripción de la mercancía exportada. Debe ser conforme al catálogo c_FraccionArancelaria publicado en el Portal del SAT en internet. + :param cantidad_aduana: Atributo opcional para precisar la cantidad de bienes en la aduana conforme a la UnidadAduana cuando en el nodo Comprobante:Conceptos:Concepto se hubiera registrado información comercial. + :param unidad_aduana: Atributo condicional para precisar la clave de la unidad de medida aplicable para la cantidad expresada en la mercancía en la aduana, conforme al catálogo c_UnidadAduana publicado en el Portal del SAT en internet. + :param valor_unitario_aduana: Atributo condicional para precisar el valor o precio unitario del bien en la aduana. Se expresa en dólares de Estados Unidos de América (USD), el cual puede estar registrado hasta con 6 decimales. + :param descripciones_especificas: Nodo opcional que indica la lista de descripciones específicas de la mercancía. Una mercancía puede tener más de una descripción específica. + """ + + def __init__( + self, + no_identificacion: str, + valor_dolares: Decimal | int, + fraccion_arancelaria: str = None, + cantidad_aduana: Decimal | int = None, + unidad_aduana: str = None, + valor_unitario_aduana: Decimal | int = None, + descripciones_especificas: DescripcionesEspecificas | dict | Sequence[DescripcionesEspecificas | dict] = None, + ): + super().__init__({ + 'NoIdentificacion': no_identificacion, + 'ValorDolares': valor_dolares, + 'FraccionArancelaria': fraccion_arancelaria, + 'CantidadAduana': cantidad_aduana, + 'UnidadAduana': unidad_aduana, + 'ValorUnitarioAduana': valor_unitario_aduana, + 'DescripcionesEspecificas': descripciones_especificas, + }) + + +class ComercioExterior(CFDI): + """ + Complemento para incorporar la información en caso de exportación definitiva de mercancías. + + :param clave_de_pedimento: Atributo requerido que indica la clave de pedimento que se haya declarado conforme al catálogo c_ClavePedimento publicado en el Portal del SAT en internet. + :param certificado_origen: Atributo requerido para indicar la excepción de certificados de Origen de los Tratados de Libre Comercio que ha celebrado México con diversos países. 0 = No Funge como certificado de origen 1 = Funge como certificado de origen. + :param tipo_cambio_usd: Atributo requerido que indica el número de pesos mexicanos que equivalen a un dólar de Estados Unidos de América, de acuerdo con el artículo 20 del Código Fiscal de la Federación. + :param total_usd: Atributo requerido que indica el importe total del comprobante en dólares de Estados Unidos de América. + :param mercancias: Nodo requerido para capturar la información de la declaración de las mercancías exportadas. + :param motivo_traslado: Atributo condicional que indica la clave del motivo por el cual en la exportación definitiva de mercancías con clave de pedimento A1, éstas no son objeto de enajenación o siéndolo sean a título gratuito, desde el domicilio del emisor hacia el domicilio del receptor o del destinatario. La clave del motivo es conforme con el catálogo c_MotivoTraslado publicado en el Portal del SAT en internet. + :param num_certificado_origen: Atributo condicional para expresar el folio del certificado de origen o el folio fiscal del CFDI con el que se pagó la expedición del certificado de origen. + :param numero_exportador_confiable: Atributo condicional que indica el número de exportador confiable, conforme al artículo 22 del Anexo 1 del Tratado de Libre Comercio con la Asociación Europea y a la Decisión de la Comunidad Europea. + :param incoterm: Atributo condicional que indica la clave del INCOTERM aplicable a la factura, conforme al catálogo c_INCOTERM publicado en el Portal del SAT en internet. + :param observaciones: Atributo opcional para ingresar información adicional, como alguna leyenda que se considere incluir en el CFDI. + :param emisor: Nodo opcional para capturar los datos complementarios del emisor del comprobante. + :param propietario: Nodo condicional para capturar los datos del o los propietarios de la mercancía que se traslada y ésta no sea objeto de enajenación o siéndolo sea a título gratuito, cuando el emisor del CFDI es un tercero. + :param receptor: Nodo condicional para capturar los datos complementarios del receptor del CFDI. + :param destinatario: Nodo opcional para capturar los datos del destinatario de la mercancía cuando éste sea distinto del receptor del CFDI. + """ + + tag = '{http://www.sat.gob.mx/ComercioExterior20}ComercioExterior' + version = '2.0' + + def __init__( + self, + clave_de_pedimento: str, + certificado_origen: int, + tipo_cambio_usd: Decimal | int, + total_usd: Decimal | int, + mercancias: Mercancia | dict | Sequence[Mercancia | dict], + motivo_traslado: str = None, + num_certificado_origen: str = None, + numero_exportador_confiable: str = None, + incoterm: str = None, + observaciones: str = None, + emisor: Emisor | dict = None, + propietario: Propietario | dict | Sequence[Propietario | dict] = None, + receptor: Receptor | dict = None, + destinatario: Destinatario | dict | Sequence[Destinatario | dict] = None, + ): + super().__init__({ + 'Version': self.version, + 'ClaveDePedimento': clave_de_pedimento, + 'CertificadoOrigen': certificado_origen, + 'TipoCambioUSD': tipo_cambio_usd, + 'TotalUSD': total_usd, + 'Mercancias': mercancias, + 'MotivoTraslado': motivo_traslado, + 'NumCertificadoOrigen': num_certificado_origen, + 'NumeroExportadorConfiable': numero_exportador_confiable, + 'Incoterm': incoterm, + 'Observaciones': observaciones, + 'Emisor': emisor, + 'Propietario': propietario, + 'Receptor': receptor, + 'Destinatario': destinatario, + }) + + diff --git a/satcfdi/transform/objectify.py b/satcfdi/transform/objectify.py index 49170be..0251418 100644 --- a/satcfdi/transform/objectify.py +++ b/satcfdi/transform/objectify.py @@ -11943,17 +11943,161 @@ def descripciones_especificas0(cls, node): def comercio_exterior1(cls, node): self = cls() self.tag = node.tag - el = node.find('{http://www.sat.gob.mx/ComercioExterior}Emisor') + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}Emisor') if el is not None: self['Emisor'] = emisor7(cls, el) + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}Propietario') + if el is not None: + self['Propietario'] = [propietario2(cls, n) for n in node.iterfind('{http://www.sat.gob.mx/ComercioExterior20}Propietario')] + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}Receptor') + if el is not None: + self['Receptor'] = receptor7(cls, el) + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}Destinatario') + if el is not None: + self['Destinatario'] = [destinatario2(cls, n) for n in node.iterfind('{http://www.sat.gob.mx/ComercioExterior20}Destinatario')] + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}Mercancias') + self['Mercancias'] = [mercancia4(cls, n) for n in el.iterfind('{http://www.sat.gob.mx/ComercioExterior20}Mercancia')] + self['Version'] = node.attrib['Version'] + if (a := node.attrib.get('MotivoTraslado')) is not None: + self['MotivoTraslado'] = catalog_code('C5bc_c_MotivoTraslado', a) + self['ClaveDePedimento'] = catalog_code('C5bc_c_ClavePedimento', node.attrib['ClaveDePedimento']) + self['CertificadoOrigen'] = Xint(node.attrib['CertificadoOrigen']) + if (a := node.attrib.get('NumCertificadoOrigen')) is not None: + self['NumCertificadoOrigen'] = a + if (a := node.attrib.get('NumeroExportadorConfiable')) is not None: + self['NumeroExportadorConfiable'] = a + if (a := node.attrib.get('Incoterm')) is not None: + self['Incoterm'] = catalog_code('C5bc_c_INCOTERM', a) + if (a := node.attrib.get('Observaciones')) is not None: + self['Observaciones'] = a + self['TipoCambioUSD'] = Decimal(node.attrib['TipoCambioUSD']) + self['TotalUSD'] = Decimal(node.attrib['TotalUSD']) + return self +def emisor7(cls, node): + self = ScalarMap() + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}Domicilio') + self['Domicilio'] = domicilioc(cls, el) + if (a := node.attrib.get('Curp')) is not None: + self['Curp'] = a + return self +def domicilioc(cls, node): + self = ScalarMap() + self['Calle'] = node.attrib['Calle'] + if (a := node.attrib.get('NumeroExterior')) is not None: + self['NumeroExterior'] = a + if (a := node.attrib.get('NumeroInterior')) is not None: + self['NumeroInterior'] = a + if (a := node.attrib.get('Colonia')) is not None: + self['Colonia'] = catalog_code('C756_c_Colonia', (a, node.attrib['CodigoPostal'])) + if (a := node.attrib.get('Localidad')) is not None: + self['Localidad'] = catalog_code('C756_c_Localidad', (a, node.attrib['Estado'])) + if (a := node.attrib.get('Referencia')) is not None: + self['Referencia'] = a + if (a := node.attrib.get('Municipio')) is not None: + self['Municipio'] = catalog_code('C756_c_Municipio', (a, node.attrib['Estado'])) + self['Estado'] = catalog_code('C756_c_Estado', node.attrib['Estado'], 1) + self['Pais'] = catalog_code('C756_c_Pais', node.attrib['Pais']) + self['CodigoPostal'] = node.attrib['CodigoPostal'] + return self +def propietario2(cls, node): + self = ScalarMap() + self['NumRegIdTrib'] = node.attrib['NumRegIdTrib'] + self['ResidenciaFiscal'] = catalog_code('C756_c_Pais', node.attrib['ResidenciaFiscal']) + return self +def receptor7(cls, node): + self = ScalarMap() + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}Domicilio') + if el is not None: + self['Domicilio'] = domiciliod(cls, el) + if (a := node.attrib.get('NumRegIdTrib')) is not None: + self['NumRegIdTrib'] = a + return self +def domiciliod(cls, node): + self = ScalarMap() + self['Calle'] = node.attrib['Calle'] + if (a := node.attrib.get('NumeroExterior')) is not None: + self['NumeroExterior'] = a + if (a := node.attrib.get('NumeroInterior')) is not None: + self['NumeroInterior'] = a + if (a := node.attrib.get('Colonia')) is not None: + self['Colonia'] = a + if (a := node.attrib.get('Localidad')) is not None: + self['Localidad'] = a + if (a := node.attrib.get('Referencia')) is not None: + self['Referencia'] = a + if (a := node.attrib.get('Municipio')) is not None: + self['Municipio'] = a + self['Estado'] = node.attrib['Estado'] + self['Pais'] = catalog_code('C756_c_Pais', node.attrib['Pais']) + self['CodigoPostal'] = node.attrib['CodigoPostal'] + return self +def destinatario2(cls, node): + self = ScalarMap() + self['Domicilio'] = [domicilioe(cls, n) for n in node.iterfind('{http://www.sat.gob.mx/ComercioExterior20}Domicilio')] + if (a := node.attrib.get('NumRegIdTrib')) is not None: + self['NumRegIdTrib'] = a + if (a := node.attrib.get('Nombre')) is not None: + self['Nombre'] = a + return self +def domicilioe(cls, node): + self = ScalarMap() + self['Calle'] = node.attrib['Calle'] + if (a := node.attrib.get('NumeroExterior')) is not None: + self['NumeroExterior'] = a + if (a := node.attrib.get('NumeroInterior')) is not None: + self['NumeroInterior'] = a + if (a := node.attrib.get('Colonia')) is not None: + self['Colonia'] = a + if (a := node.attrib.get('Localidad')) is not None: + self['Localidad'] = a + if (a := node.attrib.get('Referencia')) is not None: + self['Referencia'] = a + if (a := node.attrib.get('Municipio')) is not None: + self['Municipio'] = a + self['Estado'] = node.attrib['Estado'] + self['Pais'] = catalog_code('C756_c_Pais', node.attrib['Pais']) + self['CodigoPostal'] = node.attrib['CodigoPostal'] + return self +def mercancia4(cls, node): + self = ScalarMap() + el = node.find('{http://www.sat.gob.mx/ComercioExterior20}DescripcionesEspecificas') + if el is not None: + self['DescripcionesEspecificas'] = [descripciones_especificas1(cls, n) for n in node.iterfind('{http://www.sat.gob.mx/ComercioExterior20}DescripcionesEspecificas')] + self['NoIdentificacion'] = node.attrib['NoIdentificacion'] + if (a := node.attrib.get('FraccionArancelaria')) is not None: + self['FraccionArancelaria'] = catalog_code('C5bc_c_FraccionArancelaria', a) + if (a := node.attrib.get('CantidadAduana')) is not None: + self['CantidadAduana'] = Decimal(a) + if (a := node.attrib.get('UnidadAduana')) is not None: + self['UnidadAduana'] = catalog_code('C5bc_c_UnidadAduana', a) + if (a := node.attrib.get('ValorUnitarioAduana')) is not None: + self['ValorUnitarioAduana'] = Decimal(a) + self['ValorDolares'] = Decimal(node.attrib['ValorDolares']) + return self +def descripciones_especificas1(cls, node): + self = ScalarMap() + self['Marca'] = node.attrib['Marca'] + if (a := node.attrib.get('Modelo')) is not None: + self['Modelo'] = a + if (a := node.attrib.get('SubModelo')) is not None: + self['SubModelo'] = a + if (a := node.attrib.get('NumeroSerie')) is not None: + self['NumeroSerie'] = a + return self +def comercio_exterior2(cls, node): + self = cls() + self.tag = node.tag + el = node.find('{http://www.sat.gob.mx/ComercioExterior}Emisor') + if el is not None: + self['Emisor'] = emisor8(cls, el) el = node.find('{http://www.sat.gob.mx/ComercioExterior}Receptor') - self['Receptor'] = receptor7(cls, el) + self['Receptor'] = receptor8(cls, el) el = node.find('{http://www.sat.gob.mx/ComercioExterior}Destinatario') if el is not None: - self['Destinatario'] = destinatario2(cls, el) + self['Destinatario'] = destinatario3(cls, el) el = node.find('{http://www.sat.gob.mx/ComercioExterior}Mercancias') if el is not None: - self['Mercancias'] = [mercancia4(cls, n) for n in el.iterfind('{http://www.sat.gob.mx/ComercioExterior}Mercancia')] + self['Mercancias'] = [mercancia5(cls, n) for n in el.iterfind('{http://www.sat.gob.mx/ComercioExterior}Mercancia')] self['Version'] = node.attrib['Version'] self['TipoOperacion'] = catalog_code('C5bc_c_TipoOperacion', node.attrib['TipoOperacion']) if (a := node.attrib.get('ClaveDePedimento')) is not None: @@ -11975,21 +12119,21 @@ def comercio_exterior1(cls, node): if (a := node.attrib.get('TotalUSD')) is not None: self['TotalUSD'] = Decimal(a) return self -def emisor7(cls, node): +def emisor8(cls, node): self = ScalarMap() if (a := node.attrib.get('Curp')) is not None: self['Curp'] = a return self -def receptor7(cls, node): +def receptor8(cls, node): self = ScalarMap() if (a := node.attrib.get('Curp')) is not None: self['Curp'] = a self['NumRegIdTrib'] = node.attrib['NumRegIdTrib'] return self -def destinatario2(cls, node): +def destinatario3(cls, node): self = ScalarMap() el = node.find('{http://www.sat.gob.mx/ComercioExterior}Domicilio') - self['Domicilio'] = domicilioc(cls, el) + self['Domicilio'] = domiciliof(cls, el) if (a := node.attrib.get('NumRegIdTrib')) is not None: self['NumRegIdTrib'] = a if (a := node.attrib.get('Rfc')) is not None: @@ -11999,7 +12143,7 @@ def destinatario2(cls, node): if (a := node.attrib.get('Nombre')) is not None: self['Nombre'] = a return self -def domicilioc(cls, node): +def domiciliof(cls, node): self = ScalarMap() self['Calle'] = node.attrib['Calle'] if (a := node.attrib.get('NumeroExterior')) is not None: @@ -12018,11 +12162,11 @@ def domicilioc(cls, node): self['Pais'] = catalog_code('C756_c_Pais', node.attrib['Pais']) self['CodigoPostal'] = node.attrib['CodigoPostal'] return self -def mercancia4(cls, node): +def mercancia5(cls, node): self = ScalarMap() el = node.find('{http://www.sat.gob.mx/ComercioExterior}DescripcionesEspecificas') if el is not None: - self['DescripcionesEspecificas'] = [descripciones_especificas1(cls, n) for n in node.iterfind('{http://www.sat.gob.mx/ComercioExterior}DescripcionesEspecificas')] + self['DescripcionesEspecificas'] = [descripciones_especificas2(cls, n) for n in node.iterfind('{http://www.sat.gob.mx/ComercioExterior}DescripcionesEspecificas')] self['NoIdentificacion'] = node.attrib['NoIdentificacion'] if (a := node.attrib.get('FraccionArancelaria')) is not None: self['FraccionArancelaria'] = catalog_code('C5bc_c_FraccionArancelaria', a) @@ -12034,7 +12178,7 @@ def mercancia4(cls, node): self['ValorUnitarioAduana'] = Decimal(a) self['ValorDolares'] = Decimal(node.attrib['ValorDolares']) return self -def descripciones_especificas1(cls, node): +def descripciones_especificas2(cls, node): self = ScalarMap() self['Marca'] = node.attrib['Marca'] if (a := node.attrib.get('Modelo')) is not None: @@ -13407,9 +13551,9 @@ def nomina1(cls, node): self.tag = node.tag el = node.find('{http://www.sat.gob.mx/nomina12}Emisor') if el is not None: - self['Emisor'] = emisor8(cls, el) + self['Emisor'] = emisor9(cls, el) el = node.find('{http://www.sat.gob.mx/nomina12}Receptor') - self['Receptor'] = receptor8(cls, el) + self['Receptor'] = receptor9(cls, el) el = node.find('{http://www.sat.gob.mx/nomina12}Percepciones') if el is not None: self['Percepciones'] = percepciones1(cls, el) @@ -13435,7 +13579,7 @@ def nomina1(cls, node): if (a := node.attrib.get('TotalOtrosPagos')) is not None: self['TotalOtrosPagos'] = Decimal(a) return self -def emisor8(cls, node): +def emisor9(cls, node): self = ScalarMap() el = node.find('{http://www.sat.gob.mx/nomina12}EntidadSNCF') if el is not None: @@ -13453,7 +13597,7 @@ def entidad_sncf0(cls, node): if (a := node.attrib.get('MontoRecursoPropio')) is not None: self['MontoRecursoPropio'] = Decimal(a) return self -def receptor8(cls, node): +def receptor9(cls, node): self = ScalarMap() el = node.find('{http://www.sat.gob.mx/nomina12}SubContratacion') if el is not None: @@ -14220,9 +14364,13 @@ def s_comercio_exterior0(cls, node): return comercio_exterior0(cls, node) raise NamespaceMismatchError(node) def s_comercio_exterior1(cls, node): - if node.attrib.get('Version') == '1.0': + if node.attrib.get('Version') == '2.0': return comercio_exterior1(cls, node) raise NamespaceMismatchError(node) +def s_comercio_exterior2(cls, node): + if node.attrib.get('Version') == '1.0': + return comercio_exterior2(cls, node) + raise NamespaceMismatchError(node) def s_estado_de_cuenta_combustible0(cls, node): if node.attrib.get('Version') == '1.1' and node.attrib.get('TipoOperacion') == 'Tarjeta': return estado_de_cuenta_combustible0(cls, node) @@ -14476,7 +14624,8 @@ def s_rsakey_value0(cls, node): '{http://www.sat.gob.mx/CartaPorte20}CartaPorte': s_carta_porte1, '{http://www.sat.gob.mx/CartaPorte30}CartaPorte': s_carta_porte2, '{http://www.sat.gob.mx/ComercioExterior11}ComercioExterior': s_comercio_exterior0, - '{http://www.sat.gob.mx/ComercioExterior}ComercioExterior': s_comercio_exterior1, + '{http://www.sat.gob.mx/ComercioExterior20}ComercioExterior': s_comercio_exterior1, + '{http://www.sat.gob.mx/ComercioExterior}ComercioExterior': s_comercio_exterior2, '{http://www.sat.gob.mx/EstadoDeCuentaCombustible}EstadoDeCuentaCombustible': s_estado_de_cuenta_combustible0, '{http://www.sat.gob.mx/EstadoDeCuentaCombustible12}EstadoDeCuentaCombustible': s_estado_de_cuenta_combustible1, '{http://www.sat.gob.mx/GastosHidrocarburos10}GastosHidrocarburos': s_gastos_hidrocarburos0, diff --git a/satcfdi/transform/schemas.py b/satcfdi/transform/schemas.py index f7643c7..0fb3294 100644 --- a/satcfdi/transform/schemas.py +++ b/satcfdi/transform/schemas.py @@ -3937,6 +3937,10 @@ def comercio_exterior0(col, data): col.add_schema('http://www.sat.gob.mx/ComercioExterior11 http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd') col.add_base('www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd') def comercio_exterior1(col, data): + col.add_map('cce20', 'http://www.sat.gob.mx/ComercioExterior20') + col.add_schema('http://www.sat.gob.mx/ComercioExterior20 http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xsd') + col.add_base('www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xsd') +def comercio_exterior2(col, data): col.add_map('cce', 'http://www.sat.gob.mx/ComercioExterior') col.add_schema('http://www.sat.gob.mx/ComercioExterior http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior/ComercioExterior10.xsd') col.add_base('www.sat.gob.mx/sitio_internet/cfd/ComercioExterior/ComercioExterior10.xsd') @@ -4244,8 +4248,11 @@ def s_comercio_exterior0(col, data): if data.get('Version') == '1.1': comercio_exterior0(col, data) def s_comercio_exterior1(col, data): - if data.get('Version') == '1.0': + if data.get('Version') == '2.0': comercio_exterior1(col, data) +def s_comercio_exterior2(col, data): + if data.get('Version') == '1.0': + comercio_exterior2(col, data) def s_estado_de_cuenta_combustible0(col, data): if data.get('Version') == '1.1' and data.get('TipoOperacion') == 'Tarjeta': estado_de_cuenta_combustible0(col, data) @@ -4464,7 +4471,8 @@ def s_rsakey_value0(col, data): '{http://www.sat.gob.mx/CartaPorte20}CartaPorte': s_carta_porte1, '{http://www.sat.gob.mx/CartaPorte30}CartaPorte': s_carta_porte2, '{http://www.sat.gob.mx/ComercioExterior11}ComercioExterior': s_comercio_exterior0, - '{http://www.sat.gob.mx/ComercioExterior}ComercioExterior': s_comercio_exterior1, + '{http://www.sat.gob.mx/ComercioExterior20}ComercioExterior': s_comercio_exterior1, + '{http://www.sat.gob.mx/ComercioExterior}ComercioExterior': s_comercio_exterior2, '{http://www.sat.gob.mx/EstadoDeCuentaCombustible}EstadoDeCuentaCombustible': s_estado_de_cuenta_combustible0, '{http://www.sat.gob.mx/EstadoDeCuentaCombustible12}EstadoDeCuentaCombustible': s_estado_de_cuenta_combustible1, '{http://www.sat.gob.mx/GastosHidrocarburos10}GastosHidrocarburos': s_gastos_hidrocarburos0, diff --git a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/4/cadenaoriginal_4_0/cadenaoriginal_4_0.xslt b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/4/cadenaoriginal_4_0/cadenaoriginal_4_0.xslt index 7aa0efd..3edc01a 100644 --- a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/4/cadenaoriginal_4_0/cadenaoriginal_4_0.xslt +++ b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/4/cadenaoriginal_4_0/cadenaoriginal_4_0.xslt @@ -1 +1 @@ -||| \ No newline at end of file +||| \ No newline at end of file diff --git a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xsd b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xsd new file mode 100644 index 0000000..4fd7d48 --- /dev/null +++ b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xsd @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xslt b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xslt new file mode 100644 index 0000000..cc4b81c --- /dev/null +++ b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/ComercioExterior20/ComercioExterior20.xslt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/CartaPorte/catCartaPorte.xsd b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/CartaPorte/catCartaPorte.xsd index bd732d9..67defe0 100644 --- a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/CartaPorte/catCartaPorte.xsd +++ b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/CartaPorte/catCartaPorte.xsd @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/catCFDI.xsd b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/catCFDI.xsd index 53a7b8a..703d88d 100644 --- a/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/catCFDI.xsd +++ b/satcfdi/transform/schemas/www.sat.gob.mx/sitio_internet/cfd/catalogos/catCFDI.xsd @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/satcfdi/transform/xmlify.py b/satcfdi/transform/xmlify.py index a56d6d4..c711a94 100644 --- a/satcfdi/transform/xmlify.py +++ b/satcfdi/transform/xmlify.py @@ -12555,20 +12555,172 @@ def descripciones_especificas0(name, data): def comercio_exterior1(name, data): col = SchemaCollector() cfdi_schemas[data.tag](col, data) - self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=col.nsmap) + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=col.nsmap) el = data.get('Emisor') if el is not None: self.append(emisor7('Emisor', el)) + el = data.get('Propietario') + if el is not None: + for r in iterate(el): + self.append(propietario2('Propietario', r)) + el = data.get('Receptor') + if el is not None: + self.append(receptor7('Receptor', el)) + el = data.get('Destinatario') + if el is not None: + for r in iterate(el): + self.append(destinatario2('Destinatario', r)) + el = data['Mercancias'] + st = SubElement(self, '{http://www.sat.gob.mx/ComercioExterior20}Mercancias') + for r in iterate(el): + st.append(mercancia4('Mercancia', r)) + self.attrib['Version'] = data['Version'] + if (a := data.get('MotivoTraslado')) is not None: + self.attrib['MotivoTraslado'] = strcode(a) + self.attrib['ClaveDePedimento'] = strcode(data['ClaveDePedimento']) + self.attrib['CertificadoOrigen'] = str(data['CertificadoOrigen']) + if (a := data.get('NumCertificadoOrigen')) is not None: + self.attrib['NumCertificadoOrigen'] = a + if (a := data.get('NumeroExportadorConfiable')) is not None: + self.attrib['NumeroExportadorConfiable'] = a + if (a := data.get('Incoterm')) is not None: + self.attrib['Incoterm'] = strcode(a) + if (a := data.get('Observaciones')) is not None: + self.attrib['Observaciones'] = a + self.attrib['TipoCambioUSD'] = fmt_decimal(data['TipoCambioUSD']) + self.attrib['TotalUSD'] = fmt_decimal(data['TotalUSD']) + return self +def emisor7(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + el = data['Domicilio'] + self.append(domicilioc('Domicilio', el)) + if (a := data.get('Curp')) is not None: + self.attrib['Curp'] = a + return self +def domicilioc(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + self.attrib['Calle'] = data['Calle'] + if (a := data.get('NumeroExterior')) is not None: + self.attrib['NumeroExterior'] = a + if (a := data.get('NumeroInterior')) is not None: + self.attrib['NumeroInterior'] = a + if (a := data.get('Colonia')) is not None: + self.attrib['Colonia'] = strcode(a) + if (a := data.get('Localidad')) is not None: + self.attrib['Localidad'] = strcode(a) + if (a := data.get('Referencia')) is not None: + self.attrib['Referencia'] = a + if (a := data.get('Municipio')) is not None: + self.attrib['Municipio'] = strcode(a) + self.attrib['Estado'] = strcode(data['Estado']) + self.attrib['Pais'] = strcode(data['Pais']) + self.attrib['CodigoPostal'] = strcode(data['CodigoPostal']) + return self +def propietario2(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + self.attrib['NumRegIdTrib'] = data['NumRegIdTrib'] + self.attrib['ResidenciaFiscal'] = strcode(data['ResidenciaFiscal']) + return self +def receptor7(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + el = data.get('Domicilio') + if el is not None: + self.append(domiciliod('Domicilio', el)) + if (a := data.get('NumRegIdTrib')) is not None: + self.attrib['NumRegIdTrib'] = a + return self +def domiciliod(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + self.attrib['Calle'] = data['Calle'] + if (a := data.get('NumeroExterior')) is not None: + self.attrib['NumeroExterior'] = a + if (a := data.get('NumeroInterior')) is not None: + self.attrib['NumeroInterior'] = a + if (a := data.get('Colonia')) is not None: + self.attrib['Colonia'] = a + if (a := data.get('Localidad')) is not None: + self.attrib['Localidad'] = a + if (a := data.get('Referencia')) is not None: + self.attrib['Referencia'] = a + if (a := data.get('Municipio')) is not None: + self.attrib['Municipio'] = a + self.attrib['Estado'] = data['Estado'] + self.attrib['Pais'] = strcode(data['Pais']) + self.attrib['CodigoPostal'] = data['CodigoPostal'] + return self +def destinatario2(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + el = data['Domicilio'] + for r in iterate(el): + self.append(domicilioe('Domicilio', r)) + if (a := data.get('NumRegIdTrib')) is not None: + self.attrib['NumRegIdTrib'] = a + if (a := data.get('Nombre')) is not None: + self.attrib['Nombre'] = a + return self +def domicilioe(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + self.attrib['Calle'] = data['Calle'] + if (a := data.get('NumeroExterior')) is not None: + self.attrib['NumeroExterior'] = a + if (a := data.get('NumeroInterior')) is not None: + self.attrib['NumeroInterior'] = a + if (a := data.get('Colonia')) is not None: + self.attrib['Colonia'] = a + if (a := data.get('Localidad')) is not None: + self.attrib['Localidad'] = a + if (a := data.get('Referencia')) is not None: + self.attrib['Referencia'] = a + if (a := data.get('Municipio')) is not None: + self.attrib['Municipio'] = a + self.attrib['Estado'] = data['Estado'] + self.attrib['Pais'] = strcode(data['Pais']) + self.attrib['CodigoPostal'] = data['CodigoPostal'] + return self +def mercancia4(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + el = data.get('DescripcionesEspecificas') + if el is not None: + for r in iterate(el): + self.append(descripciones_especificas1('DescripcionesEspecificas', r)) + self.attrib['NoIdentificacion'] = data['NoIdentificacion'] + if (a := data.get('FraccionArancelaria')) is not None: + self.attrib['FraccionArancelaria'] = strcode(a) + if (a := data.get('CantidadAduana')) is not None: + self.attrib['CantidadAduana'] = fmt_decimal(a) + if (a := data.get('UnidadAduana')) is not None: + self.attrib['UnidadAduana'] = strcode(a) + if (a := data.get('ValorUnitarioAduana')) is not None: + self.attrib['ValorUnitarioAduana'] = fmt_decimal(a) + self.attrib['ValorDolares'] = fmt_decimal(data['ValorDolares']) + return self +def descripciones_especificas1(name, data): + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior20', name), nsmap=data.get('_nsmap') or {'cce20': 'http://www.sat.gob.mx/ComercioExterior20'}) + self.attrib['Marca'] = data['Marca'] + if (a := data.get('Modelo')) is not None: + self.attrib['Modelo'] = a + if (a := data.get('SubModelo')) is not None: + self.attrib['SubModelo'] = a + if (a := data.get('NumeroSerie')) is not None: + self.attrib['NumeroSerie'] = a + return self +def comercio_exterior2(name, data): + col = SchemaCollector() + cfdi_schemas[data.tag](col, data) + self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=col.nsmap) + el = data.get('Emisor') + if el is not None: + self.append(emisor8('Emisor', el)) el = data['Receptor'] - self.append(receptor7('Receptor', el)) + self.append(receptor8('Receptor', el)) el = data.get('Destinatario') if el is not None: - self.append(destinatario2('Destinatario', el)) + self.append(destinatario3('Destinatario', el)) el = data.get('Mercancias') if el is not None: st = SubElement(self, '{http://www.sat.gob.mx/ComercioExterior}Mercancias') for r in iterate(el): - st.append(mercancia4('Mercancia', r)) + st.append(mercancia5('Mercancia', r)) self.attrib['Version'] = data['Version'] self.attrib['TipoOperacion'] = strcode(data['TipoOperacion']) if (a := data.get('ClaveDePedimento')) is not None: @@ -12590,21 +12742,21 @@ def comercio_exterior1(name, data): if (a := data.get('TotalUSD')) is not None: self.attrib['TotalUSD'] = fmt_decimal(a) return self -def emisor7(name, data): +def emisor8(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=data.get('_nsmap') or {'cce': 'http://www.sat.gob.mx/ComercioExterior'}) if (a := data.get('Curp')) is not None: self.attrib['Curp'] = a return self -def receptor7(name, data): +def receptor8(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=data.get('_nsmap') or {'cce': 'http://www.sat.gob.mx/ComercioExterior'}) if (a := data.get('Curp')) is not None: self.attrib['Curp'] = a self.attrib['NumRegIdTrib'] = data['NumRegIdTrib'] return self -def destinatario2(name, data): +def destinatario3(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=data.get('_nsmap') or {'cce': 'http://www.sat.gob.mx/ComercioExterior'}) el = data['Domicilio'] - self.append(domicilioc('Domicilio', el)) + self.append(domiciliof('Domicilio', el)) if (a := data.get('NumRegIdTrib')) is not None: self.attrib['NumRegIdTrib'] = a if (a := data.get('Rfc')) is not None: @@ -12614,7 +12766,7 @@ def destinatario2(name, data): if (a := data.get('Nombre')) is not None: self.attrib['Nombre'] = a return self -def domicilioc(name, data): +def domiciliof(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=data.get('_nsmap') or {'cce': 'http://www.sat.gob.mx/ComercioExterior'}) self.attrib['Calle'] = data['Calle'] if (a := data.get('NumeroExterior')) is not None: @@ -12633,12 +12785,12 @@ def domicilioc(name, data): self.attrib['Pais'] = strcode(data['Pais']) self.attrib['CodigoPostal'] = data['CodigoPostal'] return self -def mercancia4(name, data): +def mercancia5(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=data.get('_nsmap') or {'cce': 'http://www.sat.gob.mx/ComercioExterior'}) el = data.get('DescripcionesEspecificas') if el is not None: for r in iterate(el): - self.append(descripciones_especificas1('DescripcionesEspecificas', r)) + self.append(descripciones_especificas2('DescripcionesEspecificas', r)) self.attrib['NoIdentificacion'] = data['NoIdentificacion'] if (a := data.get('FraccionArancelaria')) is not None: self.attrib['FraccionArancelaria'] = strcode(a) @@ -12650,7 +12802,7 @@ def mercancia4(name, data): self.attrib['ValorUnitarioAduana'] = fmt_decimal(a) self.attrib['ValorDolares'] = fmt_decimal(data['ValorDolares']) return self -def descripciones_especificas1(name, data): +def descripciones_especificas2(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/ComercioExterior', name), nsmap=data.get('_nsmap') or {'cce': 'http://www.sat.gob.mx/ComercioExterior'}) self.attrib['Marca'] = data['Marca'] if (a := data.get('Modelo')) is not None: @@ -14147,9 +14299,9 @@ def nomina1(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/nomina12', name), nsmap=col.nsmap) el = data.get('Emisor') if el is not None: - self.append(emisor8('Emisor', el)) + self.append(emisor9('Emisor', el)) el = data['Receptor'] - self.append(receptor8('Receptor', el)) + self.append(receptor9('Receptor', el)) el = data.get('Percepciones') if el is not None: self.append(percepciones1('Percepciones', el)) @@ -14179,7 +14331,7 @@ def nomina1(name, data): if (a := data.get('TotalOtrosPagos')) is not None: self.attrib['TotalOtrosPagos'] = fmt_decimal(a) return self -def emisor8(name, data): +def emisor9(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/nomina12', name), nsmap=data.get('_nsmap') or {'nomina12': 'http://www.sat.gob.mx/nomina12'}) el = data.get('EntidadSNCF') if el is not None: @@ -14197,7 +14349,7 @@ def entidad_sncf0(name, data): if (a := data.get('MontoRecursoPropio')) is not None: self.attrib['MontoRecursoPropio'] = fmt_decimal(a) return self -def receptor8(name, data): +def receptor9(name, data): self = Element('{%s}%s' % ('http://www.sat.gob.mx/nomina12', name), nsmap=data.get('_nsmap') or {'nomina12': 'http://www.sat.gob.mx/nomina12'}) el = data.get('SubContratacion') if el is not None: @@ -15007,9 +15159,13 @@ def s_comercio_exterior0(data): return comercio_exterior0('ComercioExterior', data) raise NamespaceMismatchError(data) def s_comercio_exterior1(data): - if data.get('Version') == '1.0': + if data.get('Version') == '2.0': return comercio_exterior1('ComercioExterior', data) raise NamespaceMismatchError(data) +def s_comercio_exterior2(data): + if data.get('Version') == '1.0': + return comercio_exterior2('ComercioExterior', data) + raise NamespaceMismatchError(data) def s_estado_de_cuenta_combustible0(data): if data.get('Version') == '1.1' and data.get('TipoOperacion') == 'Tarjeta': return estado_de_cuenta_combustible0('EstadoDeCuentaCombustible', data) @@ -15263,7 +15419,8 @@ def s_rsakey_value0(data): '{http://www.sat.gob.mx/CartaPorte20}CartaPorte': s_carta_porte1, '{http://www.sat.gob.mx/CartaPorte30}CartaPorte': s_carta_porte2, '{http://www.sat.gob.mx/ComercioExterior11}ComercioExterior': s_comercio_exterior0, - '{http://www.sat.gob.mx/ComercioExterior}ComercioExterior': s_comercio_exterior1, + '{http://www.sat.gob.mx/ComercioExterior20}ComercioExterior': s_comercio_exterior1, + '{http://www.sat.gob.mx/ComercioExterior}ComercioExterior': s_comercio_exterior2, '{http://www.sat.gob.mx/EstadoDeCuentaCombustible}EstadoDeCuentaCombustible': s_estado_de_cuenta_combustible0, '{http://www.sat.gob.mx/EstadoDeCuentaCombustible12}EstadoDeCuentaCombustible': s_estado_de_cuenta_combustible1, '{http://www.sat.gob.mx/GastosHidrocarburos10}GastosHidrocarburos': s_gastos_hidrocarburos0,