Stamp with Comercio Exterior

This commit is contained in:
el Mau 2022-11-05 22:48:54 -06:00
parent 80102ebe1a
commit d8fbc4a856
3 changed files with 457 additions and 1 deletions

View File

@ -74,6 +74,18 @@ class DictToCfdi():
'xmlns': 'http://www.sat.gob.mx/leyendasFiscales',
'schema': ' http://www.sat.gob.mx/leyendasFiscales http://www.sat.gob.mx/sitio_internet/cfd/leyendasFiscales/leyendasFisc.xsd',
}
_PAGOS = {
'version': '2.0',
'prefix': '',
'xmlns': 'http://www.sat.gob.mx/',
'schema': ' http://www.sat.gob.mx/ http://www.sat.gob.mx/sitio_internet/cfd//.xsd',
}
_COMERCIO = {
'version': '1.1',
'prefix': 'cce11',
'xmlns': 'http://www.sat.gob.mx/ComercioExterior11',
'schema': ' http://www.sat.gob.mx/ComercioExterior11 http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd',
}
def __init__ (self, data):
self._data = data
@ -111,6 +123,12 @@ class DictToCfdi():
self._attr_complementos['leyendas'] = {
self._LEYENDAS['prefix']: self._LEYENDAS['xmlns']
}
if 'comercio' in self._data['complementos']:
self._schema += self._COMERCIO['schema']
self._attr_complementos['comercio'] = {
self._COMERCIO['prefix']: self._COMERCIO['xmlns']
}
return
def _comprobante(self):
@ -223,6 +241,12 @@ class DictToCfdi():
if 'leyendas' in self._data['complementos']:
self._complemento_leyendas(self._data['complementos']['leyendas'], node)
if 'pagos' in self._data['complementos']:
self._complemento_pagos(self._data['complementos']['pagos'], node)
elif 'comercio' in self._data['complementos']:
self._complemento_comercio(self._data['complementos']['comercio'], node)
return
def _complemento_leyendas(self, data, node):
@ -235,6 +259,69 @@ class DictToCfdi():
ET.SubElement(node_leyendas, node_name, leyenda)
return
def _complemento_pagos(self, data, node):
attr = {'version': self._PAGOS['version']}
return
def _complemento_comercio(self, data, node):
mercancias = data.pop('mercancias', {})
emisor = data.pop('emisor', {})
propietario = data.pop('propietario', {})
receptor = data.pop('receptor', {})
destinatario = data.pop('destinatario', {})
attr = data
node_name = f"{{{self._COMERCIO['xmlns']}}}ComercioExterior"
node_comercio = ET.SubElement(node, node_name, attr)
if emisor:
node_name = f"{{{self._COMERCIO['xmlns']}}}Emisor"
attr = {}
if 'Curp' in emisor:
attr = {'Curp': emisor.pop('Curp')}
node_emisor = ET.SubElement(node_comercio, node_name, attr)
node_name = f"{{{self._COMERCIO['xmlns']}}}Domicilio"
ET.SubElement(node_emisor, node_name, emisor)
if propietario:
node_name = f"{{{self._COMERCIO['xmlns']}}}Propietario"
ET.SubElement(node_comercio, node_name, propietario)
if receptor:
node_name = f"{{{self._COMERCIO['xmlns']}}}Receptor"
attr = {}
if 'NumRegIdTrib' in receptor:
attr = {'NumRegIdTrib': emisor.pop('NumRegIdTrib')}
node_receptor = ET.SubElement(node_comercio, node_name, attr)
node_name = f"{{{self._COMERCIO['xmlns']}}}Domicilio"
ET.SubElement(node_receptor, node_name, receptor)
if destinatario:
node_name = f"{{{self._COMERCIO['xmlns']}}}Destinatario"
attr = {}
if 'NumRegIdTrib' in destinatario:
attr['NumRegIdTrib'] = destinatario.pop('NumRegIdTrib')
if 'Nombre' in destinatario:
attr['Nombre'] = destinatario.pop('Nombre')
node_destinatario = ET.SubElement(node_comercio, node_name, attr)
node_name = f"{{{self._COMERCIO['xmlns']}}}Domicilio"
ET.SubElement(node_destinatario, node_name, destinatario)
if mercancias:
node_name = f"{{{self._COMERCIO['xmlns']}}}Mercancias"
node_mercancias = ET.SubElement(node_comercio, node_name)
for mercancia in mercancias:
description = mercancia.pop('description', {})
node_name = f"{{{self._COMERCIO['xmlns']}}}Mercancia"
node_mercancia = ET.SubElement(node_mercancias, node_name, mercancia)
if description:
node_name = f"{{{self._COMERCIO['xmlns']}}}DescripcionesEspecificas"
ET.SubElement(node_mercancia, node_name, description)
return
def _addenda(self):
type_boveda = self._data['addenda'].get('type', '')
type_client = self._data['addenda'].get('type_client', '')
@ -339,6 +426,13 @@ class DataToDict():
'05': '_conceptos',
'06': '_impuestos',
'10': '_leyendas',
'11': '_complemento',
'12': '_complemento_12',
'13': '_complemento_13',
'14': '_complemento_14',
'15': '_complemento_15',
'16': '_complemento_16',
'17': '_complemento_17',
'49': '_addenda_lotes',
'50': '_boveda',
'51': '_addenda',
@ -348,9 +442,11 @@ class DataToDict():
def __init__ (self, data):
self._data = data
self._cfdi = {'conceptos': [], 'complementos': {}, 'addenda': {}}
self._complement = ''
self._type_header = ''
self._partes = []
self._lotes = []
self._ce_mercancias = []
self._process_data()
@property
@ -372,6 +468,10 @@ class DataToDict():
self._cfdi['addenda']['partes'] = self._partes
self._cfdi['addenda']['lotes'] = self._lotes
if self._ce_mercancias:
self._cfdi['complementos']['comercio']['mercancias'] = \
self._ce_mercancias
return
def _comprobante(self, data):
@ -538,6 +638,181 @@ class DataToDict():
self._cfdi['complementos']['leyendas'] = leyendas
return
def _fields_to_dict(self, fields, data):
attr = {}
for index, field in enumerate(fields):
if not data[index]:
continue
attr[field] = data[index]
return attr
def _complemento(self, data):
if not data:
return
self._complement = data[0]
version = {'Version': data[1]}
if self._complement == '1':
self._cfdi['complementos']['pagos'] = version
elif self._complement == '2':
self._cfdi['complementos']['comercio'] = version
return
def _complemento_12(self, data):
if not data:
return
if self._complement == '1':
fields = (
'TotalRetencionesIVA',
'TotalRetencionesISR',
'TotalRetencionesIEPS',
'TotalTrasladosBaseIVA16',
'TotalTrasladosImpuestoIVA16',
'TotalTrasladosBaseIVA8',
'TotalTrasladosImpuestoIVA8',
'TotalTrasladosBaseIVA0',
'TotalTrasladosImpuestoIVA0',
'TotalTrasladosBaseIVAExento',
'MontoTotalPagos',
)
attr = self._fields_to_dict(fields, data)
self._cfdi['complementos']['pagos'].update(attr)
elif self._complement == '2':
fields = (
'MotivoTraslado',
'TipoOperacion',
'ClaveDePedimento',
'CertificadoOrigen',
'NumCertificadoOrigen',
'NumeroExportadorConfiable',
'Incoterm',
'Subdivision',
'Observaciones',
'TipoCambioUSD',
'TotalUSD',
)
attr = self._fields_to_dict(fields, data)
self._cfdi['complementos']['comercio'].update(attr)
return
def _complemento_13(self, data):
if not data:
return
if self._complement == '1':
pass
elif self._complement == '2':
fields = (
'Curp',
'Calle',
'NumeroExterior',
'NumeroInterior',
'Colonia',
'Localidad',
'Referencia',
'Municipio',
'Estado',
'Pais',
'CodigoPostal',
)
attr = self._fields_to_dict(fields, data)
self._cfdi['complementos']['comercio']['emisor'] = attr
return
def _complemento_14(self, data):
if not data:
return
if self._complement == '1':
pass
elif self._complement == '2':
fields = ('NumRegIdTrib', 'ResidenciaFiscal')
attr = self._fields_to_dict(fields, data)
if attr:
self._cfdi['complementos']['comercio']['propietario'] = attr
return
def _complemento_15(self, data):
if not data:
return
if self._complement == '1':
pass
elif self._complement == '2':
fields = (
'NumRegIdTrib',
'Calle',
'NumeroExterior',
'NumeroInterior',
'Colonia',
'Localidad',
'Referencia',
'Municipio',
'Estado',
'Pais',
'CodigoPostal',
)
attr = self._fields_to_dict(fields, data)
self._cfdi['complementos']['comercio']['receptor'] = attr
return
def _complemento_16(self, data):
if not data:
return
if self._complement == '1':
pass
elif self._complement == '2':
fields = (
'NumRegIdTrib',
'Nombre',
'Calle',
'NumeroExterior',
'NumeroInterior',
'Colonia',
'Localidad',
'Referencia',
'Municipio',
'Estado',
'Pais',
'CodigoPostal',
)
attr = self._fields_to_dict(fields, data)
self._cfdi['complementos']['comercio']['destinatario'] = attr
return
def _complemento_17(self, data):
if not data:
return
if self._complement == '1':
pass
elif self._complement == '2':
fields = (
'NoIdentificacion',
'FraccionArancelaria',
'CantidadAduana',
'UnidadAduana',
'ValorUnitarioAduana',
'ValorDolares',
)
mercancia = self._fields_to_dict(fields, data)
fields = (
'Marca',
'Modelo',
'SubModelo',
'NumeroSerie',
)
description = self._fields_to_dict(fields, data[6:])
if description:
mercancia['description'] = description
self._ce_mercancias.append(mercancia)
return
def _boveda(self, data):
type_addenda = data[0]
if type_addenda == '01':

