oc-facho/facho/fe/nomina/__init__.py
bit4bit 74d98e249d se adiciona archivo faltante de nomina, y se agregan mas deducciones
FossilOrigin-Name: afb6c19bd3d7f71dd3ceff6e95cc39aaf65d15707eef8535d092e68b34c05c65
2021-11-05 02:09:21 +00:00

126 lines
3.8 KiB
Python

from .. import fe
from .. import form
from dataclasses import dataclass
class Amount(form.Amount):
pass
class Devengado:
pass
@dataclass
class DevengadoBasico(Devengado):
dias_trabajados: int
sueldo_trabajado: Amount
def apply(self, fragment):
fragment.find_or_create_element('./Basico')
fragment.set_attributes('/Basico',
# NIE069
DiasTrabajados = str(self.dias_trabajados),
# NIE070
SueldoTrabajado = str(self.sueldo_trabajado)
)
@dataclass
class DevengadoTransporte(Devengado):
auxilio_transporte: Amount = None
viatico_manutencion: Amount = None
viatico_manutencion_no_salarial: Amount = None
def apply(self, fragment):
fragment.set_element('./Transporte', None,
append_ = True,
# NIE071
AuxilioTransporte = self.auxilio_transporte,
# NIE072
ViaticoManuAlojS = self.viatico_manutencion,
# NIE073
ViaticoManuAlojNS = self.viatico_manutencion_no_salarial
)
class Deduccion:
pass
@dataclass
class DeduccionSalud(Deduccion):
porcentaje: Amount
deduccion: Amount
def apply(self, fragment):
fragment.set_element('./Salud', None,
append_ = True,
# NIE161
Porcentaje = self.porcentaje,
# NIE163
Deduccion = self.deduccion
)
@dataclass
class DeduccionFondoPension(Deduccion):
porcentaje: Amount
deduccion: Amount
def apply(self, fragment):
fragment.set_element('./FondoPension', None,
append_ = True,
# NIE164
Porcentaje = self.porcentaje,
# NIE166
Deduccion = self.deduccion
)
class DIANNominaIndividualError(Exception):
pass
class DIANNominaIndividual:
def __init__(self):
self.fexml = fe.FeXML('NominaIndividual', 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
# layout, la dian requiere que los elementos
# esten ordenados segun el anexo tecnico
self.fexml.placeholder_for('./Devengados/Basico')
self.fexml.placeholder_for('./Devengados/Transporte', optional=True)
self.devengados = self.fexml.fragment('./Devengados')
self.deducciones = self.fexml.fragment('./Deducciones')
def adicionar_devengado(self, devengado):
if not isinstance(devengado, Devengado):
raise ValueError('se espera tipo Devengado')
devengado.apply(self.devengados)
def adicionar_deduccion(self, deduccion):
if not isinstance(deduccion, Deduccion):
raise ValueError('se espera tipo Devengado')
deduccion.apply(self.deducciones)
def validate(self):
"""
Valida requisitos segun anexo tecnico
"""
errors = []
def add_error(xpath, msg):
if not self.fexml.exist_element(xpath):
errors.append(DIANNominaIndividualError(msg))
add_error('/fe:NominaIndividual/Devengados/Basico',
'se requiere DevengadoBasico')
add_error('/fe:NominaIndividual/Deducciones/Salud',
'se requiere DeduccionSalud')
add_error('/fe:NominaIndividual/Deducciones/FondoPension',
'se requiere DeduccionFondoPension')
return errors
def toFachoXML(self):
return self.fexml