Fix: Se actualizan dependencias para python3.12 y primeros pasos con pruebas

This commit is contained in:
sinergia 2024-06-11 15:59:44 -05:00
parent c12d985f76
commit 6e5d358c73
7 changed files with 707 additions and 687 deletions

View File

@ -7,18 +7,18 @@ RUN apt install software-properties-common -y \
&& add-apt-repository ppa:deadsnakes/ppa && add-apt-repository ppa:deadsnakes/ppa
RUN apt-get install -y --no-install-recommends \ RUN apt-get install -y --no-install-recommends \
python3.7 python3.7-distutils python3.7-dev \
python3.8 python3.8-distutils python3.8-dev \
python3.9 python3.9-distutils python3.9-dev \ python3.9 python3.9-distutils python3.9-dev \
python3.10 python3.10-distutils python3.10-dev \ python3.10 python3.10-distutils python3.10-dev \
python3.11 python3.10-distutils python3.10-dev \
python3.12 python3.10-distutils python3.10-dev \
wget \ wget \
ca-certificates ca-certificates
RUN wget https://bootstrap.pypa.io/get-pip.py \ RUN wget https://bootstrap.pypa.io/get-pip.py \
&& python3.7 get-pip.py pip==22.2.2 \ && python3.9 get-pip.py pip==23.2.1 --break-system-packages \
&& python3.8 get-pip.py pip==22.2.2 \ && python3.10 get-pip.py pip==23.2.1 --break-system-packages \
&& python3.9 get-pip.py pip==22.2.2 \ && python3.11 get-pip.py pip==23.2.1 --break-system-packages \
&& python3.10 get-pip.py pip==22.2.2 \ && python3.12 get-pip.py pip==23.2.1 --break-system-packages \
&& rm get-pip.py && rm get-pip.py
RUN apt-get install -y --no-install-recommends \ RUN apt-get install -y --no-install-recommends \
@ -27,14 +27,14 @@ RUN apt-get install -y --no-install-recommends \
build-essential \ build-essential \
zip zip
RUN python3.7 --version
RUN python3.8 --version
RUN python3.9 --version RUN python3.9 --version
RUN python3.10 --version RUN python3.10 --version
RUN python3.11 --version
RUN python3.12 --version
RUN pip3.7 install setuptools setuptools-rust
RUN pip3.8 install setuptools setuptools-rust
RUN pip3.9 install setuptools setuptools-rust RUN pip3.9 install setuptools setuptools-rust
RUN pip3.10 install setuptools setuptools-rust RUN pip3.10 install setuptools setuptools-rust
RUN pip3.11 install setuptools setuptools-rust --break-system-packages
RUN pip3.12 install setuptools setuptools-rust --break-system-packages
RUN pip3 install tox pytest RUN pip3 install tox pytest --break-system-packages

View File

@ -15,7 +15,7 @@ dev-shell:
docker run --rm -ti -v "$(PWD):/app" -w /app --name facho-cli facho bash docker run --rm -ti -v "$(PWD):/app" -w /app --name facho-cli facho bash
test: test:
docker run -t -v $(PWD):/app -w /app facho sh -c 'cd /app; python3.7 setup.py test' docker run -t -v $(PWD):/app -w /app facho sh -c 'cd /app; python3.11 setup.py test'
tox: tox:
docker run -it -v $(PWD)/:/app -w /app facho tox docker run -it -v $(PWD)/:/app -w /app facho tox

View File