View File

@ -6,13 +6,13 @@
<xsl:include href="utilerias.xslt"/>
<xsl:include href="leyendasFisc.xslt"/>
<xsl:include href="comercioexterior11.xslt"/>
<!--
<xsl:include href="nomina12.xslt"/>
<xsl:include href="divisas.xslt"/>
<xsl:include href="ine11.xslt"/>
<xsl:include href="iedu.xslt"/>
<xsl:include href="cartaporte20.xslt"/>
<xsl:include href="comercioexterior11.xslt"/>
<xsl:include href="donat11.xslt"/>
<xsl:include href="pagos20.xslt"/>
<xsl:include href="implocal.xslt"/>

View File

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:cce11="http://www.sat.gob.mx/ComercioExterior11">
<xsl:template match="cce11:ComercioExterior">
<!--Manejador de nodos tipo ComercioExterior-->
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@Version" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@MotivoTraslado" />
</xsl:call-template>
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@TipoOperacion" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@ClaveDePedimento" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@CertificadoOrigen" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@NumCertificadoOrigen" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@NumeroExportadorConfiable" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Incoterm" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Subdivision" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Observaciones" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@TipoCambioUSD" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@TotalUSD" />
</xsl:call-template>
<!-- Iniciamos el manejo de los elementos hijo en la secuencia -->
<xsl:apply-templates select="./cce11:Emisor" />
<xsl:for-each select="./cce11:Propietario">
<xsl:apply-templates select="."/>
</xsl:for-each>
<xsl:apply-templates select="./cce11:Receptor" />
<xsl:for-each select="./cce11:Destinatario">
<xsl:apply-templates select="."/>
</xsl:for-each>
<xsl:apply-templates select="./cce11:Mercancias" />
</xsl:template>
<xsl:template match="cce11:Emisor">
<!-- Iniciamos el tratamiento de los atributos de cce11:Emisor-->
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Curp" />
</xsl:call-template>
<xsl:apply-templates select="./cce11:Domicilio" />
</xsl:template>
<xsl:template match="cce11:Propietario">
<!-- Tratamiento de los atributos de cce11:Propietario-->
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@NumRegIdTrib" />
</xsl:call-template>
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@ResidenciaFiscal" />
</xsl:call-template>
</xsl:template>
<xsl:template match="cce11:Receptor">
<!-- Tratamiento de los atributos de cce11:Receptor-->
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@NumRegIdTrib" />
</xsl:call-template>
<xsl:apply-templates select="./cce11:Domicilio" />
</xsl:template>
<xsl:template match="cce11:Destinatario">
<!-- Tratamiento de los atributos de cce11:Destinatario-->
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@NumRegIdTrib" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Nombre" />
</xsl:call-template>
<!-- Manejo de los nodos dependientes -->
<xsl:for-each select="./cce11:Domicilio">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="cce11:Mercancias">
<!-- Iniciamos el manejo de los nodos dependientes -->
<xsl:for-each select="./cce11:Mercancia">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="cce11:Domicilio">
<!-- Iniciamos el tratamiento de los atributos de cce11:Domicilio-->
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@Calle" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@NumeroExterior" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@NumeroInterior" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Colonia" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Localidad" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Referencia" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Municipio" />
</xsl:call-template>
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@Estado" />
</xsl:call-template>
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@Pais" />
</xsl:call-template>
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@CodigoPostal" />
</xsl:call-template>
</xsl:template>
<xsl:template match="cce11:Mercancia">
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@NoIdentificacion" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@FraccionArancelaria" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@CantidadAduana" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@UnidadAduana" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@ValorUnitarioAduana" />
</xsl:call-template>
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@ValorDolares" />
</xsl:call-template>
<xsl:for-each select="./cce11:DescripcionesEspecificas">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="cce11:DescripcionesEspecificas">
<xsl:call-template name="Requerido">
<xsl:with-param name="valor" select="./@Marca" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@Modelo" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@SubModelo" />
</xsl:call-template>
<xsl:call-template name="Opcional">
<xsl:with-param name="valor" select="./@NumeroSerie" />
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>