se adicionan mas campos requeridos para NominaIndividual
FossilOrigin-Name: 12c10fc4b3e4b69c665c8cde599a788266402977af62eed9b9a25459e1545f02
This commit is contained in:
parent
8deebbdfa4
commit
a34963ca49
@ -101,3 +101,4 @@ SubTipoTrabajador = CodeList(path_for_codelist('SubTipoTrabajador-2.1.gc'), 'cod
|
||||
TipoContrato = CodeList(path_for_codelist('TipoContrato-2.1.gc'), 'code', 'name')
|
||||
PeriodoNomina = CodeList(path_for_codelist('PeriodoNomina-2.1.gc'), 'code', 'name')
|
||||
TipoMoneda = CodeList(path_for_codelist('TipoMoneda-2.1.gc'), 'code', 'name')
|
||||
IdiomaISO6391 = CodeList(path_for_codelist('Idioma-2.1.gc'), 'iso-639-1', 'name')
|
||||
|
@ -17,23 +17,65 @@ from .deduccion import *
|
||||
from .trabajador import *
|
||||
from .empleador import *
|
||||
from .pago import *
|
||||
|
||||
from .pais import Pais
|
||||
from .departamento import Departamento
|
||||
from .municipio import Municipio
|
||||
from .lugar import Lugar
|
||||
|
||||
from .amount import Amount
|
||||
from .exception import *
|
||||
|
||||
@dataclass
|
||||
class NumeroSecuencia:
|
||||
consecutivo: int
|
||||
numero: str
|
||||
|
||||
def apply(self, fragment):
|
||||
fragment.set_attributes('./NumeroSecuenciaXML',
|
||||
# NIE011
|
||||
Consecutivo=self.consecutivo,
|
||||
# NIE012
|
||||
Numero = self.numero)
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class Proveedor:
|
||||
nit: str
|
||||
dv: int
|
||||
software_id: str
|
||||
software_sc: str
|
||||
|
||||
def apply(self, fragment):
|
||||
fragment.set_attributes('./ProveedorXML',
|
||||
# NIE017
|
||||
NIT=self.nit,
|
||||
# NIE018
|
||||
DV=self.dv,
|
||||
# NIE019
|
||||
SoftwareID=self.software_id,
|
||||
# NIE020
|
||||
SoftwareSC=self.software_sc,
|
||||
)
|
||||
|
||||
def post_apply(self, fexml, fragment):
|
||||
cune_xpath = fexml.xpath_from_root('/InformacionGeneral')
|
||||
cune = fexml.get_element_attribute(cune_xpath, 'CUNE')
|
||||
codigo_qr = f"https://catalogo‐vpfe.dian.gov.co/document/searchqr?documentkey={cune}"
|
||||
fragment.set_attributes('./ProveedorXML',
|
||||
CodigoQR=codigo_qr)
|
||||
|
||||
@dataclass
|
||||
class Metadata:
|
||||
secuencia: NumeroSecuencia
|
||||
# NIE013, NIE014, NIE015, NIE016
|
||||
lugar_generacion: Lugar
|
||||
proveedor: Proveedor
|
||||
|
||||
def apply(self, numero_secuencia_xml, lugar_generacion_xml, proveedor_xml):
|
||||
self.secuencia.apply(numero_secuencia_xml)
|
||||
self.lugar_generacion.apply(lugar_generacion_xml, './LugarGeneracionXML')
|
||||
self.proveedor.apply(proveedor_xml)
|
||||
|
||||
def post_apply(self, fexml, numero_secuencia_xml, lugar_generacion_xml, proveedor_xml):
|
||||
self.proveedor.post_apply(fexml, proveedor_xml)
|
||||
|
||||
@dataclass
|
||||
class PeriodoNomina:
|
||||
code: str
|
||||
@ -138,7 +180,12 @@ class DIANNominaXML:
|
||||
|
||||
# layout, la dian requiere que los elementos
|
||||
# esten ordenados segun el anexo tecnico
|
||||
self.fexml.placeholder_for('./UBLExtensions')
|
||||
self.fexml.placeholder_for('./Novedad', optional=True)
|
||||
self.fexml.placeholder_for('./Periodo')
|
||||
self.fexml.placeholder_for('./NumeroSecuenciaXML')
|
||||
self.fexml.placeholder_for('./LugarGeneracionXML')
|
||||
self.fexml.placeholder_for('./ProveedorXML')
|
||||
self.fexml.placeholder_for('./InformacionGeneral')
|
||||
self.fexml.placeholder_for('./Empleador')
|
||||
self.fexml.placeholder_for('./Trabajador')
|
||||
@ -149,6 +196,8 @@ class DIANNominaXML:
|
||||
|
||||
self.informacion_general_xml = self.fexml.fragment('./InformacionGeneral')
|
||||
self.numero_secuencia_xml = self.fexml.fragment('./NumeroSecuenciaXML')
|
||||
self.lugar_generacion_xml = self.fexml.fragment('./LugarGeneracionXML')
|
||||
self.proveedor_xml = self.fexml.fragment('./ProveedorXML')
|
||||
self.empleador = self.fexml.fragment('./Empleador')
|
||||
self.trabajador = self.fexml.fragment('./Trabajador')
|
||||
self.pago_xml = self.fexml.fragment('./Pago')
|
||||
@ -156,12 +205,14 @@ class DIANNominaXML:
|
||||
self.deducciones = self.fexml.fragment('./Deducciones')
|
||||
|
||||
self.informacion_general = None
|
||||
self.metadata = None
|
||||
|
||||
def asignar_numero_secuencia(self, secuencia):
|
||||
if not isinstance(secuencia, NumeroSecuencia):
|
||||
raise ValueError('se espera tipo NumeroSecuencia')
|
||||
secuencia.apply(self.numero_secuencia_xml)
|
||||
|
||||
def asignar_metadata(self, metadata):
|
||||
if not isinstance(metadata, Metadata):
|
||||
raise ValueError('se espera tipo Metadata')
|
||||
self.metadata = metadata
|
||||
self.metadata.apply(self.numero_secuencia_xml, self.lugar_generacion_xml, self.proveedor_xml)
|
||||
|
||||
def asignar_informacion_general(self, general):
|
||||
if not isinstance(general, InformacionGeneral):
|
||||
raise ValueError('se espera tipo InformacionGeneral')
|
||||
@ -246,13 +297,16 @@ class DIANNominaXML:
|
||||
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.informacion_general.post_apply(self.fexml, self.informacion_general_xml)
|
||||
|
||||
if self.metadata is not None:
|
||||
self.metadata.post_apply(self.fexml, self.numero_secuencia_xml, self.lugar_generacion_xml, self.proveedor_xml)
|
||||
|
||||
return self.fexml
|
||||
|
||||
def _comprobante_total(self):
|
||||
|
@ -109,12 +109,32 @@ def test_nomina_obligatorios_segun_anexo_tecnico():
|
||||
assert_error(errors, 'se requiere DeduccionSalud')
|
||||
assert_error(errors, 'se requiere DeduccionFondoPension')
|
||||
|
||||
def test_nomina_cune():
|
||||
def test_nomina_xml():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.asignar_numero_secuencia(fe.nomina.NumeroSecuencia(
|
||||
numero = 'N00001'
|
||||
))
|
||||
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||
secuencia=fe.nomina.NumeroSecuencia(
|
||||
numero = 'N00001',
|
||||
consecutivo=232
|
||||
),
|
||||
lugar_generacion=fe.nomina.Lugar(
|
||||
pais = fe.nomina.Pais(
|
||||
code = 'CO'
|
||||
),
|
||||
departamento = fe.nomina.Departamento(
|
||||
code = '05'
|
||||
),
|
||||
municipio = fe.nomina.Municipio(
|
||||
code = '05001'
|
||||
),
|
||||
),
|
||||
proveedor=fe.nomina.Proveedor(
|
||||
nit='999999',
|
||||
dv=2,
|
||||
software_id='xx',
|
||||
software_sc='yy'
|
||||
)
|
||||
))
|
||||
|
||||
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||
fecha_generacion = '2020-01-16',
|
||||
@ -179,6 +199,16 @@ def test_nomina_cune():
|
||||
# TODO(bit4bit) no logro generar cune igual al del anexo tecnico
|
||||
#assert xml.get_element_attribute('/fe:NominaIndividual/InformacionGeneral', 'CUNE') == '16560dc8956122e84ffb743c817fe7d494e058a44d9ca3fa4c234c268b4f766003253fbee7ea4af9682dd57210f3bac2'
|
||||
assert xml.get_element_attribute('/fe:NominaIndividual/InformacionGeneral', 'CUNE') == 'b8f9b6c24de07ffd92ea5467433a3b69357cfaffa7c19722db94b2e0eca41d057085a54f484b5da15ff585e773b0b0ab'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/NumeroSecuenciaXML/@Numero') == 'N00001'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/NumeroSecuenciaXML/@Consecutivo') == '232'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/LugarGeneracionXML/@Pais') == 'CO'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/LugarGeneracionXML/@DepartamentoEstado') == '05'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/LugarGeneracionXML/@MunicipioCiudad') == '05001'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/ProveedorXML/@NIT') == '999999'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/ProveedorXML/@DV') == '2'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/ProveedorXML/@SoftwareID') == 'xx'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/ProveedorXML/@SoftwareSC') == 'yy'
|
||||
assert xml.get_element_text_or_attribute('/fe:NominaIndividual/ProveedorXML/@CodigoQR') != None
|
||||
|
||||
def assert_error(errors, msg):
|
||||
for error in errors:
|
||||
|
Loading…
Reference in New Issue
Block a user