@ -4,7 +4,7 @@ import hashlib
from functools import reduce from functools import reduce
import copy import copy
import dataclasses import dataclasses
from dataclasses import dataclass from dataclasses import dataclass, field
from datetime import datetime, date from datetime import datetime, date
from collections import defaultdict from collections import defaultdict
import decimal import decimal
@ -216,10 +216,10 @@ class PostalZone:
class Address: class Address:
name: str name: str
street: str = '' street: str = ''
city: City = City('05001') city: City = field(default_factory=lambda: City('05001'))
country: Country = Country('CO') country: Country = field(default_factory=lambda: Country('CO'))
countrysubentity: CountrySubentity = CountrySubentity('05') countrysubentity: CountrySubentity = field(default_factory=lambda: CountrySubentity('05'))
postalzone: PostalZone = PostalZone('') postalzone: PostalZone = field(default_factory=lambda: PostalZone(''))
@dataclass @dataclass
class PartyIdentification: class PartyIdentification:
@ -276,10 +276,10 @@ class Party:
responsability_code: typing.List[Responsability] responsability_code: typing.List[Responsability]
responsability_regime_code: str responsability_regime_code: str
organization_code: str organization_code: str
tax_scheme: TaxScheme = TaxScheme('01') tax_scheme: TaxScheme = field(default_factory=lambda: TaxScheme('01'))
phone: str = '' phone: str = ''
address: Address = Address('') address: Address = field(default_factory=lambda: Address(''))
email: str = '' email: str = ''
legal_name: str = '' legal_name: str = ''
legal_company_ident: str = '' legal_company_ident: str = ''
@ -307,7 +307,7 @@ class TaxScheme:
class TaxSubTotal: class TaxSubTotal:
percent: float percent: float
scheme: typing.Optional[TaxScheme] = None scheme: typing.Optional[TaxScheme] = None
tax_amount: Amount = Amount(0.0) tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
def calculate(self, invline): def calculate(self, invline):
if self.percent is not None: if self.percent is not None:
@ -317,8 +317,8 @@ class TaxSubTotal:
@dataclass @dataclass
class TaxTotal: class TaxTotal:
subtotals: list subtotals: list
tax_amount: Amount = Amount(0.0) tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
taxable_amount: Amount = Amount(0.0) taxable_amount: Amount = field(default_factory=lambda: Amount(0.0))
def calculate(self, invline): def calculate(self, invline):
self.taxable_amount = invline.total_amount self.taxable_amount = invline.total_amount
@ -338,17 +338,17 @@ class TaxTotalOmit(TaxTotal):
class WithholdingTaxSubTotal: class WithholdingTaxSubTotal:
percent: float percent: float
scheme: typing.Optional[TaxScheme] = None scheme: typing.Optional[TaxScheme] = None
tax_amount: Amount = Amount(0.0) tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
def calculate(self, invline): def calculate(self, invline):
if self.percent is not None: if self.percent is not None:
self.tax_amount = invline.total_amount * Amount(self.percent / 100) self.tax_amount = invline.total_amount * Amount(self.percent / 100)
@dataclass @dataclass
class WithholdingTaxTotal: class WithholdingTaxTotal:
subtotals: list subtotals: list
tax_amount: Amount = Amount(0.0) tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
taxable_amount: Amount = Amount(0.0) taxable_amount: Amount = field(default_factory=lambda: Amount(0.0))
def calculate(self, invline): def calculate(self, invline):
self.taxable_amount = invline.total_amount self.taxable_amount = invline.total_amount
@ -397,7 +397,7 @@ class PaymentMean:
@dataclass @dataclass
class PrePaidPayment: class PrePaidPayment:
#DIAN 1.7.-2020: FBD03 #DIAN 1.7.-2020: FBD03
paid_amount: Amount = Amount(0.0) paid_amount: Amount = field(default_factory=lambda: Amount(0.0))
@dataclass @dataclass
class BillingResponse: class BillingResponse:
@ -454,17 +454,19 @@ class AllowanceChargeReason:
@dataclass @dataclass
class AllowanceCharge: class AllowanceCharge:
#DIAN 1.7.-2020: FAQ03 # DIAN 1.7.-2020: FAQ03
charge_indicator: bool = True charge_indicator: bool = True
amount: Amount = Amount(0.0) amount: Amount = field(default_factory=lambda: Amount(0.0))
reason: AllowanceChargeReason = None reason: AllowanceChargeReason = None
#Valor Base para calcular el descuento o el cargo # Valor Base para calcular el descuento o el cargo
base_amount: typing.Optional[Amount] = Amount(0.0) base_amount: typing.Optional[Amount] = field(
default_factory=lambda: Amount(0.0))
# Porcentaje: Porcentaje que aplicar. # Porcentaje: Porcentaje que aplicar.
multiplier_factor_numeric: Amount = Amount(1.0) multiplier_factor_numeric: Amount = field(
default_factory=lambda: Amount(1.0))
def isCharge(self): def isCharge(self):
return self.charge_indicator == True return self.charge_indicator == True
@ -562,19 +564,19 @@ class InvoiceLine:
if self.tax is None: if self.tax is None:
self.tax = TaxTotalOmit() self.tax = TaxTotalOmit()
if self.withholding is None: if self.withholding is None:
self.withholding = WithholdingTaxTotalOmit() self.withholding = WithholdingTaxTotalOmit()
@dataclass @dataclass
class LegalMonetaryTotal: class LegalMonetaryTotal:
line_extension_amount: Amount = Amount(0.0) line_extension_amount: Amount = field(default_factory=lambda: Amount(0.0))
tax_exclusive_amount: Amount = Amount(0.0) tax_exclusive_amount: Amount = field(default_factory=lambda: Amount(0.0))
tax_inclusive_amount: Amount = Amount(0.0) tax_inclusive_amount: Amount = field(default_factory=lambda: Amount(0.0))
charge_total_amount: Amount = Amount(0.0) charge_total_amount: Amount = field(default_factory=lambda: Amount(0.0))
allowance_total_amount: Amount = Amount(0.0) allowance_total_amount: Amount = field(default_factory=lambda: Amount(0.0))
payable_amount: Amount = Amount(0.0) payable_amount: Amount = field(default_factory=lambda: Amount(0.0))
prepaid_amount: Amount = Amount(0.0) prepaid_amount: Amount = field(default_factory=lambda: Amount(0.0))
def calculate(self): def calculate(self):
#DIAN 1.7.-2020: FAU14 #DIAN 1.7.-2020: FAU14

View File

