se adiciona archivo faltante de nomina, y se agregan mas deducciones
FossilOrigin-Name: afb6c19bd3d7f71dd3ceff6e95cc39aaf65d15707eef8535d092e68b34c05c65
This commit is contained in:
125
facho/fe/nomina/__init__.py
Normal file
125
facho/fe/nomina/__init__.py
Normal file
@@ -0,0 +1,125 @@
|
||||
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
|
||||
Reference in New Issue
Block a user