se extendie NominaIndividualDeAjuste de NominaIndividual

FossilOrigin-Name: 10b3af439bee9b932e4f5067bec0768af60e514f595e00ecb1bdf7c88c39afc1
This commit is contained in:
bit4bit 2021-11-10 01:08:39 +00:00
parent b60fe675c1
commit bb16b5e968
3 changed files with 69 additions and 28 deletions

View File

@ -455,5 +455,16 @@ class FachoXML:
def tostring(self, **kw):
return self.builder.tostring(self.root, **kw)
def xpath_from_root(self, xpath):
nsmap = {}
ns = ''
if isinstance(self.nsmap, dict):
nsmap = dict(map(reversed, self.nsmap.items()))
ns = nsmap[etree.QName(self.root).namespace] + ':'
new_xpath = '/' + ns + etree.QName(self.root).localname + '/' + xpath.lstrip('/')
return new_xpath
def __str__(self):
return self.tostring()

View File

@ -69,17 +69,17 @@ class InformacionGeneral:
# generar cune
# ver 8.1.1.1
xpaths = [
'/fe:NominaIndividual/NumeroSecuenciaXML/@Numero',
'/fe:NominaIndividual/InformacionGeneral/@FechaGen',
'/fe:NominaIndividual/InformacionGeneral/@HoraGen',
'/fe:NominaIndividual/DevengadosTotal',
'/fe:NominaIndividual/DeduccionesTotal',
'/fe:NominaIndividual/ComprobanteTotal',
'/fe:NominaIndividual/Empleador/@NIT',
'/fe:NominaIndividual/Trabajador/@NumeroDocumento',
'/fe:NominaIndividual/InformacionGeneral/@TipoXML',
fexml.xpath_from_root('/NumeroSecuenciaXML/@Numero'),
fexml.xpath_from_root('/InformacionGeneral/@FechaGen'),
fexml.xpath_from_root('/InformacionGeneral/@HoraGen'),
fexml.xpath_from_root('/DevengadosTotal'),
fexml.xpath_from_root('/DeduccionesTotal'),
fexml.xpath_from_root('/ComprobanteTotal'),
fexml.xpath_from_root('/Empleador/@NIT'),
fexml.xpath_from_root('/Trabajador/@NumeroDocumento'),
fexml.xpath_from_root('/InformacionGeneral/@TipoXML'),
tuple([self.software_pin]),
'/fe:NominaIndividual/InformacionGeneral/@Ambiente'
fexml.xpath_from_root('/InformacionGeneral/@Ambiente')
]
campos = fexml.get_elements_text_or_attributes(xpaths)
@ -111,9 +111,10 @@ class Trabajador:
fragment.set_attributes('./Trabajador',
NumeroDocumento = self.numero_documento)
class DIANNominaIndividual:
def __init__(self):
self.fexml = fe.FeXML('NominaIndividual', 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
class DIANNominaXML:
def __init__(self, tag_document):
self.tag_document = tag_document
self.fexml = fe.FeXML(tag_document, 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
# layout, la dian requiere que los elementos
# esten ordenados segun el anexo tecnico
@ -187,20 +188,23 @@ class DIANNominaIndividual:
if elem.get(key, None) is None:
return errors.append(err)
check_attribute('/fe:NominaIndividual/Periodo', 'FechaIngreso', 'se requiere Periodo')
check_attribute(
self.fexml.xpath_from_root('/Periodo'),
'FechaIngreso',
'se requiere Periodo')
check_element(
'/fe:NominaIndividual/Devengados/Basico',
self.fexml.xpath_from_root('/Devengados/Basico'),
'se requiere DevengadoBasico'
)
check_element(
'/fe:NominaIndividual/Deducciones/Salud',
self.fexml.xpath_from_root('/Deducciones/Salud'),
'se requiere DeduccionSalud'
)
check_element(
'/fe:NominaIndividual/Deducciones/FondoPension',
self.fexml.xpath_from_root('/Deducciones/FondoPension'),
'se requiere DeduccionFondoPension'
)
@ -220,17 +224,17 @@ class DIANNominaIndividual:
return self.fexml
def _comprobante_total(self):
devengados_total = self.fexml.get_element_text_or_attribute('/fe:NominaIndividual/DevengadosTotal', '0.0')
deducciones_total = self.fexml.get_element_text_or_attribute('/fe:NominaIndividual/DeduccionesTotal', '0.0')
devengados_total = self.fexml.get_element_text_or_attribute(self.fexml.xpath_from_root('/DevengadosTotal'), '0.0')
deducciones_total = self.fexml.get_element_text_or_attribute(self.fexml.xpath_from_root('/DeduccionesTotal'), '0.0')
comprobante_total = Amount(devengados_total) - Amount(deducciones_total)
self.fexml.set_element('/fe:NominaIndividual/ComprobanteTotal', str(round(comprobante_total, 2)))
self.fexml.set_element(self.fexml.xpath_from_root('/ComprobanteTotal'), str(round(comprobante_total, 2)))
def _deducciones_total(self):
xpaths = [
'/fe:NominaIndividual/Deducciones/Salud/@Deduccion',
'/fe:NominaIndividual/Deducciones/FondoPension/@Deduccion'
self.fexml.xpath_from_root('/Deducciones/Salud/@Deduccion'),
self.fexml.xpath_from_root('/Deducciones/FondoPension/@Deduccion')
]
deducciones = map(lambda valor: Amount(valor),
self._values_of_xpaths(xpaths))
@ -240,14 +244,14 @@ class DIANNominaIndividual:
for deduccion in deducciones:
deducciones_total += deduccion
self.fexml.set_element('/fe:NominaIndividual/DeduccionesTotal', str(round(deducciones_total, 2)))
self.fexml.set_element(f'/fe:{self.tag_document}/DeduccionesTotal', str(round(deducciones_total, 2)))
def _devengados_total(self):
xpaths = [
'/fe:NominaIndividual/Devengados/Basico/@SueldoTrabajado',
'/fe:NominaIndividual/Devengados/Transporte/@AuxilioTransporte',
'/fe:NominaIndividual/Devengados/Transporte/@ViaticoManuAlojS',
'/fe:NominaIndividual/Devengados/Transporte/@ViaticoManuAlojNS'
self.fexml.xpath_from_root('/Devengados/Basico/@SueldoTrabajado'),
self.fexml.xpath_from_root('/Devengados/Transporte/@AuxilioTransporte'),
self.fexml.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojS'),
self.fexml.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojNS')
]
devengados = map(lambda valor: Amount(valor),
self._values_of_xpaths(xpaths))
@ -256,7 +260,7 @@ class DIANNominaIndividual:
for devengado in devengados:
devengados_total += devengado
self.fexml.set_element('/fe:NominaIndividual/DevengadosTotal', str(round(devengados_total,2)))
self.fexml.set_element(self.fexml.xpath_from_root('/DevengadosTotal'), str(round(devengados_total,2)))
def _values_of_xpaths(self, xpaths):
xpaths_values_of_values = map(lambda val: self.fexml.get_element_text_or_attribute(val, multiple=True), xpaths)
@ -270,3 +274,15 @@ class DIANNominaIndividual:
xpaths_values.append(xpath_value)
return filter(lambda val: val is not None, xpaths_values)
class DIANNominaIndividual(DIANNominaXML):
def __init__(self):
super().__init__('NominaIndividual')
# TODO(bit4bit) confirmar que no tienen en comun con NominaIndividual
class DIANNominaIndividualDeAjuste(DIANNominaXML):
def __init__(self):
super().__init__('NominaIndividualDeAjuste')

View File

@ -370,3 +370,17 @@ def test_facho_xml_query_element_text_or_attribute():
assert xml.get_element_text_or_attribute('/root/A') == 'contenido'
assert xml.get_element_text_or_attribute('/root/A/@clave') == 'valor'
def test_facho_xml_build_xml_absolute():
xml = facho.FachoXML('root')
xpath = xml.xpath_from_root('/A')
assert xpath == '/root/A'
def test_facho_xml_build_xml_absolute_namespace():
xml = facho.FachoXML('{%s}root' % ('http://www.dian.gov.co/contratos/facturaelectronica/v1'),
nsmap={'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1'})
xpath = xml.xpath_from_root('/A')
assert xpath == '/fe:root/A'