se extendie NominaIndividualDeAjuste de NominaIndividual
FossilOrigin-Name: 10b3af439bee9b932e4f5067bec0768af60e514f595e00ecb1bdf7c88c39afc1
This commit is contained in:
		| @@ -455,5 +455,16 @@ class FachoXML: | |||||||
|     def tostring(self, **kw): |     def tostring(self, **kw): | ||||||
|         return self.builder.tostring(self.root, **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): |     def __str__(self): | ||||||
|         return self.tostring() |         return self.tostring() | ||||||
|   | |||||||
| @@ -69,17 +69,17 @@ class InformacionGeneral: | |||||||
|         # generar cune |         # generar cune | ||||||
|         # ver 8.1.1.1 |         # ver 8.1.1.1 | ||||||
|         xpaths = [ |         xpaths = [ | ||||||
|             '/fe:NominaIndividual/NumeroSecuenciaXML/@Numero', |             fexml.xpath_from_root('/NumeroSecuenciaXML/@Numero'), | ||||||
|             '/fe:NominaIndividual/InformacionGeneral/@FechaGen', |             fexml.xpath_from_root('/InformacionGeneral/@FechaGen'), | ||||||
|             '/fe:NominaIndividual/InformacionGeneral/@HoraGen', |             fexml.xpath_from_root('/InformacionGeneral/@HoraGen'), | ||||||
|             '/fe:NominaIndividual/DevengadosTotal', |             fexml.xpath_from_root('/DevengadosTotal'), | ||||||
|             '/fe:NominaIndividual/DeduccionesTotal', |             fexml.xpath_from_root('/DeduccionesTotal'), | ||||||
|             '/fe:NominaIndividual/ComprobanteTotal', |             fexml.xpath_from_root('/ComprobanteTotal'), | ||||||
|             '/fe:NominaIndividual/Empleador/@NIT', |             fexml.xpath_from_root('/Empleador/@NIT'), | ||||||
|             '/fe:NominaIndividual/Trabajador/@NumeroDocumento', |             fexml.xpath_from_root('/Trabajador/@NumeroDocumento'), | ||||||
|             '/fe:NominaIndividual/InformacionGeneral/@TipoXML', |             fexml.xpath_from_root('/InformacionGeneral/@TipoXML'), | ||||||
|             tuple([self.software_pin]), |             tuple([self.software_pin]), | ||||||
|             '/fe:NominaIndividual/InformacionGeneral/@Ambiente' |             fexml.xpath_from_root('/InformacionGeneral/@Ambiente') | ||||||
|         ] |         ] | ||||||
|         campos = fexml.get_elements_text_or_attributes(xpaths) |         campos = fexml.get_elements_text_or_attributes(xpaths) | ||||||
|          |          | ||||||
| @@ -111,9 +111,10 @@ class Trabajador: | |||||||
|         fragment.set_attributes('./Trabajador', |         fragment.set_attributes('./Trabajador', | ||||||
|                                 NumeroDocumento = self.numero_documento) |                                 NumeroDocumento = self.numero_documento) | ||||||
|  |  | ||||||
| class DIANNominaIndividual: | class DIANNominaXML: | ||||||
|     def __init__(self): |     def __init__(self, tag_document): | ||||||
|         self.fexml = fe.FeXML('NominaIndividual', 'http://www.dian.gov.co/contratos/facturaelectronica/v1') |         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 |         # layout, la dian requiere que los elementos | ||||||
|         # esten ordenados segun el anexo tecnico |         # esten ordenados segun el anexo tecnico | ||||||
| @@ -187,20 +188,23 @@ class DIANNominaIndividual: | |||||||
|             if elem.get(key, None) is None: |             if elem.get(key, None) is None: | ||||||
|                 return errors.append(err) |                 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( |         check_element( | ||||||
|             '/fe:NominaIndividual/Devengados/Basico', |             self.fexml.xpath_from_root('/Devengados/Basico'), | ||||||
|             'se requiere DevengadoBasico' |             'se requiere DevengadoBasico' | ||||||
|         ) |         ) | ||||||
|          |          | ||||||
|         check_element( |         check_element( | ||||||
|             '/fe:NominaIndividual/Deducciones/Salud', |             self.fexml.xpath_from_root('/Deducciones/Salud'), | ||||||
|             'se requiere DeduccionSalud' |             'se requiere DeduccionSalud' | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         check_element( |         check_element( | ||||||
|             '/fe:NominaIndividual/Deducciones/FondoPension', |             self.fexml.xpath_from_root('/Deducciones/FondoPension'), | ||||||
|             'se requiere DeduccionFondoPension' |             'se requiere DeduccionFondoPension' | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -220,17 +224,17 @@ class DIANNominaIndividual: | |||||||
|         return self.fexml |         return self.fexml | ||||||
|  |  | ||||||
|     def _comprobante_total(self): |     def _comprobante_total(self): | ||||||
|         devengados_total = self.fexml.get_element_text_or_attribute('/fe:NominaIndividual/DevengadosTotal', '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('/fe:NominaIndividual/DeduccionesTotal', '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) |         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): |     def _deducciones_total(self): | ||||||
|         xpaths = [ |         xpaths = [ | ||||||
|             '/fe:NominaIndividual/Deducciones/Salud/@Deduccion', |             self.fexml.xpath_from_root('/Deducciones/Salud/@Deduccion'), | ||||||
|             '/fe:NominaIndividual/Deducciones/FondoPension/@Deduccion' |             self.fexml.xpath_from_root('/Deducciones/FondoPension/@Deduccion') | ||||||
|         ] |         ] | ||||||
|         deducciones = map(lambda valor: Amount(valor), |         deducciones = map(lambda valor: Amount(valor), | ||||||
|                           self._values_of_xpaths(xpaths)) |                           self._values_of_xpaths(xpaths)) | ||||||
| @@ -240,14 +244,14 @@ class DIANNominaIndividual: | |||||||
|         for deduccion in deducciones: |         for deduccion in deducciones: | ||||||
|             deducciones_total += deduccion |             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): |     def _devengados_total(self): | ||||||
|         xpaths = [ |         xpaths = [ | ||||||
|             '/fe:NominaIndividual/Devengados/Basico/@SueldoTrabajado', |             self.fexml.xpath_from_root('/Devengados/Basico/@SueldoTrabajado'), | ||||||
|             '/fe:NominaIndividual/Devengados/Transporte/@AuxilioTransporte', |             self.fexml.xpath_from_root('/Devengados/Transporte/@AuxilioTransporte'), | ||||||
|             '/fe:NominaIndividual/Devengados/Transporte/@ViaticoManuAlojS', |             self.fexml.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojS'), | ||||||
|             '/fe:NominaIndividual/Devengados/Transporte/@ViaticoManuAlojNS' |             self.fexml.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojNS') | ||||||
|         ] |         ] | ||||||
|         devengados = map(lambda valor: Amount(valor), |         devengados = map(lambda valor: Amount(valor), | ||||||
|                          self._values_of_xpaths(xpaths)) |                          self._values_of_xpaths(xpaths)) | ||||||
| @@ -256,7 +260,7 @@ class DIANNominaIndividual: | |||||||
|         for devengado in devengados: |         for devengado in devengados: | ||||||
|             devengados_total += devengado |             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): |     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_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) |                 xpaths_values.append(xpath_value) | ||||||
|  |  | ||||||
|         return filter(lambda val: val is not None, xpaths_values) |         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') | ||||||
|   | |||||||
| @@ -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') == 'contenido' | ||||||
|     assert xml.get_element_text_or_attribute('/root/A/@clave') == 'valor' |     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' | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user