se confirma calculo de devengadostotal,deduccionestotal y comprobantetotal
FossilOrigin-Name: 6c297492215eac22da511abe720a3922432711c194f1bd3b5543f23ff789f58c
This commit is contained in:
parent
8d17c282e3
commit
3ec31c36b4
@ -98,10 +98,13 @@ class LXMLBuilder:
|
||||
def set_text(self, elem, text):
|
||||
elem.text = text
|
||||
|
||||
def xpath(self, elem, xpath):
|
||||
def xpath(self, elem, xpath, multiple=False):
|
||||
elems = elem.xpath(xpath, namespaces=self.nsmap)
|
||||
if elems:
|
||||
return elems[0]
|
||||
if multiple:
|
||||
return elems
|
||||
else:
|
||||
return elems[0]
|
||||
|
||||
return None
|
||||
|
||||
@ -351,32 +354,63 @@ class FachoXML:
|
||||
self.builder.set_attribute(elem, k, str(v))
|
||||
return self
|
||||
|
||||
def get_element_attribute(self, xpath, attribute):
|
||||
elem = self.get_element(xpath)
|
||||
def get_element_attribute(self, xpath, attribute, multiple=False):
|
||||
elem = self.get_element(xpath, multiple=multiple)
|
||||
|
||||
if elem is None:
|
||||
raise ValueError("xpath %s not found" % (xpath))
|
||||
|
||||
return self.builder.get_attribute(elem, attribute)
|
||||
if multiple:
|
||||
vals = []
|
||||
for e in elem:
|
||||
vals.append(self.builder.get_attribute(e, attribute))
|
||||
return vals
|
||||
else:
|
||||
return self.builder.get_attribute(elem, attribute)
|
||||
|
||||
def get_element(self, xpath):
|
||||
def get_element(self, xpath, multiple=False):
|
||||
xpath = self.fragment_prefix + self._path_xpath_for(xpath)
|
||||
return self.builder.xpath(self.root, xpath)
|
||||
return self.builder.xpath(self.root, xpath, multiple=multiple)
|
||||
|
||||
def get_element_text(self, xpath, format_=str):
|
||||
def get_element_text(self, xpath, format_=str, multiple=False):
|
||||
xpath = self.fragment_prefix + self._path_xpath_for(xpath)
|
||||
elem = self.builder.xpath(self.root, xpath)
|
||||
text = self.builder.get_text(elem)
|
||||
return format_(text)
|
||||
elem = self.builder.xpath(self.root, xpath, multiple=multiple)
|
||||
if multiple:
|
||||
vals = []
|
||||
for e in elem:
|
||||
text = self.builder.get_text(e)
|
||||
if text is not None:
|
||||
vals.append(format_(text))
|
||||
return vals
|
||||
else:
|
||||
text = self.builder.get_text(elem)
|
||||
if text is None:
|
||||
return None
|
||||
return format_(text)
|
||||
|
||||
def get_element_text_or_attribute(self, xpath):
|
||||
def get_element_text_or_attribute(self, xpath, default=None, multiple=False):
|
||||
parts = xpath.split('/')
|
||||
is_attribute = parts[-1].startswith('@')
|
||||
if is_attribute:
|
||||
attribute_name = parts.pop(-1).lstrip('@')
|
||||
element_path = "/".join(parts)
|
||||
return self.get_element_attribute(element_path, attribute_name)
|
||||
try:
|
||||
val = self.get_element_attribute(element_path, attribute_name, multiple=multiple)
|
||||
if val is None:
|
||||
return default
|
||||
return val
|
||||
except KeyError:
|
||||
return default
|
||||
except ValueError:
|
||||
return default
|
||||
else:
|
||||
return self.get_element_text(xpath)
|
||||
try:
|
||||
val = self.get_element_text(xpath, multiple=multiple)
|
||||
if val is None:
|
||||
return default
|
||||
return val
|
||||
except ValueError:
|
||||
return default
|
||||
|
||||
def exist_element(self, xpath):
|
||||
elem = self.get_element(xpath)
|
||||
|
@ -204,33 +204,66 @@ class DIANNominaIndividual:
|
||||
return errors
|
||||
|
||||
def toFachoXML(self):
|
||||
self._devengados_total()
|
||||
self._deducciones_total()
|
||||
self._comprobante_total()
|
||||
|
||||
if self.informacion_general is not None:
|
||||
#TODO(bit4bit) acoplamiento temporal
|
||||
# es importante el orden de ejecucion
|
||||
self._devengados_total()
|
||||
self._deducciones_total()
|
||||
self._comprobante_total()
|
||||
|
||||
|
||||
self.informacion_general.post_apply(self.fexml, self.informacion_general_xml)
|
||||
|
||||
return self.fexml
|
||||
|
||||
def _comprobante_total(self):
|
||||
# TODO
|
||||
self.fexml.set_element('/fe:NominaIndividual/ComprobanteTotal', '2500000.00')
|
||||
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')
|
||||
|
||||
comprobante_total = Amount(devengados_total) - Amount(deducciones_total)
|
||||
|
||||
self.fexml.set_element('/fe:NominaIndividual/ComprobanteTotal', str(round(comprobante_total, 2)))
|
||||
|
||||
def _deducciones_total(self):
|
||||
# TODO
|
||||
self.fexml.set_element('/fe:NominaIndividual/DeduccionesTotal', '1000000.00')
|
||||
xpaths = [
|
||||
'/fe:NominaIndividual/Deducciones/Salud/@Deduccion',
|
||||
'/fe:NominaIndividual/Deducciones/FondoPension/@Deduccion'
|
||||
]
|
||||
deducciones = map(lambda valor: Amount(valor),
|
||||
self._values_of_xpaths(xpaths))
|
||||
|
||||
deducciones_total = Amount(0.0)
|
||||
|
||||
for deduccion in deducciones:
|
||||
deducciones_total += deduccion
|
||||
|
||||
self.fexml.set_element('/fe:NominaIndividual/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'
|
||||
]
|
||||
devengados = map(lambda valor: Amount(valor),
|
||||
[
|
||||
self.fexml.get_element_attribute('/fe:NominaIndividual/Devengados/Basico', 'SueldoTrabajado')
|
||||
]
|
||||
)
|
||||
self._values_of_xpaths(xpaths))
|
||||
|
||||
devengados_total = Amount(0.0)
|
||||
for devengado in devengados:
|
||||
devengados_total += devengado
|
||||
self.fexml.set_element('/fe:NominaIndividual/DevengadosTotal', round(devengados_total,2))
|
||||
|
||||
self.fexml.set_element('/fe:NominaIndividual/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)
|
||||
xpaths_values = []
|
||||
# toda esta carreta para hacer un aplano de lista
|
||||
for xpath_values in xpaths_values_of_values:
|
||||
if xpath_values is None:
|
||||
continue
|
||||
|
||||
for xpath_value in xpath_values:
|
||||
xpaths_values.append(xpath_value)
|
||||
|
||||
return filter(lambda val: val is not None, xpaths_values)
|
||||
|
@ -32,6 +32,41 @@ def test_adicionar_devengado_transporte():
|
||||
|
||||
assert xml.get_element_attribute('/fe:NominaIndividual/Devengados/Transporte', 'AuxilioTransporte') == '2000000.0'
|
||||
|
||||
def test_adicionar_devengado_comprobante_total():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = 60,
|
||||
sueldo_trabajado = fe.nomina.Amount(2_000_000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(19),
|
||||
deduccion = fe.nomina.Amount(1_000_000)
|
||||
))
|
||||
|
||||
|
||||
xml = nomina.toFachoXML()
|
||||
|
||||
assert xml.get_element_text('/fe:NominaIndividual/ComprobanteTotal') == '1000000.00'
|
||||
|
||||
def test_adicionar_devengado_comprobante_total_cero():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = 60,
|
||||
sueldo_trabajado = fe.nomina.Amount(1_000_000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(19),
|
||||
deduccion = fe.nomina.Amount(1_000_000)
|
||||
))
|
||||
|
||||
xml = nomina.toFachoXML()
|
||||
|
||||
assert xml.get_element_text('/fe:NominaIndividual/ComprobanteTotal') == '0.00'
|
||||
|
||||
def test_adicionar_devengado_transporte_muchos():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
@ -45,12 +80,16 @@ def test_adicionar_devengado_transporte_muchos():
|
||||
|
||||
xml = nomina.toFachoXML()
|
||||
print(xml)
|
||||
assert str(xml) == """<NominaIndividual xmlns:facho="http://git.disroot.org/Etrivial/facho" xmlns="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cdt="urn:DocumentInformation:names:specification:ubl:colombia:schema:xsd:DocumentInformationAggregateComponents-1" xmlns:clm54217="urn:un:unece:uncefact:codelist:specification:54217:2001" xmlns:clmIANAMIMEMediaType="urn:un:unece:uncefact:codelist:specification:IANAMIMEMediaType:2003" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:sts="dian:gov:co:facturaelectronica:Structures-2-1" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#"><NumeroSecuenciaXML/><InformacionGeneral/><Empleador/><Trabajador/><Devengados><Basico/><Transporte AuxilioTransporte="2000000.0"/><Transporte AuxilioTransporte="3000000.0"/></Devengados><Deducciones/></NominaIndividual>"""
|
||||
|
||||
assert xml.get_element_text('/fe:NominaIndividual/DevengadosTotal') == '5000000.00'
|
||||
|
||||
def test_adicionar_deduccion_salud():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = 60,
|
||||
sueldo_trabajado = fe.nomina.Amount(1000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(19),
|
||||
deduccion = fe.nomina.Amount(1000)
|
||||
@ -58,7 +97,7 @@ def test_adicionar_deduccion_salud():
|
||||
|
||||
xml = nomina.toFachoXML()
|
||||
print(xml)
|
||||
assert str(xml) == """<NominaIndividual xmlns:facho="http://git.disroot.org/Etrivial/facho" xmlns="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cdt="urn:DocumentInformation:names:specification:ubl:colombia:schema:xsd:DocumentInformationAggregateComponents-1" xmlns:clm54217="urn:un:unece:uncefact:codelist:specification:54217:2001" xmlns:clmIANAMIMEMediaType="urn:un:unece:uncefact:codelist:specification:IANAMIMEMediaType:2003" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:sts="dian:gov:co:facturaelectronica:Structures-2-1" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#"><NumeroSecuenciaXML/><InformacionGeneral/><Empleador/><Trabajador/><Devengados><Basico/></Devengados><Deducciones><Salud Porcentaje="19.0" Deduccion="1000.0"/></Deducciones></NominaIndividual>"""
|
||||
assert xml.get_element_text('/fe:NominaIndividual/DeduccionesTotal') == '1000.00'
|
||||
|
||||
def test_nomina_obligatorios_segun_anexo_tecnico():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
@ -98,6 +137,11 @@ def test_nomina_cune():
|
||||
sueldo_trabajado = fe.nomina.Amount(3_500_000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(19),
|
||||
deduccion = fe.nomina.Amount(1_000_000)
|
||||
))
|
||||
|
||||
xml = nomina.toFachoXML()
|
||||
assert xml.get_element_attribute('/fe:NominaIndividual/InformacionGeneral', 'CUNE') == '16560dc8956122e84ffb743c817fe7d494e058a44d9ca3fa4c234c268b4f766003253fbee7ea4af9682dd57210f3bac2'
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user