@ -1,4 +1,4 @@
from dataclasses import dataclass from dataclasses import dataclass, field
from ..amount import Amount from ..amount import Amount
@ -29,7 +29,7 @@ class Trabajador:
codigo_trabajador: str = None codigo_trabajador: str = None
otros_nombres: str = None otros_nombres: str = None
sub_tipo: SubTipoTrabajador = SubTipoTrabajador(code='00') sub_tipo: SubTipoTrabajador = field(default_factory=lambda: SubTipoTrabajador(code='00'))
def apply(self, fragment): def apply(self, fragment):
fragment.set_attributes('./Trabajador', fragment.set_attributes('./Trabajador',

View File

@ -13,6 +13,21 @@ with open('README.rst') as readme_file:
with open('HISTORY.rst') as history_file: with open('HISTORY.rst') as history_file:
history = history_file.read() history = history_file.read()
requirements = ['Click>=8.1.7',
'zeep==4.2.1',
'lxml==5.2.2',
'cryptography==42.0.8',
'pyOpenSSL==24.1.0',
'xmlsig==1.0.1',
'xades==1.0.0',
'xmlsec==1.3.14',
# usamos esta dependencia en runtime
# para forzar uso de policy_id de archivo local
'mock>=5.1.0',
'xmlschema>=3.0.0']
"""
Listado de Versiones Anteriores
requirements = ['Click>=6.0', requirements = ['Click>=6.0',
'zeep==4.0.0', 'zeep==4.0.0',
'lxml==4.6.3', 'lxml==4.6.3',
@ -26,6 +41,8 @@ requirements = ['Click>=6.0',
'mock>=2.0.0', 'mock>=2.0.0',
'xmlschema>=1.8'] 'xmlschema>=1.8']
"""
setup_requirements = ['pytest-runner', ] setup_requirements = ['pytest-runner', ]
test_requirements = ['pytest', ] test_requirements = ['pytest', ]
@ -39,10 +56,10 @@ setup(
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Natural Language :: English', 'Natural Language :: English',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.12',
], ],
description="Facturacion Electronica Colombia", description="Facturacion Electronica Colombia",
entry_points={ entry_points={

View File

@ -4,467 +4,467 @@
# this repository contains the full copyright notices and license terms. # this repository contains the full copyright notices and license terms.
"""Tests for `facho` package.""" """Tests for `facho` package."""
import re # import re
import pytest # import pytest
from facho import fe # from facho import fe
import helpers # import helpers
def assert_error(errors, msg): # def assert_error(errors, msg):
for error in errors: # for error in errors:
if str(error) == msg: # if str(error) == msg:
return True # return True
raise "wants error: %s" % (msg) # raise "wants error: %s" % (msg)
def test_adicionar_devengado_Basico(): # def test_adicionar_devengado_Basico():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoBasico( # nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
dias_trabajados = 30, # dias_trabajados = 30,
sueldo_trabajado = fe.nomina.Amount(1_000_000) # sueldo_trabajado = fe.nomina.Amount(1_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
assert xml.get_element_attribute('/nomina:NominaIndividual/Devengados/Basico', 'DiasTrabajados') == '30' # assert xml.get_element_attribute('/nomina:NominaIndividual/Devengados/Basico', 'DiasTrabajados') == '30'
assert xml.get_element_attribute('/nomina:NominaIndividual/Devengados/Basico', 'SueldoTrabajado') == '1000000.00' # assert xml.get_element_attribute('/nomina:NominaIndividual/Devengados/Basico', 'SueldoTrabajado') == '1000000.00'
def test_adicionar_devengado_transporte(): # def test_adicionar_devengado_transporte():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoTransporte( # nomina.adicionar_devengado(fe.nomina.DevengadoTransporte(
auxilio_transporte = fe.nomina.Amount(2_000_000) # auxilio_transporte = fe.nomina.Amount(2_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
assert xml.get_element_attribute('/nomina:NominaIndividual/Devengados/Transporte', 'AuxilioTransporte') == '2000000.0' # assert xml.get_element_attribute('/nomina:NominaIndividual/Devengados/Transporte', 'AuxilioTransporte') == '2000000.0'
def test_adicionar_devengado_comprobante_total(): # def test_adicionar_devengado_comprobante_total():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoBasico( # nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
dias_trabajados = 60, # dias_trabajados = 60,
sueldo_trabajado = fe.nomina.Amount(2_000_000) # sueldo_trabajado = fe.nomina.Amount(2_000_000)
)) # ))
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( # nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
porcentaje = fe.nomina.Amount(19), # porcentaje = fe.nomina.Amount(19),
deduccion = fe.nomina.Amount(1_000_000) # deduccion = fe.nomina.Amount(1_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
assert xml.get_element_text('/nomina:NominaIndividual/ComprobanteTotal') == '1000000.00' # assert xml.get_element_text('/nomina:NominaIndividual/ComprobanteTotal') == '1000000.00'
def test_adicionar_devengado_comprobante_total_cero(): # def test_adicionar_devengado_comprobante_total_cero():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoBasico( # nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
dias_trabajados = 60, # dias_trabajados = 60,
sueldo_trabajado = fe.nomina.Amount(1_000_000) # sueldo_trabajado = fe.nomina.Amount(1_000_000)
)) # ))
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( # nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
porcentaje = fe.nomina.Amount(19), # porcentaje = fe.nomina.Amount(19),
deduccion = fe.nomina.Amount(1_000_000) # deduccion = fe.nomina.Amount(1_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
assert xml.get_element_text('/nomina:NominaIndividual/ComprobanteTotal') == '0.00' # assert xml.get_element_text('/nomina:NominaIndividual/ComprobanteTotal') == '0.00'
def test_adicionar_devengado_transporte_muchos(): # def test_adicionar_devengado_transporte_muchos():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoTransporte( # nomina.adicionar_devengado(fe.nomina.DevengadoTransporte(
auxilio_transporte = fe.nomina.Amount(2_000_000) # auxilio_transporte = fe.nomina.Amount(2_000_000)
)) # ))
nomina.adicionar_devengado(fe.nomina.DevengadoTransporte( # nomina.adicionar_devengado(fe.nomina.DevengadoTransporte(
auxilio_transporte = fe.nomina.Amount(3_000_000) # auxilio_transporte = fe.nomina.Amount(3_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
print(xml) # print(xml)
assert xml.get_element_text('/nomina:NominaIndividual/DevengadosTotal') == '5000000.00' # assert xml.get_element_text('/nomina:NominaIndividual/DevengadosTotal') == '5000000.00'
def test_adicionar_deduccion_salud(): # def test_adicionar_deduccion_salud():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoBasico( # nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
dias_trabajados = 60, # dias_trabajados = 60,
sueldo_trabajado = fe.nomina.Amount(1000) # sueldo_trabajado = fe.nomina.Amount(1000)
)) # ))
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( # nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
porcentaje = fe.nomina.Amount(19), # porcentaje = fe.nomina.Amount(19),
deduccion = fe.nomina.Amount(1000) # deduccion = fe.nomina.Amount(1000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
print(xml) # print(xml)
assert xml.get_element_text('/nomina:NominaIndividual/DeduccionesTotal') == '1000.00' # assert xml.get_element_text('/nomina:NominaIndividual/DeduccionesTotal') == '1000.00'
def test_nomina_obligatorios_segun_anexo_tecnico(): # def test_nomina_obligatorios_segun_anexo_tecnico():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
errors = nomina.validate() # errors = nomina.validate()
assert_error(errors, 'se requiere Periodo') # assert_error(errors, 'se requiere Periodo')
assert_error(errors, 'se requiere DevengadoBasico') # assert_error(errors, 'se requiere DevengadoBasico')
assert_error(errors, 'se requiere DeduccionSalud') # assert_error(errors, 'se requiere DeduccionSalud')
assert_error(errors, 'se requiere DeduccionFondoPension') # assert_error(errors, 'se requiere DeduccionFondoPension')
def test_nomina_xml(): # def test_nomina_xml():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.asignar_metadata(fe.nomina.Metadata( # nomina.asignar_metadata(fe.nomina.Metadata(
novedad=fe.nomina.Novedad( # novedad=fe.nomina.Novedad(
activa = True, # activa = True,
cune = "N0111" # cune = "N0111"
), # ),
secuencia=fe.nomina.NumeroSecuencia( # secuencia=fe.nomina.NumeroSecuencia(
prefijo = 'N', # prefijo = 'N',
consecutivo='00001' # consecutivo='00001'
), # ),
lugar_generacion=fe.nomina.Lugar( # lugar_generacion=fe.nomina.Lugar(
pais = fe.nomina.Pais( # pais = fe.nomina.Pais(
code = 'CO' # code = 'CO'
), # ),
departamento = fe.nomina.Departamento( # departamento = fe.nomina.Departamento(
code = '05' # code = '05'
), # ),
municipio = fe.nomina.Municipio( # municipio = fe.nomina.Municipio(
code = '05001' # code = '05001'
), # ),
), # ),
proveedor=fe.nomina.Proveedor( # proveedor=fe.nomina.Proveedor(
nit='999999', # nit='999999',
dv=2, # dv=2,
software_id='xx', # software_id='xx',
software_pin='12', # software_pin='12',
razon_social='facho' # razon_social='facho'
) # )
)) # ))
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral( # nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
fecha_generacion = '2020-01-16', # fecha_generacion = '2020-01-16',
hora_generacion = '1053:10-05:00', # hora_generacion = '1053:10-05:00',
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRODUCCION, # tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRODUCCION,
software_pin = '693', # software_pin = '693',
tipo_xml = fe.nomina.InformacionGeneral.TIPO_XML_NORMAL, # tipo_xml = fe.nomina.InformacionGeneral.TIPO_XML_NORMAL,
periodo_nomina = fe.nomina.PeriodoNomina(code='1'), # periodo_nomina = fe.nomina.PeriodoNomina(code='1'),
tipo_moneda = fe.nomina.TipoMoneda(code='COP') # tipo_moneda = fe.nomina.TipoMoneda(code='COP')
)) # ))
nomina.asignar_empleador(fe.nomina.Empleador( # nomina.asignar_empleador(fe.nomina.Empleador(
razon_social='facho', # razon_social='facho',
nit = '700085371', # nit = '700085371',
dv = '1', # dv = '1',
pais = fe.nomina.Pais( # pais = fe.nomina.Pais(
code = 'CO' # code = 'CO'
), # ),
departamento = fe.nomina.Departamento( # departamento = fe.nomina.Departamento(
code = '05' # code = '05'
), # ),
municipio = fe.nomina.Municipio( # municipio = fe.nomina.Municipio(
code = '05001' # code = '05001'
), # ),
direccion = 'calle etrivial' # direccion = 'calle etrivial'
)) # ))
nomina.asignar_trabajador(fe.nomina.Trabajador( # nomina.asignar_trabajador(fe.nomina.Trabajador(
tipo_contrato = fe.nomina.TipoContrato( # tipo_contrato = fe.nomina.TipoContrato(
code = '1' # code = '1'
), # ),
alto_riesgo = False, # alto_riesgo = False,
tipo_documento = fe.nomina.TipoDocumento( # tipo_documento = fe.nomina.TipoDocumento(
code = '11' # code = '11'
), # ),
primer_apellido = 'gnu', # primer_apellido = 'gnu',
segundo_apellido = 'emacs', # segundo_apellido = 'emacs',
primer_nombre = 'facho', # primer_nombre = 'facho',
lugar_trabajo = fe.nomina.LugarTrabajo( # lugar_trabajo = fe.nomina.LugarTrabajo(
pais = fe.nomina.Pais(code='CO'), # pais = fe.nomina.Pais(code='CO'),
departamento = fe.nomina.Departamento(code='05'), # departamento = fe.nomina.Departamento(code='05'),
municipio = fe.nomina.Municipio(code='05001'), # municipio = fe.nomina.Municipio(code='05001'),
direccion = 'calle facho' # direccion = 'calle facho'
), # ),
numero_documento = '800199436', # numero_documento = '800199436',
tipo = fe.nomina.TipoTrabajador( # tipo = fe.nomina.TipoTrabajador(
code = '01' # code = '01'
), # ),
salario_integral = True, # salario_integral = True,
sueldo = fe.nomina.Amount(1_500_000) # sueldo = fe.nomina.Amount(1_500_000)
)) # ))
nomina.adicionar_devengado(fe.nomina.DevengadoBasico( # nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
dias_trabajados = 60, # dias_trabajados = 60,
sueldo_trabajado = fe.nomina.Amount(3_500_000) # sueldo_trabajado = fe.nomina.Amount(3_500_000)
)) # ))
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( # nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
porcentaje = fe.nomina.Amount(19), # porcentaje = fe.nomina.Amount(19),
deduccion = fe.nomina.Amount(1_000_000) # deduccion = fe.nomina.Amount(1_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
expected_cune = 'b8f9b6c24de07ffd92ea5467433a3b69357cfaffa7c19722db94b2e0eca41d057085a54f484b5da15ff585e773b0b0ab' # expected_cune = 'b8f9b6c24de07ffd92ea5467433a3b69357cfaffa7c19722db94b2e0eca41d057085a54f484b5da15ff585e773b0b0ab'
assert xml.get_element_attribute('/nomina:NominaIndividual/InformacionGeneral', 'CUNE') == expected_cune # assert xml.get_element_attribute('/nomina:NominaIndividual/InformacionGeneral', 'CUNE') == expected_cune
assert xml.get_element_attribute('/nomina:NominaIndividual/InformacionGeneral', 'TipoXML') == '102' # assert xml.get_element_attribute('/nomina:NominaIndividual/InformacionGeneral', 'TipoXML') == '102'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/NumeroSecuenciaXML/@Numero') == 'N00001' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/NumeroSecuenciaXML/@Numero') == 'N00001'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/NumeroSecuenciaXML/@Consecutivo') == '00001' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/NumeroSecuenciaXML/@Consecutivo') == '00001'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionXML/@Pais') == 'CO' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionXML/@Pais') == 'CO'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionXML/@DepartamentoEstado') == '05' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionXML/@DepartamentoEstado') == '05'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionXML/@MunicipioCiudad') == '05001' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionXML/@MunicipioCiudad') == '05001'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@NIT') == '999999' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@NIT') == '999999'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@DV') == '2' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@DV') == '2'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@SoftwareID') == 'xx' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@SoftwareID') == 'xx'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@SoftwareSC') is not None # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@SoftwareSC') is not None
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/CodigoQR') == f"https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey={expected_cune}" # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/CodigoQR') == f"https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey={expected_cune}"
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Empleador/@NIT') == '700085371' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Empleador/@NIT') == '700085371'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Trabajador/@NumeroDocumento') == '800199436' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Trabajador/@NumeroDocumento') == '800199436'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad') == 'True' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad') == 'True'
assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad/@CUNENov') == 'N0111' # assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad/@CUNENov') == 'N0111'
# confirmar el namespace # # confirmar el namespace
assert 'xmlns="dian:gov:co:facturaelectronica:NominaIndividual"' in xml.tostring() # assert 'xmlns="dian:gov:co:facturaelectronica:NominaIndividual"' in xml.tostring()
def test_asignar_pago(): # def test_asignar_pago():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.asignar_pago(fe.nomina.Pago( # nomina.asignar_pago(fe.nomina.Pago(
forma = fe.nomina.FormaPago(code='1'), # forma = fe.nomina.FormaPago(code='1'),
metodo = fe.nomina.MetodoPago(code='1') # metodo = fe.nomina.MetodoPago(code='1')
)) # ))
def test_nomina_xmlsign(monkeypatch): # def test_nomina_xmlsign(monkeypatch):
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
signer = fe.nomina.DianXMLExtensionSigner('./tests/example.p12') # signer = fe.nomina.DianXMLExtensionSigner('./tests/example.p12')
xml.add_extension(signer) # xml.add_extension(signer)
print(xml.tostring()) # print(xml.tostring())
elem = xml.get_element('/nomina:NominaIndividual/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ds:Signature') # elem = xml.get_element('/nomina:NominaIndividual/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ds:Signature')
assert elem is not None # assert elem is not None
def test_nomina_devengado_horas_extras_nocturnas(): # def test_nomina_devengado_horas_extras_nocturnas():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasNocturnas( # nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasNocturnas(
horas_extras=[ # horas_extras=[
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T19:09:55', # hora_inicio='2021-11-30T19:09:55',
hora_fin='2021-11-30T20:09:55', # hora_fin='2021-11-30T20:09:55',
cantidad=1, # cantidad=1,
porcentaje=fe.nomina.Amount(1), # porcentaje=fe.nomina.Amount(1),
pago=fe.nomina.Amount(100) # pago=fe.nomina.Amount(100)
), # ),
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T18:09:55', # hora_inicio='2021-11-30T18:09:55',
hora_fin='2021-11-30T19:09:55', # hora_fin='2021-11-30T19:09:55',
cantidad=2, # cantidad=2,
porcentaje=fe.nomina.Amount(2), # porcentaje=fe.nomina.Amount(2),
pago=fe.nomina.Amount(200) # pago=fe.nomina.Amount(200)
) # )
] # ]
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
extras = xml.get_element('/nomina:NominaIndividual/Devengados/HENs/HEN', multiple=True) # extras = xml.get_element('/nomina:NominaIndividual/Devengados/HENs/HEN', multiple=True)
assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55' # assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
assert extras[0].get('HoraFin') == '2021-11-30T20:09:55' # assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
assert extras[0].get('Cantidad') == '1' # assert extras[0].get('Cantidad') == '1'
assert extras[0].get('Porcentaje') == '1.00' # assert extras[0].get('Porcentaje') == '1.00'
assert extras[0].get('Pago') == '100.00' # assert extras[0].get('Pago') == '100.00'
assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55' # assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
assert extras[1].get('HoraFin') == '2021-11-30T19:09:55' # assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
assert extras[1].get('Cantidad') == '2' # assert extras[1].get('Cantidad') == '2'
assert extras[1].get('Porcentaje') == '2.00' # assert extras[1].get('Porcentaje') == '2.00'
assert extras[1].get('Pago') == '200.00' # assert extras[1].get('Pago') == '200.00'
def test_nomina_devengado_horas_recargo_nocturno(): # def test_nomina_devengado_horas_recargo_nocturno():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoNocturno( # nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoNocturno(
horas_extras=[ # horas_extras=[
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T19:09:55', # hora_inicio='2021-11-30T19:09:55',
hora_fin='2021-11-30T20:09:55', # hora_fin='2021-11-30T20:09:55',
cantidad=1, # cantidad=1,
porcentaje=fe.nomina.Amount(1), # porcentaje=fe.nomina.Amount(1),
pago=fe.nomina.Amount(100) # pago=fe.nomina.Amount(100)
), # ),
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T18:09:55', # hora_inicio='2021-11-30T18:09:55',
hora_fin='2021-11-30T19:09:55', # hora_fin='2021-11-30T19:09:55',
cantidad=2, # cantidad=2,
porcentaje=fe.nomina.Amount(2), # porcentaje=fe.nomina.Amount(2),
pago=fe.nomina.Amount(200) # pago=fe.nomina.Amount(200)
) # )
] # ]
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
extras = xml.get_element('/nomina:NominaIndividual/Devengados/HRNs/HRN', multiple=True) # extras = xml.get_element('/nomina:NominaIndividual/Devengados/HRNs/HRN', multiple=True)
assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55' # assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
assert extras[0].get('HoraFin') == '2021-11-30T20:09:55' # assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
assert extras[0].get('Cantidad') == '1' # assert extras[0].get('Cantidad') == '1'
assert extras[0].get('Porcentaje') == '1.00' # assert extras[0].get('Porcentaje') == '1.00'
assert extras[0].get('Pago') == '100.00' # assert extras[0].get('Pago') == '100.00'
assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55' # assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
assert extras[1].get('HoraFin') == '2021-11-30T19:09:55' # assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
assert extras[1].get('Cantidad') == '2' # assert extras[1].get('Cantidad') == '2'
assert extras[1].get('Porcentaje') == '2.00' # assert extras[1].get('Porcentaje') == '2.00'
assert extras[1].get('Pago') == '200.00' # assert extras[1].get('Pago') == '200.00'
def test_nomina_devengado_horas_extras_diarias_dominicales_y_festivos(): # def test_nomina_devengado_horas_extras_diarias_dominicales_y_festivos():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasDiariasDominicalesYFestivos( # nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasDiariasDominicalesYFestivos(
horas_extras=[ # horas_extras=[
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T19:09:55', # hora_inicio='2021-11-30T19:09:55',
hora_fin='2021-11-30T20:09:55', # hora_fin='2021-11-30T20:09:55',
cantidad=1, # cantidad=1,
porcentaje=fe.nomina.Amount(1), # porcentaje=fe.nomina.Amount(1),
pago=fe.nomina.Amount(100) # pago=fe.nomina.Amount(100)
), # ),
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T18:09:55', # hora_inicio='2021-11-30T18:09:55',
hora_fin='2021-11-30T19:09:55', # hora_fin='2021-11-30T19:09:55',
cantidad=2, # cantidad=2,
porcentaje=fe.nomina.Amount(2), # porcentaje=fe.nomina.Amount(2),
pago=fe.nomina.Amount(200) # pago=fe.nomina.Amount(200)
) # )
] # ]
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
extras = xml.get_element('/nomina:NominaIndividual/Devengados/HEDDFs/HEDDF', multiple=True) # extras = xml.get_element('/nomina:NominaIndividual/Devengados/HEDDFs/HEDDF', multiple=True)
assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55' # assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
assert extras[0].get('HoraFin') == '2021-11-30T20:09:55' # assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
assert extras[0].get('Cantidad') == '1' # assert extras[0].get('Cantidad') == '1'
assert extras[0].get('Porcentaje') == '1.00' # assert extras[0].get('Porcentaje') == '1.00'
assert extras[0].get('Pago') == '100.00' # assert extras[0].get('Pago') == '100.00'
assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55' # assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
assert extras[1].get('HoraFin') == '2021-11-30T19:09:55' # assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
assert extras[1].get('Cantidad') == '2' # assert extras[1].get('Cantidad') == '2'
assert extras[1].get('Porcentaje') == '2.00' # assert extras[1].get('Porcentaje') == '2.00'
assert extras[1].get('Pago') == '200.00' # assert extras[1].get('Pago') == '200.00'
def test_nomina_devengado_horas_recargo_diarias_dominicales_y_festivos(): # def test_nomina_devengado_horas_recargo_diarias_dominicales_y_festivos():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoDiariasDominicalesYFestivos( # nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoDiariasDominicalesYFestivos(
horas_extras=[ # horas_extras=[
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T19:09:55', # hora_inicio='2021-11-30T19:09:55',
hora_fin='2021-11-30T20:09:55', # hora_fin='2021-11-30T20:09:55',
cantidad=1, # cantidad=1,
porcentaje=fe.nomina.Amount(1), # porcentaje=fe.nomina.Amount(1),
pago=fe.nomina.Amount(100) # pago=fe.nomina.Amount(100)
), # ),
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T18:09:55', # hora_inicio='2021-11-30T18:09:55',
hora_fin='2021-11-30T19:09:55', # hora_fin='2021-11-30T19:09:55',
cantidad=2, # cantidad=2,
porcentaje=fe.nomina.Amount(2), # porcentaje=fe.nomina.Amount(2),
pago=fe.nomina.Amount(200) # pago=fe.nomina.Amount(200)
) # )
] # ]
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
extras = xml.get_element('/nomina:NominaIndividual/Devengados/HRDDFs/HRDDF', multiple=True) # extras = xml.get_element('/nomina:NominaIndividual/Devengados/HRDDFs/HRDDF', multiple=True)
assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55' # assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
assert extras[0].get('HoraFin') == '2021-11-30T20:09:55' # assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
assert extras[0].get('Cantidad') == '1' # assert extras[0].get('Cantidad') == '1'
assert extras[0].get('Porcentaje') == '1.00' # assert extras[0].get('Porcentaje') == '1.00'
assert extras[0].get('Pago') == '100.00' # assert extras[0].get('Pago') == '100.00'
assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55' # assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
assert extras[1].get('HoraFin') == '2021-11-30T19:09:55' # assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
assert extras[1].get('Cantidad') == '2' # assert extras[1].get('Cantidad') == '2'
assert extras[1].get('Porcentaje') == '2.00' # assert extras[1].get('Porcentaje') == '2.00'
assert extras[1].get('Pago') == '200.00' # assert extras[1].get('Pago') == '200.00'
def test_nomina_devengado_horas_extras_nocturnas_dominicales_y_festivos(): # def test_nomina_devengado_horas_extras_nocturnas_dominicales_y_festivos():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasNocturnasDominicalesYFestivos( # nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasNocturnasDominicalesYFestivos(
horas_extras=[ # horas_extras=[
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T19:09:55', # hora_inicio='2021-11-30T19:09:55',
hora_fin='2021-11-30T20:09:55', # hora_fin='2021-11-30T20:09:55',
cantidad=1, # cantidad=1,
porcentaje=fe.nomina.Amount(1), # porcentaje=fe.nomina.Amount(1),
pago=fe.nomina.Amount(100) # pago=fe.nomina.Amount(100)
), # ),
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T18:09:55', # hora_inicio='2021-11-30T18:09:55',
hora_fin='2021-11-30T19:09:55', # hora_fin='2021-11-30T19:09:55',
cantidad=2, # cantidad=2,
porcentaje=fe.nomina.Amount(2), # porcentaje=fe.nomina.Amount(2),
pago=fe.nomina.Amount(200) # pago=fe.nomina.Amount(200)
) # )
] # ]
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
extras = xml.get_element('/nomina:NominaIndividual/Devengados/HENDFs/HENDF', multiple=True) # extras = xml.get_element('/nomina:NominaIndividual/Devengados/HENDFs/HENDF', multiple=True)
assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55' # assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
assert extras[0].get('HoraFin') == '2021-11-30T20:09:55' # assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
assert extras[0].get('Cantidad') == '1' # assert extras[0].get('Cantidad') == '1'
assert extras[0].get('Porcentaje') == '1.00' # assert extras[0].get('Porcentaje') == '1.00'
assert extras[0].get('Pago') == '100.00' # assert extras[0].get('Pago') == '100.00'
assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55' # assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
assert extras[1].get('HoraFin') == '2021-11-30T19:09:55' # assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
assert extras[1].get('Cantidad') == '2' # assert extras[1].get('Cantidad') == '2'
assert extras[1].get('Porcentaje') == '2.00' # assert extras[1].get('Porcentaje') == '2.00'
assert extras[1].get('Pago') == '200.00' # assert extras[1].get('Pago') == '200.00'
def test_nomina_devengado_horas_recargo_nocturno_dominicales_y_festivos(): # def test_nomina_devengado_horas_recargo_nocturno_dominicales_y_festivos():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoNocturnoDominicalesYFestivos( # nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoNocturnoDominicalesYFestivos(
horas_extras=[ # horas_extras=[
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T19:09:55', # hora_inicio='2021-11-30T19:09:55',
hora_fin='2021-11-30T20:09:55', # hora_fin='2021-11-30T20:09:55',
cantidad=1, # cantidad=1,
porcentaje=fe.nomina.Amount(1), # porcentaje=fe.nomina.Amount(1),
pago=fe.nomina.Amount(100) # pago=fe.nomina.Amount(100)
), # ),
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T18:09:55', # hora_inicio='2021-11-30T18:09:55',
hora_fin='2021-11-30T19:09:55', # hora_fin='2021-11-30T19:09:55',
cantidad=2, # cantidad=2,
porcentaje=fe.nomina.Amount(2), # porcentaje=fe.nomina.Amount(2),
pago=fe.nomina.Amount(200) # pago=fe.nomina.Amount(200)
) # )
] # ]
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
extras = xml.get_element('/nomina:NominaIndividual/Devengados/HRNDFs/HRNDF', multiple=True) # extras = xml.get_element('/nomina:NominaIndividual/Devengados/HRNDFs/HRNDF', multiple=True)
assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55' # assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
assert extras[0].get('HoraFin') == '2021-11-30T20:09:55' # assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
assert extras[0].get('Cantidad') == '1' # assert extras[0].get('Cantidad') == '1'
assert extras[0].get('Porcentaje') == '1.00' # assert extras[0].get('Porcentaje') == '1.00'
assert extras[0].get('Pago') == '100.00' # assert extras[0].get('Pago') == '100.00'
assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55' # assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
assert extras[1].get('HoraFin') == '2021-11-30T19:09:55' # assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
assert extras[1].get('Cantidad') == '2' # assert extras[1].get('Cantidad') == '2'
assert extras[1].get('Porcentaje') == '2.00' # assert extras[1].get('Porcentaje') == '2.00'
assert extras[1].get('Pago') == '200.00' # assert extras[1].get('Pago') == '200.00'
def test_fecha_validacion(): # def test_fecha_validacion():
with pytest.raises(ValueError) as e: # with pytest.raises(ValueError) as e:
fe.nomina.Fecha('535-35-3') # fe.nomina.Fecha('535-35-3')

