Ejemplo Complemento de Pagos en CFDI 4.0

This commit is contained in:
el Mau 2022-09-12 19:26:23 -05:00
parent 5f91511266
commit 1972723d9e
2 changed files with 106 additions and 34 deletions

View File

@ -5,15 +5,20 @@
"TipoDeComprobante": "P", "TipoDeComprobante": "P",
"LugarExpedicion": "06850", "LugarExpedicion": "06850",
"SubTotal": "0", "SubTotal": "0",
"Total": "0" "Total": "0",
"Exportacion": "01"
}, },
"emisor": { "emisor": {
"Rfc": "LAN7008173R5", "Rfc": "EKU9003173C9",
"Nombre": "ESCUELA KEMPER URGATE",
"RegimenFiscal": "601" "RegimenFiscal": "601"
}, },
"receptor": { "receptor": {
"Rfc": "BASM740115RW0", "Rfc": "BASM740115RW0",
"UsoCFDI": "P01" "Nombre": "MAURICIO BAEZA SERVIN",
"DomicilioFiscalReceptor": "06850",
"RegimenFiscalReceptor": "612" ,
"UsoCFDI": "CP01"
}, },
"conceptos": [ "conceptos": [
{ {
@ -22,26 +27,58 @@
"ClaveUnidad": "ACT", "ClaveUnidad": "ACT",
"Descripcion": "Pago", "Descripcion": "Pago",
"ValorUnitario": "0", "ValorUnitario": "0",
"Importe": "0" "Importe": "0",
"ObjetoImp": "01"
} }
], ],
"pagos": [ "pagos": {
{ "totales": {
"FechaPago": "2020-08-07T12:00:00", "TotalTrasladosBaseIVA16": "1000.00",
"FormaDePagoP": "03", "TotalTrasladosImpuestoIVA16": "160.00",
"MonedaP": "MXN", "MontoTotalPagos": "1160.00"
"Monto": "6073.60", },
"documentos": [ "pagos": [
{ {
"IdDocumento": "5243138D-EE4B-4B1B-A648-320DCC4E3BD2", "FechaPago": "2020-08-07T12:00:00",
"ImpPagado": "6073.60", "FormaDePagoP": "03",
"ImpSaldoAnt": "6073.60", "MonedaP": "MXN",
"ImpSaldoInsoluto": "0.00", "TipoCambioP": "1",
"MetodoDePagoDR": "PPD", "Monto": "1160.00",
"MonedaDR": "MXN", "documentos": [
"NumParcialidad": "1" {
"IdDocumento": "5243138D-EE4B-4B1B-A648-320DCC4E3BD2",
"ImpPagado": "1160.00",
"ImpSaldoAnt": "1160.00",
"ImpSaldoInsoluto": "0.00",
"MonedaDR": "MXN",
"EquivalenciaDR": "1",
"NumParcialidad": "1",
"ObjetoImpDR": "02",
"impuestos": {
"traslados": [
{
"BaseDR": "1000.00",
"ImpuestoDR": "002",
"TipoFactorDR": "Tasa",
"TasaOCuotaDR": "0.160000",
"ImporteDR": "160.00"
}
]
}
}
],
"impuestos": {
"traslados": [
{
"BaseP": "1000.00",
"ImpuestoP": "002",
"TipoFactorP": "Tasa",
"TasaOCuotaP": "0.160000",
"ImporteP": "160.00"
}
]
} }
] }
} ]
] }
} }

View File

@ -26,7 +26,7 @@ log = logging.getLogger(__name__)
PACs = { PACs = {
# ~ 'finkok': PACFinkok, 'finkok': PACFinkok,
'comercio': PACComercioDigital, 'comercio': PACComercioDigital,
} }
NS_CFDI = { NS_CFDI = {
@ -56,12 +56,12 @@ class CFDI(object):
_prefix = 'cfdi' _prefix = 'cfdi'
_xmlns = 'http://www.sat.gob.mx/cfd/4' _xmlns = 'http://www.sat.gob.mx/cfd/4'
schema = f'{_xmlns} http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd' schema = f'{_xmlns} http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd'
_pagos = 'http://www.sat.gob.mx/Pagos' _pagos = 'http://www.sat.gob.mx/Pagos20'
PAGOS = { PAGOS = {
'version': '1.0', 'version': '2.0',
'prefix': _pagos, 'prefix': _pagos,
'ns': {'pago10': _pagos}, 'ns': {'pago20': _pagos},
'schema': f' {_pagos} http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos10.xsd', 'schema': f' {_pagos} http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos20.xsd',
} }
_nomina = 'http://www.sat.gob.mx/nomina12' _nomina = 'http://www.sat.gob.mx/nomina12'
NOMINA = { NOMINA = {
@ -237,16 +237,51 @@ class CFDI(object):
return return
def _pagos(self, complemento, data): def _pagos(self, complemento, data):
node_name = f"{{{self.PAGOS['prefix']}}}Pagos" pre = self.PAGOS['prefix']
totales = data['totales']
pagos = data['pagos']
node_name = f"{{{pre}}}Pagos"
attr = {'Version': self.PAGOS['version']} attr = {'Version': self.PAGOS['version']}
node_pagos = ET.SubElement(complemento, node_name, attr) node_pagos = ET.SubElement(complemento, node_name, attr)
for pago in data:
documentos = pago.pop('documentos') node_name = f"{{{pre}}}Totales"
node_name = f"{{{self.PAGOS['prefix']}}}Pago" ET.SubElement(node_pagos, node_name, totales)
for pago in pagos:
documents = pago.pop('documentos')
taxes_pago = pago.pop('impuestos')
node_name = f"{{{pre}}}Pago"
node_pago = ET.SubElement(node_pagos, node_name, pago) node_pago = ET.SubElement(node_pagos, node_name, pago)
node_name = f"{{{self.PAGOS['prefix']}}}DoctoRelacionado" node_name = f"{{{pre}}}DoctoRelacionado"
for doc in documentos: for doc in documents:
ET.SubElement(node_pago, node_name, doc) taxes = doc.pop('impuestos', {})
traslados = taxes.get('traslados', [])
retenciones = taxes.get('retenciones', [])
node_doc = ET.SubElement(node_pago, node_name, doc)
if traslados or retenciones:
node_name = f"{{{pre}}}ImpuestosDR"
node_taxes = ET.SubElement(node_doc, node_name)
if traslados:
node_name = f"{{{pre}}}TrasladosDR"
node_tax = ET.SubElement(node_taxes, node_name)
for traslado in traslados:
node_name = f"{{{pre}}}TrasladoDR"
ET.SubElement(node_tax, node_name, traslado)
traslados = taxes_pago.get('traslados', [])
retenciones = taxes_pago.get('retenciones', [])
if traslados or retenciones:
node_name = f"{{{pre}}}ImpuestosP"
node_taxes = ET.SubElement(node_pago, node_name)
if traslados:
node_name = f"{{{pre}}}TrasladosP"
node_tax = ET.SubElement(node_taxes, node_name)
for traslado in traslados:
node_name = f"{{{pre}}}TrasladoP"
ET.SubElement(node_tax, node_name, traslado)
return return
def _nomina(self, complemento, data): def _nomina(self, complemento, data):