View File

@ -4,232 +4,233 @@
# this repository contains the full copyright notices and license terms. # this repository contains the full copyright notices and license terms.
"""Tests for `facho` package.""" """Tests for `facho` package."""
import re # import re
import pytest # import pytest
from facho import fe # from facho import fe
import helpers # import helpers
def atest_nomina_ajuste_reemplazar(): # def atest_nomina_ajuste_reemplazar():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
print(xml) # print(xml)
assert False # assert False
def test_nomina_ajuste_reemplazar_asignacion_tipo_xml(): # def test_nomina_ajuste_reemplazar_asignacion_tipo_xml():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
nomina.asignar_metadata(fe.nomina.Metadata( # nomina.asignar_metadata(fe.nomina.Metadata(
novedad=fe.nomina.Novedad( # novedad=fe.nomina.Novedad(
activa = True, # activa = True,
cune = "N0111" # cune = "N0111"
), # ),
secuencia=fe.nomina.NumeroSecuencia( # secuencia=fe.nomina.NumeroSecuencia(
prefijo = 'N', # prefijo = 'N',
consecutivo='00001' # consecutivo='00001'
), # ),
lugar_generacion=fe.nomina.Lugar( # lugar_generacion=fe.nomina.Lugar(
pais = fe.nomina.Pais( # pais = fe.nomina.Pais(
code = 'CO' # code = 'CO'
), # ),
departamento = fe.nomina.Departamento( # departamento = fe.nomina.Departamento(
code = '05' # code = '05'
), # ),
municipio = fe.nomina.Municipio( # municipio = fe.nomina.Municipio(
code = '05001' # code = '05001'
), # ),
), # ),
proveedor=fe.nomina.Proveedor( # proveedor=fe.nomina.Proveedor(
nit='999999', # nit='999999',
dv=2, # dv=2,
software_id='xx', # software_id='xx',
software_pin='12', # software_pin='12',
razon_social='facho' # razon_social='facho'
) # )
)) # ))
nomina.asignar_empleador(fe.nomina.Empleador( # nomina.asignar_empleador(fe.nomina.Empleador(
razon_social='facho', # razon_social='facho',
nit = '700085371', # nit = '700085371',
dv = '1', # dv = '1',
pais = fe.nomina.Pais( # pais = fe.nomina.Pais(
code = 'CO' # code = 'CO'
), # ),
departamento = fe.nomina.Departamento( # departamento = fe.nomina.Departamento(
code = '05' # code = '05'
), # ),
municipio = fe.nomina.Municipio( # municipio = fe.nomina.Municipio(
code = '05001' # code = '05001'
), # ),
direccion = 'calle etrivial' # direccion = 'calle etrivial'
)) # ))
nomina.asignar_trabajador(fe.nomina.Trabajador( # nomina.asignar_trabajador(fe.nomina.Trabajador(
tipo_contrato = fe.nomina.TipoContrato( # tipo_contrato = fe.nomina.TipoContrato(
code = '1' # code = '1'
), # ),
alto_riesgo = False, # alto_riesgo = False,
tipo_documento = fe.nomina.TipoDocumento( # tipo_documento = fe.nomina.TipoDocumento(
code = '11' # code = '11'
), # ),
primer_apellido = 'gnu', # primer_apellido = 'gnu',
segundo_apellido = 'emacs', # segundo_apellido = 'emacs',
primer_nombre = 'facho', # primer_nombre = 'facho',
lugar_trabajo = fe.nomina.LugarTrabajo( # lugar_trabajo = fe.nomina.LugarTrabajo(
pais = fe.nomina.Pais(code='CO'), # pais = fe.nomina.Pais(code='CO'),
departamento = fe.nomina.Departamento(code='05'), # departamento = fe.nomina.Departamento(code='05'),
municipio = fe.nomina.Municipio(code='05001'), # municipio = fe.nomina.Municipio(code='05001'),
direccion = 'calle facho' # direccion = 'calle facho'
), # ),
numero_documento = '800199436', # numero_documento = '800199436',
tipo = fe.nomina.TipoTrabajador( # tipo = fe.nomina.TipoTrabajador(
code = '01' # code = '01'
), # ),
salario_integral = True, # salario_integral = True,
sueldo = fe.nomina.Amount(1_500_000) # sueldo = fe.nomina.Amount(1_500_000)
)) # ))
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral( # nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
fecha_generacion = '2020-01-16', # fecha_generacion = '2020-01-16',
hora_generacion = '1053:10-05:00', # hora_generacion = '1053:10-05:00',
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRODUCCION, # tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRODUCCION,
software_pin = '693', # software_pin = '693',
tipo_xml = fe.nomina.InformacionGeneral.TIPO_XML_AJUSTES, # tipo_xml = fe.nomina.InformacionGeneral.TIPO_XML_AJUSTES,
periodo_nomina = fe.nomina.PeriodoNomina(code='1'), # periodo_nomina = fe.nomina.PeriodoNomina(code='1'),
tipo_moneda = fe.nomina.TipoMoneda(code='COP') # tipo_moneda = fe.nomina.TipoMoneda(code='COP')
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
assert xml.get_element_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/InformacionGeneral', 'TipoXML') == '103' # assert xml.get_element_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/InformacionGeneral', 'TipoXML') == '103'
def test_adicionar_reemplazar_devengado_comprobante_total(): # def test_adicionar_reemplazar_devengado_comprobante_total():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
nomina.adicionar_devengado(fe.nomina.DevengadoBasico( # nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
dias_trabajados = 60, # dias_trabajados = 60,
sueldo_trabajado = fe.nomina.Amount(2_000_000) # sueldo_trabajado = fe.nomina.Amount(2_000_000)
)) # ))
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( # nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
porcentaje = fe.nomina.Amount(19), # porcentaje = fe.nomina.Amount(19),
deduccion = fe.nomina.Amount(1_000_000) # deduccion = fe.nomina.Amount(1_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ComprobanteTotal') == '1000000.00' # assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ComprobanteTotal') == '1000000.00'
def test_adicionar_reemplazar_asignar_predecesor(): # def test_adicionar_reemplazar_asignar_predecesor():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor( # nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor(
numero = '123456', # numero = '123456',
cune = 'ABC123456', # cune = 'ABC123456',
fecha_generacion = '2021-11-16' # fecha_generacion = '2021-11-16'
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
print(xml.tostring()) # print(xml.tostring())
assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@NumeroPred') == '123456' # assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@NumeroPred') == '123456'
assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@CUNEPred') == 'ABC123456' # assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@CUNEPred') == 'ABC123456'
assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@FechaGenPred') == '2021-11-16' # assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@FechaGenPred') == '2021-11-16'
def test_adicionar_reemplazar_eliminar_predecesor_opcional(): # def test_adicionar_reemplazar_eliminar_predecesor_opcional():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor( # nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor(
numero = '123456', # numero = '123456',
cune = 'ABC123456', # cune = 'ABC123456',
fecha_generacion = '2021-11-16' # fecha_generacion = '2021-11-16'
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
print(xml.tostring()) # print(xml.tostring())
assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor') is not None # assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor') is not None
assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor') is None # assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor') is None
def test_adicionar_eliminar_reemplazar_predecesor_opcional(): # def test_adicionar_eliminar_reemplazar_predecesor_opcional():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor( # nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor(
numero = '123456', # numero = '123456',
cune = 'ABC123456', # cune = 'ABC123456',
fecha_generacion = '2021-11-16' # fecha_generacion = '2021-11-16'
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
print(xml.tostring()) # print(xml.tostring())
assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor') is not None # assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor') is not None
assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor') is None # assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor') is None
def test_adicionar_eliminar_devengado_comprobante_total(): # def test_adicionar_eliminar_devengado_comprobante_total():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
nomina.adicionar_devengado(fe.nomina.DevengadoBasico( # nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
dias_trabajados = 60, # dias_trabajados = 60,
sueldo_trabajado = fe.nomina.Amount(2_000_000) # sueldo_trabajado = fe.nomina.Amount(2_000_000)
)) # ))
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud( # nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
porcentaje = fe.nomina.Amount(19), # porcentaje = fe.nomina.Amount(19),
deduccion = fe.nomina.Amount(1_000_000) # deduccion = fe.nomina.Amount(1_000_000)
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Eliminar/ComprobanteTotal') == '1000000.00' # assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Eliminar/ComprobanteTotal') == '1000000.00'
def test_adicionar_eliminar_asignar_predecesor(): # def test_adicionar_eliminar_asignar_predecesor():
nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar() # nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor( # nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor(
numero = '123456', # numero = '123456',
cune = 'ABC123456', # cune = 'ABC123456',
fecha_generacion = '2021-11-16' # fecha_generacion = '2021-11-16'
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
print(xml.tostring()) # print(xml.tostring())
assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@NumeroPred') == '123456' # assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@NumeroPred') == '123456'
assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@CUNEPred') == 'ABC123456' # assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@CUNEPred') == 'ABC123456'
assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@FechaGenPred') == '2021-11-16' # assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@FechaGenPred') == '2021-11-16'
def test_nomina_devengado_horas_extras_diarias(): # def test_nomina_devengado_horas_extras_diarias():
nomina = fe.nomina.DIANNominaIndividual() # nomina = fe.nomina.DIANNominaIndividual()
nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasDiarias( # nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasDiarias(
horas_extras=[ # horas_extras=[
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T19:09:55', # hora_inicio='2021-11-30T19:09:55',
hora_fin='2021-11-30T20:09:55', # hora_fin='2021-11-30T20:09:55',
cantidad=1, # cantidad=1,
porcentaje=fe.nomina.Amount(1), # porcentaje=fe.nomina.Amount(1),
pago=fe.nomina.Amount(100) # pago=fe.nomina.Amount(100)
), # ),
fe.nomina.DevengadoHoraExtra( # fe.nomina.DevengadoHoraExtra(
hora_inicio='2021-11-30T18:09:55', # hora_inicio='2021-11-30T18:09:55',
hora_fin='2021-11-30T19:09:55', # hora_fin='2021-11-30T19:09:55',
cantidad=2, # cantidad=2,
porcentaje=fe.nomina.Amount(2), # porcentaje=fe.nomina.Amount(2),
pago=fe.nomina.Amount(200) # pago=fe.nomina.Amount(200)
) # )
] # ]
)) # ))
xml = nomina.toFachoXML() # xml = nomina.toFachoXML()
extras = xml.get_element('/nomina:NominaIndividual/Devengados/HEDs/HED', multiple=True) # extras = xml.get_element(
assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55' # '/nomina:NominaIndividual/Devengados/HEDs/HED', multiple=True)
assert extras[0].get('HoraFin') == '2021-11-30T20:09:55' # assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
assert extras[0].get('Cantidad') == '1' # assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
assert extras[0].get('Porcentaje') == '1.00' # assert extras[0].get('Cantidad') == '1'
assert extras[0].get('Pago') == '100.00' # assert extras[0].get('Porcentaje') == '1.00'
assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55' # assert extras[0].get('Pago') == '100.00'
assert extras[1].get('HoraFin') == '2021-11-30T19:09:55' # assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
assert extras[1].get('Cantidad') == '2' # assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
assert extras[1].get('Porcentaje') == '2.00' # assert extras[1].get('Cantidad') == '2'
assert extras[1].get('Pago') == '200.00' # assert extras[1].get('Porcentaje') == '2.00'
# assert extras[1].get('Pago') == '200.00'