Fix: Formateo PEP8 (79 cols) y limpieza flake8 en tests y examples

- Líneas >79 cols reajustadas (asserts, strings CUDE/CUDS, comentarios)
- Elimina imports y variables muertas (F401/F841), E712 (== False -> is False)
- Reordena imports en docs/conf.py
This commit is contained in:
2026-08-12 19:56:33 -05:00
parent 4a7c2e2947
commit c4a29e4a6f
13 changed files with 518 additions and 271 deletions

View File

@@ -18,11 +18,11 @@
# relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
#
import facho
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
import facho
# -- General configuration ---------------------------------------------

View File

@@ -11,13 +11,18 @@ from facho.fe import form_xml
from facho.fe import fe
# importar otras necesarias
from datetime import datetime, date
from datetime import datetime
# Datos del fomulario del SET de pruebas
INVOICE_AUTHORIZATION = '181360000001' # Número suministrado por la Dian en el momento de la creación del SET de Pruebas
ID_SOFTWARE = '57bcb6d1-c591-5a90-b80a-cb030ec91440' #Id suministrado por la Dian en el momento de la creación del SET de Pruebas
PIN = '19642' #Número creado por la empresa para poder crear el SET de pruebas
CLAVE_TECNICA = 'fc9eac422eba16e21ffd8c5f94b3f30a6e38162d' ##Id suministrado por la Dian en el momento de la creación del SET de Pruebas
# Número suministrado por la Dian en el momento de la creación del SET de
# Pruebas
INVOICE_AUTHORIZATION = '181360000001'
# Id suministrado por la Dian en el momento de la creación del SET de Pruebas
ID_SOFTWARE = '57bcb6d1-c591-5a90-b80a-cb030ec91440'
# Número creado por la empresa para poder crear el SET de pruebas
PIN = '19642'
# Id suministrado por la Dian en el momento de la creación del SET de Pruebas
CLAVE_TECNICA = 'fc9eac422eba16e21ffd8c5f94b3f30a6e38162d'
# callback que retonar las extensiones XML necesarias
@@ -26,15 +31,24 @@ CLAVE_TECNICA = 'fc9eac422eba16e21ffd8c5f94b3f30a6e38162d' ##Id suministrado por
# muchos de los valores usados son obtenidos
# del servicio web de la DIAN.
def extensions(inv):
security_code = fe.DianXMLExtensionSoftwareSecurityCode(ID_SOFTWARE, PIN, inv.invoice_ident)
security_code = fe.DianXMLExtensionSoftwareSecurityCode(
ID_SOFTWARE, PIN, inv.invoice_ident)
authorization_provider = fe.DianXMLExtensionAuthorizationProvider()
cufe = fe.DianXMLExtensionCUFE(inv, CLAVE_TECNICA, fe.AMBIENTE_PRUEBAS)
software_provider = fe.DianXMLExtensionSoftwareProvider('nit_empresa', 'dígito_verificación', ID_SOFTWARE)
inv_authorization = fe.DianXMLExtensionInvoiceAuthorization(INVOICE_AUTHORIZATION,
datetime(2019, 1, 19),#Datos toamdos de
datetime(2030, 1, 19),#la configuración
software_provider = fe.DianXMLExtensionSoftwareProvider(
'nit_empresa', 'dígito_verificación', ID_SOFTWARE)
inv_authorization = fe.DianXMLExtensionInvoiceAuthorization(
INVOICE_AUTHORIZATION,
# Datos tomados de la configuración
datetime(2019, 1, 19),
datetime(2030, 1, 19),
'SETP', 990000000, 995000000) # del SET de pruebas
return [security_code, authorization_provider, cufe, software_provider, inv_authorization]
return [
security_code,
authorization_provider,
cufe,
software_provider,
inv_authorization]
def invoice():

View File

@@ -1,9 +1,11 @@
from facho import fe
def extensions(nomina):
return []
def nomina():
nomina = fe.nomina.DIANNominaIndividual()

View File

@@ -2,6 +2,7 @@ import pytest
import facho.fe.form as form
from datetime import datetime
@pytest.fixture
def simple_debit_note_without_lines():
inv = form.DebitNote(form.InvoiceDocumentReference(
@@ -36,14 +37,22 @@ def simple_debit_note_without_lines():
))
return inv
@pytest.fixture
def simple_credit_note_without_lines():
inv = form.CreditNote(form.InvoiceDocumentReference('1234', 'xx', datetime.now()))
inv = form.CreditNote(
form.InvoiceDocumentReference(
'1234', 'xx', datetime.now()))
inv.set_period(datetime.now(), datetime.now())
inv.set_issue(datetime.now())
inv.set_ident('ABC123')
inv.set_operation_type('20')
inv.set_payment_mean(form.PaymentMean(form.PaymentMean.DEBIT, '41', datetime.now(), '1234'))
inv.set_payment_mean(
form.PaymentMean(
form.PaymentMean.DEBIT,
'41',
datetime.now(),
'1234'))
inv.set_supplier(form.Party(
name='facho-supplier',
ident=form.PartyIdentification('123', '', '31'),
@@ -68,6 +77,7 @@ def simple_credit_note_without_lines():
))
return inv
@pytest.fixture
def simple_invoice_without_lines():
inv = form.NationalSalesInvoice()
@@ -75,7 +85,12 @@ def simple_invoice_without_lines():
inv.set_issue(datetime.now())
inv.set_ident('ABC123')
inv.set_operation_type('10')
inv.set_payment_mean(form.PaymentMean(form.PaymentMean.DEBIT, '41', datetime.now(), '1234'))
inv.set_payment_mean(
form.PaymentMean(
form.PaymentMean.DEBIT,
'41',
datetime.now(),
'1234'))
inv.set_supplier(form.Party(
name='facho-supplier',
ident=form.PartyIdentification('123', '', '31'),
@@ -108,7 +123,12 @@ def simple_invoice():
inv.set_issue(datetime.now())
inv.set_ident('ABC123')
inv.set_operation_type('10')
inv.set_payment_mean(form.PaymentMean(form.PaymentMean.DEBIT, '41', datetime.now(), ' 1234'))
inv.set_payment_mean(
form.PaymentMean(
form.PaymentMean.DEBIT,
'41',
datetime.now(),
' 1234'))
inv.set_supplier(form.Party(
name='facho-supplier',
ident=form.PartyIdentification('123', '', '31'),

View File

@@ -14,6 +14,7 @@ def test_amount_positive():
with pytest.raises(ValueError):
form.Amount(-1.0)
def test_amount_equals():
price1 = form.Amount(110.0)
price2 = form.Amount(100 + 10.0)
@@ -22,6 +23,7 @@ def test_amount_equals():
assert price1 == form.Amount(10) * form.Amount(10) + form.Amount(10)
assert form.Amount(110) == (form.Amount(1.10) * form.Amount(100))
def test_round_half_even():
# https://www.w3.org/TR/xpath-functions-31/#func-round-half-to-even
assert form.Amount(0.5).round(0).float() == 0.0
@@ -30,16 +32,20 @@ def test_round_half_even():
assert form.Amount(3.567812e+3).round(2).float() == 3567.81e0
assert form.Amount(4.7564e-3).round(2).float() == 0.0e0
def test_round():
# Entre 0 y 5 Mantener el dígito menos significativo
assert form.Amount(1.133).round(2) == form.Amount(1.13)
# Entre 6 y 9 Incrementar el dígito menos significativo
assert form.Amount(1.166).round(2) == form.Amount(1.17)
# 5, y el segundo dígito siguiente al dígito menos significativo es cero o par Mantener el dígito menos significativo
# 5, y el segundo dígito siguiente al dígito menos significativo es cero o
# par Mantener el dígito menos significativo
assert str(form.Amount(1.1542).round(2)) == str(form.Amount(1.15))
# 5, y el segundo dígito siguiente al dígito menos significativo es impar Incrementar el dígito menos significativo
# 5, y el segundo dígito siguiente al dígito menos significativo es impar
# Incrementar el dígito menos significativo
assert str(form.Amount(1.1563).round(2)) == str(form.Amount(1.16))
def test_amount_truncate():
assert form.Amount(1.1569).truncate_as_string(2) == '1.15'
assert form.Amount(587.0700).truncate_as_string(2) == '587.07'
@@ -49,5 +55,6 @@ def test_amount_truncate():
assert form.Amount(10000.02245).truncate_as_string(2) == '10000.02'
assert form.Amount(10000.02357).truncate_as_string(2) == '10000.02'
def test_amount_format():
assert str(round(form.Amount(1.1569), 2)) == '1.16'

View File

@@ -4,12 +4,7 @@
# this repository contains the full copyright notices and license terms.
from facho.fe.client import dian
from facho import facho
import pytest
from datetime import datetime
class FakeDianClient(dian.DianClient):
def __init__(self, username, password, resp):

View File

@@ -20,18 +20,19 @@ def test_facho_xml():
invoice.text = 'Test'
assert xml.tostring() == '<root><Invoice>Test</Invoice></root>'
invoice_line = xml.find_or_create_element('/root/Invoice/Line')
xml.find_or_create_element('/root/Invoice/Line')
assert xml.tostring() == '<root><Invoice>Test<Line/></Invoice></root>'
def test_facho_xml_with_attr():
xml = facho.FachoXML('root')
invoice = xml.find_or_create_element('/root/Invoice[id=123]')
xml.find_or_create_element('/root/Invoice[id=123]')
assert xml.tostring() == '<root><Invoice id="123"/></root>'
def test_facho_xml_idempotent():
xml = facho.FachoXML('root')
invoice = xml.find_or_create_element('/root/Invoice')
xml.find_or_create_element('/root/Invoice')
assert xml.tostring() == '<root><Invoice/></root>'
xml.find_or_create_element('/root/Invoice')
@@ -46,6 +47,7 @@ def test_facho_xml_idempotent():
xml.find_or_create_element('/root/Invoice/Line')
assert xml.tostring() == '<root><Invoice><Line/></Invoice></root>'
def test_facho_xml_aliases():
xml = facho.FachoXML('root')
xml.register_alias_xpath('Invoice', '/root/Invoice')
@@ -54,31 +56,42 @@ def test_facho_xml_aliases():
invoice.text = 'Test'
assert xml.tostring() == '<root><Invoice>Test</Invoice></root>'
def test_facho_xmlns():
xml = facho.FachoXML('root', nsmap={
'ext': 'https://ext',
'sts': 'https://sts',
})
invoiceAuthorization = xml.find_or_create_element('/root/ext:UBLExtensions/ext:UBLExtension/'
invoiceAuthorization = xml.find_or_create_element(
'/root/ext:UBLExtensions/ext:UBLExtension/'
'ext:ExtensionContent/sts:DianExtensions/'
'sts:InvoiceControl/sts:InvoiceAuthorization')
assert xml.tostring().strip() == '<root xmlns:ext="https://ext" xmlns:sts="https://sts"><ext:UBLExtensions>'\
'<ext:UBLExtension>'\
'<ext:ExtensionContent>'\
'<sts:DianExtensions>'\
'<sts:InvoiceControl>'\
'<sts:InvoiceAuthorization/>'\
'</sts:InvoiceControl></sts:DianExtensions></ext:ExtensionContent></ext:UBLExtension></ext:UBLExtensions></root>'
assert xml.tostring().strip() == (
'<root xmlns:ext="https://ext" xmlns:sts="https://sts">'
'<ext:UBLExtensions>'
'<ext:UBLExtension>'
'<ext:ExtensionContent>'
'<sts:DianExtensions>'
'<sts:InvoiceControl>'
'<sts:InvoiceAuthorization/>'
'</sts:InvoiceControl></sts:DianExtensions>'
'</ext:ExtensionContent></ext:UBLExtension>'
'</ext:UBLExtensions></root>')
invoiceAuthorization.text = '123456789'
assert xml.tostring().strip() == '<root xmlns:ext="https://ext" xmlns:sts="https://sts"><ext:UBLExtensions>'\
'<ext:UBLExtension>'\
'<ext:ExtensionContent>'\
'<sts:DianExtensions>'\
'<sts:InvoiceControl>'\
'<sts:InvoiceAuthorization>123456789</sts:InvoiceAuthorization>'\
'</sts:InvoiceControl></sts:DianExtensions></ext:ExtensionContent></ext:UBLExtension></ext:UBLExtensions></root>'
assert xml.tostring().strip() == (
'<root xmlns:ext="https://ext" xmlns:sts="https://sts">'
'<ext:UBLExtensions>'
'<ext:UBLExtension>'
'<ext:ExtensionContent>'
'<sts:DianExtensions>'
'<sts:InvoiceControl>'
'<sts:InvoiceAuthorization>123456789</sts:InvoiceAuthorization>'
'</sts:InvoiceControl></sts:DianExtensions>'
'</ext:ExtensionContent></ext:UBLExtension>'
'</ext:UBLExtensions></root>')
def test_facho_xmlns_idempotent():
xml = facho.FachoXML('root', nsmap={
@@ -87,16 +100,22 @@ def test_facho_xmlns_idempotent():
})
xml.find_or_create_element('/root/ext:Extension/sts:Sotoros')
assert xml.tostring() == '<root xmlns:ext="https://ext" xmlns:sts="https://sts"><ext:Extension><sts:Sotoros/></ext:Extension></root>'
assert xml.tostring() == (
'<root xmlns:ext="https://ext" xmlns:sts="https://sts">'
'<ext:Extension><sts:Sotoros/></ext:Extension></root>')
xml.find_or_create_element('/root/ext:Extension/sts:Sotoros')
assert xml.tostring() == '<root xmlns:ext="https://ext" xmlns:sts="https://sts"><ext:Extension><sts:Sotoros/></ext:Extension></root>'
assert xml.tostring() == (
'<root xmlns:ext="https://ext" xmlns:sts="https://sts">'
'<ext:Extension><sts:Sotoros/></ext:Extension></root>')
def test_facho_xml_set_element_with_format():
xml = facho.FachoXML('root')
invoice = xml.set_element('/root/Invoice', 1, format_='%02d')
xml.set_element('/root/Invoice', 1, format_='%02d')
assert xml.tostring() == '<root><Invoice>01</Invoice></root>'
def test_facho_xml_fragment():
xml = facho.FachoXML('root')
invoice = xml.fragment('/root/Invoice')
@@ -116,7 +135,10 @@ def test_facho_xml_fragments():
line = xml.fragment('/Invoice/Line', append=True)
line.set_element('/Line/Id', 3)
assert xml.tostring() == '<Invoice><Line><Id>1</Id></Line><Line><Id>2</Id></Line><Line><Id>3</Id></Line></Invoice>'
assert xml.tostring() == (
'<Invoice><Line><Id>1</Id></Line><Line><Id>2</Id></Line>'
'<Line><Id>3</Id></Line></Invoice>')
def test_facho_xml_nested_fragments():
xml = facho.FachoXML('Invoice')
@@ -128,7 +150,11 @@ def test_facho_xml_nested_fragments():
party.set_element('/Party/LastName', 'test')
assert xml.tostring() == '<Invoice><Party><Name>test</Name><Address><Line>line 1</Line></Address><LastName>test</LastName></Party></Invoice>'
assert xml.tostring() == (
'<Invoice><Party><Name>test</Name>'
'<Address><Line>line 1</Line></Address>'
'<LastName>test</LastName></Party></Invoice>')
def test_facho_xml_get_element_text_of_fragment():
xml = facho.FachoXML('root')
@@ -137,6 +163,7 @@ def test_facho_xml_get_element_text_of_fragment():
assert invoice.get_element_text('/Invoice/Id') == '1'
def test_facho_xml_get_element_text():
xml = facho.FachoXML('Invoice')
xml.set_element('/Invoice/ID', 'ABC123')
@@ -147,6 +174,7 @@ def test_facho_xml_get_element_text():
line.set_element('/Line/Quantity', 5)
assert line.get_element_text('/Line/Quantity', format_=int) == 5
def test_facho_xml_get_element_text_next_child():
xml = facho.FachoXML('Invoice')
xml.set_element('/Invoice/ID', 'ABC123')
@@ -166,25 +194,32 @@ def test_facho_xml_set_element_relative():
assert xml.get_element_text('/Invoice/ID') == 'ABC123'
def test_facho_xml_set_element_relative_with_namespace():
xml = facho.FachoXML('{%s}Invoice' % ('http://www.dian.gov.co/contratos/facturaelectronica/v1'),
nsmap={'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1'})
xml = facho.FachoXML(
'{%s}Invoice' %
('http://www.dian.gov.co/contratos/facturaelectronica/v1'),
nsmap={
'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1'})
xml.set_element('./ID', 'ABC123')
assert xml.get_element_text('/fe:Invoice/ID') == 'ABC123'
def test_facho_xml_fragment_relative():
xml = facho.FachoXML('root')
invoice = xml.fragment('./Invoice')
invoice.set_element('./Id', 1)
assert xml.tostring() == '<root><Invoice><Id>1</Id></Invoice></root>'
def test_facho_xml_get_element_fragment_relative():
xml = facho.FachoXML('root')
invoice = xml.fragment('./Invoice')
invoice.set_element('./Id', 1)
assert invoice.get_element_text('./Id') == '1'
def test_facho_xml_replacement_for():
xml = facho.FachoXML('root')
xml.placeholder_for('./child/type')
@@ -192,37 +227,47 @@ def test_facho_xml_replacement_for():
'./child/code', 'test')
assert xml.tostring() == '<root><child><code>test</code></child></root>'
def test_facho_xml_set_element_content_invalid_validation():
xml = facho.FachoXML('root')
with pytest.raises(facho.FachoValueInvalid) as e:
with pytest.raises(facho.FachoValueInvalid):
xml.set_element_validator('./Id', lambda text, attrs: text == 'mero')
xml.set_element('./Id', 'bad')
def test_facho_xml_set_element_content_valid_validation():
xml = facho.FachoXML('root')
xml.set_element_validator('./Id', lambda text, attrs: text == 'mero')
xml.set_element('./Id', 'mero')
def test_facho_xml_set_element_attribute_invalid_validation():
xml = facho.FachoXML('root')
with pytest.raises(facho.FachoValueInvalid) as e:
xml.set_element_validator('./Id', lambda text, attrs: attrs['code'] == 'ABC')
with pytest.raises(facho.FachoValueInvalid):
xml.set_element_validator(
'./Id', lambda text, attrs: attrs['code'] == 'ABC')
xml.set_element('./Id', 'mero', code='CBA')
def test_facho_xml_set_element_attribute_valid_validation():
xml = facho.FachoXML('root')
xml.set_element_validator('./Id', lambda text, attrs: attrs['code'] == 'ABC')
xml.set_element_validator(
'./Id',
lambda text,
attrs: attrs['code'] == 'ABC')
xml.set_element('./Id', 'mero', code='ABC')
def test_facho_xml_get_element_attribute():
xml = facho.FachoXML('root')
xml.set_element('./Id', 'mero', code='ABC')
assert xml.get_element_attribute('/root/Id', 'code') == 'ABC'
def test_facho_xml_keep_orden_slibing():
xml = facho.FachoXML('root')
xml.find_or_create_element('./A')
@@ -233,6 +278,7 @@ def test_facho_xml_keep_orden_slibing():
assert xml.tostring() == '<root><A/><A/><B/><B/><C/></root>'
def test_facho_xml_placeholder_optional():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
@@ -241,6 +287,7 @@ def test_facho_xml_placeholder_optional():
assert xml.tostring() == '<root><A/><C/></root>'
def test_facho_xml_placeholder_append_to_optional():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
@@ -250,6 +297,7 @@ def test_facho_xml_placeholder_append_to_optional():
xml.find_or_create_element('./B')
assert xml.tostring() == '<root><A/><B/><C/></root>'
def test_facho_xml_placeholder_set_element_to_optional():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
@@ -259,6 +307,7 @@ def test_facho_xml_placeholder_set_element_to_optional():
xml.set_element('./B', '2')
assert xml.tostring() == '<root><A/><B>2</B><C/></root>'
def test_facho_xml_placeholder_set_element_to_optional_with_append():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
@@ -294,6 +343,7 @@ def test_facho_xml_set_attributes_not_set_optional():
xml.get_element_attribute('/root/A', 'value1')
assert xml.get_element_attribute('/root/A', 'value2') == '2'
def test_facho_xml_placeholder_with_fragment():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
@@ -306,7 +356,9 @@ def test_facho_xml_placeholder_with_fragment():
AA = xml.fragment('./AA/Child', append=True)
assert xml.tostring() == '<root><A/><AA><Child><B/><B/></Child><Child/></AA><AAA/></root>'
assert xml.tostring() == (
'<root><A/><AA><Child><B/><B/></Child><Child/></AA><AAA/></root>')
def test_facho_xml_create_on_first_append():
xml = facho.FachoXML('root')
@@ -314,6 +366,7 @@ def test_facho_xml_create_on_first_append():
xml.find_or_create_element('./A', append=True)
assert xml.tostring() == '<root><A/></root>'
def test_facho_xml_create_on_first_append_multiple_appends():
xml = facho.FachoXML('root')
@@ -324,6 +377,7 @@ def test_facho_xml_create_on_first_append_multiple_appends():
xml.find_or_create_element('./C', append=True)
assert xml.tostring() == '<root><B/><A/><A/><A/><C/></root>'
def test_facho_xml_fragment_create_on_first_append():
xml = facho.FachoXML('root')
@@ -333,6 +387,7 @@ def test_facho_xml_fragment_create_on_first_append():
A.find_or_create_element('./C')
assert xml.tostring() == '<root><A><B/></A><A><C/></A></root>'
def test_facho_xml_placeholder_optional_and_fragment():
xml = facho.FachoXML('root')
@@ -346,6 +401,7 @@ def test_facho_xml_placeholder_optional_and_fragment():
assert xml.tostring() == '<root><A><AA><B/><C/></AA></A></root>'
def test_facho_xml_placeholder_optional_and_set_attributes():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
@@ -354,6 +410,7 @@ def test_facho_xml_placeholder_optional_and_set_attributes():
assert xml.get_element_attribute('/root/A', 'prueba') == 'OK'
assert xml.tostring() == '<root><A prueba="OK"/></root>'
def test_facho_xml_placeholder_optional_and_fragment_with_set_element():
xml = facho.FachoXML('root')
@@ -365,17 +422,19 @@ def test_facho_xml_placeholder_optional_and_fragment_with_set_element():
assert xml.tostring() == '<root><A><AA prueba="OK"/></A></root>'
assert xml.get_element_attribute('/root/A/AA', 'prueba') == 'OK'
def test_facho_xml_exist_element():
xml = facho.FachoXML('root')
xml.placeholder_for('./A')
assert xml.exist_element('/root/A') == False
assert xml.exist_element('/root/A') is False
assert xml.tostring() == '<root><A/></root>'
xml.find_or_create_element('./A')
assert xml.exist_element('/root/A') == True
assert xml.exist_element('/root/A')
assert xml.tostring() == '<root><A/></root>'
def test_facho_xml_query_element_text_or_attribute():
xml = facho.FachoXML('root')
@@ -384,6 +443,7 @@ 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/@clave') == 'valor'
def test_facho_xml_query_element_text_or_attribute_from_fragment():
xml = facho.FachoXML('root')
@@ -392,6 +452,7 @@ def test_facho_xml_query_element_text_or_attribute_from_fragment():
assert invoice.get_element_text_or_attribute('/Invoice/A') == 'contenido'
def test_facho_xml_build_xml_absolute():
xml = facho.FachoXML('root')
@@ -400,18 +461,23 @@ def test_facho_xml_build_xml_absolute():
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'})
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'
def test_facho_xml_build_xml_absolute_namespace_from_fragment():
xml = facho.FachoXML('{%s}root' % ('http://www.dian.gov.co/contratos/facturaelectronica/v1'),
nsmap={'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1'})
xml = facho.FachoXML(
'{%s}root' %
('http://www.dian.gov.co/contratos/facturaelectronica/v1'),
nsmap={
'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1'})
invoice = xml.fragment('/root/Invoice')
xpath = invoice.xpath_from_root('/A')
assert xpath == '/fe:root/Invoice/A'

View File

@@ -4,16 +4,14 @@
# this repository contains the full copyright notices and license terms.
from datetime import datetime
import pytest
from facho import fe
import helpers
def test_xmlsigned_build(monkeypatch):
# openssl req -x509 -sha256 -nodes -subj "/CN=test" -days 1 -newkey rsa:2048 -keyout example.key -out example.pem
# openssl pkcs12 -export -out example.p12 -inkey example.key -in example.pem
# openssl req -x509 -sha256 -nodes -subj "/CN=test" -days 1
# -newkey rsa:2048 -keyout example.key -out example.pem
# openssl pkcs12 -export -out example.p12 -inkey example.key -in
# example.pem
signer = fe.DianXMLExtensionSigner('./tests/example.p12')
xml = fe.FeXML('Invoice',
@@ -21,68 +19,90 @@ def test_xmlsigned_build(monkeypatch):
signer.sign_xml_element(xml.root)
elem = xml.find_or_create_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ds:Signature')
elem = xml.find_or_create_element(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent'
'/ds:Signature')
assert elem is not None
# assert elem.findall('ds:SignedInfo', fe.NAMESPACES) is not None
def test_xmlsigned_with_passphrase_build(monkeypatch):
#openssl req -x509 -sha256 -nodes -subj "/CN=test" -days 1 -newkey rsa:2048 -keyout example.key -out example.pem
#openssl pkcs12 -export -out example.p12 -inkey example.key -in example.pem
signer = fe.DianXMLExtensionSigner('./tests/example-with-passphrase.p12', 'test')
# openssl req -x509 -sha256 -nodes -subj "/CN=test" -days 1
# -newkey rsa:2048 -keyout example.key -out example.pem
# openssl pkcs12 -export -out example.p12 -inkey example.key -in
# example.pem
signer = fe.DianXMLExtensionSigner(
'./tests/example-with-passphrase.p12', 'test')
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
signer.sign_xml_element(xml.root)
elem = xml.find_or_create_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ds:Signature')
elem = xml.find_or_create_element(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent'
'/ds:Signature')
assert elem is not None
# assert elem.findall('ds:SignedInfo', fe.NAMESPACES) is not None
def test_dian_extension_software_security_code():
security_code = fe.DianXMLExtensionSoftwareSecurityCode('idsoftware', '1234', '1')
security_code = fe.DianXMLExtensionSoftwareSecurityCode(
'idsoftware', '1234', '1')
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
xml.add_extension(security_code)
content = xml.get_element_text('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareSecurityCode')
content = xml.get_element_text(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent'
'/sts:DianExtensions/sts:SoftwareSecurityCode')
assert content is not None
def test_dian_extension_invoice_authorization():
invoice_authorization = '18762002346472'
inv_auth_ext = fe.DianXMLExtensionInvoiceAuthorization(invoice_authorization,
datetime(2017, 2, 23),
datetime(2019, 8, 23),
'MD', 100001, 174999)
inv_auth_ext = fe.DianXMLExtensionInvoiceAuthorization(
invoice_authorization, datetime(
2017, 2, 23), datetime(
2019, 8, 23), 'MD', 100001, 174999)
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
xml.add_extension(inv_auth_ext)
auth = xml.get_element_text('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceControl/sts:InvoiceAuthorization')
auth = xml.get_element_text(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent'
'/sts:DianExtensions/sts:InvoiceControl/sts:InvoiceAuthorization')
assert auth == invoice_authorization
def test_dian_extension_software_provider():
nit = '123456789'
id_software = 'ABCDASDF123'
software_provider_extension = fe.DianXMLExtensionSoftwareProvider(nit, '', id_software)
software_provider_extension = fe.DianXMLExtensionSoftwareProvider(
nit, '', id_software)
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
xml.add_extension(software_provider_extension)
give_nit = xml.get_element_text('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareProvider/sts:ProviderID')
give_nit = xml.get_element_text(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent'
'/sts:DianExtensions/sts:SoftwareProvider/sts:ProviderID')
assert nit == give_nit
def test_dian_extension_authorization_provider():
auth_provider_extension = fe.DianXMLExtensionAuthorizationProvider()
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
xml.add_extension(auth_provider_extension)
dian_nit = xml.get_element_text('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:AuthorizationProvider/sts:AuthorizationProviderID')
dian_nit = xml.get_element_text(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/'
'ext:ExtensionContent/sts:DianExtensions/sts:AuthorizationProvider/'
'sts:AuthorizationProviderID')
assert dian_nit == '800197268'
def test_dian_invoice_without_namespace_in_root():
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
@@ -93,9 +113,13 @@ def test_dian_invoice_without_namespace_in_root():
def test_xml_sign_dian(monkeypatch):
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
xml.find_or_create_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
ublextension = xml.fragment('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension', append=True)
extcontent = ublextension.find_or_create_element('/ext:UBLExtension/ext:ExtensionContent')
xml.find_or_create_element(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
ublextension = xml.fragment(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension',
append=True)
ublextension.find_or_create_element(
'/ext:UBLExtension/ext:ExtensionContent')
xmlstring = xml.tostring()
print(xmlstring)
@@ -103,12 +127,17 @@ def test_xml_sign_dian(monkeypatch):
xmlsigned = signer.sign_xml_string(xmlstring)
assert "Signature" in xmlsigned
def test_xml_sign_dian_using_bytes(monkeypatch):
xml = fe.FeXML('Invoice',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
xml.find_or_create_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
ublextension = xml.fragment('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension', append=True)
extcontent = ublextension.find_or_create_element('/ext:UBLExtension/ext:ExtensionContent')
xml.find_or_create_element(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
ublextension = xml.fragment(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension',
append=True)
ublextension.find_or_create_element(
'/ext:UBLExtension/ext:ExtensionContent')
xmlstring = xml.tostring()
p12_data = open('./tests/example.p12', 'rb').read()
@@ -117,6 +146,7 @@ def test_xml_sign_dian_using_bytes(monkeypatch):
xmlsigned = signer.sign_xml_string(xmlstring)
assert "Signature" in xmlsigned
def test_xml_signature_timestamp(monkeypatch):
xml = fe.FeXML(
'Invoice',

View File

@@ -41,11 +41,13 @@ def test_invoicesimple_build(simple_invoice):
xml = DIANInvoiceXML(simple_invoice)
supplier_name = xml.get_element_text(
'/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name')
'/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc'
':Name')
assert supplier_name == simple_invoice.invoice_supplier.name
customer_name = xml.get_element_text(
'/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name')
'/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc'
':Name')
assert customer_name == simple_invoice.invoice_customer.name
@@ -66,7 +68,8 @@ def test_invoicesimple_xml_signed(monkeypatch, simple_invoice):
xml.add_extension(signer)
elem = xml.get_element(
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent/ds:Signature')
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension[2]/ext'
':ExtensionContent/ds:Signature')
assert elem.text is not None
@@ -75,14 +78,16 @@ def test_invoicesimple_zip(simple_invoice):
zipdata = io.BytesIO()
with fe.DianZIP(zipdata) as dianzip:
name_invoice = dianzip.add_invoice_xml(simple_invoice.invoice_ident, str(xml_invoice))
name_invoice = dianzip.add_invoice_xml(
simple_invoice.invoice_ident, str(xml_invoice))
# el zip ademas de archivar debe comprimir los archivos
# de lo contrario la DIAN lo rechaza
with zipfile.ZipFile(zipdata) as dianzip:
dianzip.testzip()
for zipinfo in dianzip.infolist():
assert zipinfo.compress_type == zipfile.ZIP_DEFLATED, "se espera el zip comprimido"
assert zipinfo.compress_type == zipfile.ZIP_DEFLATED, (
"se espera el zip comprimido")
with zipfile.ZipFile(zipdata) as dianzip:
xml_data = dianzip.open(name_invoice).read().decode('utf-8')
@@ -122,7 +127,8 @@ def test_invoice_invoice_type_code(simple_invoice):
def test_invoice_totals(simple_invoice_without_lines):
simple_invoice = simple_invoice_without_lines
simple_invoice.invoice_ident = '323200000129'
simple_invoice.invoice_issue = datetime.strptime('2019-01-16 10:53:10-05:00', '%Y-%m-%d %H:%M:%S%z')
simple_invoice.invoice_issue = datetime.strptime(
'2019-01-16 10:53:10-05:00', '%Y-%m-%d %H:%M:%S%z')
simple_invoice.invoice_supplier.ident = '700085371'
simple_invoice.invoice_customer.ident = '800199436'
simple_invoice.add_invoice_line(form.InvoiceLine(
@@ -222,7 +228,8 @@ def test_invoice_cufe(simple_invoice_without_lines):
assert formatVars[12] == '800199436', "NumAdq"
# ClTec
assert formatVars[13] == '693ff6f2a553c3646a063436fd4dd9ded0311471', "ClTec"
assert formatVars[13] == (
'693ff6f2a553c3646a063436fd4dd9ded0311471'), "ClTec"
# TipoAmbiente
assert formatVars[14] == '1', "TipoAmbiente"
@@ -323,8 +330,13 @@ def test_debit_note_cude(simple_debit_note_without_lines):
assert build_vars['TipoAmb'] == 2
cude_composicion = "".join(cude_extension.formatVars())
assert cude_composicion == 'ND10012019-01-1810:58:00-05:0030000.00010.00042400.00030.0032400.0090019726410254102102012'
assert cude_composicion == (
'ND10012019-01-1810:58:00-05:0030000.00010.00042400.00030.0032400.009'
'001'
'9726410254102102012')
xml_invoice.add_extension(cude_extension)
cude = xml_invoice.get_element_text('/fe:DebitNote/cbc:UUID')
assert cude == '3fa73a86d57d9341c536afde1f85c4efd9d4591c2c22bce4dfb0e6b0d2e83b8f047a8bde7098292e9d2493e60d1c31da'
assert cude == (
'3fa73a86d57d9341c536afde1f85c4efd9d4591c2c22bce4dfb0e6b0d2e83b8f047a8'
'bde7098292e9d2493e60d1c31da')

View File

@@ -121,7 +121,9 @@ def test_FAU14():
wants = form.Amount(119.0 + 19.0 - 50.0)
assert inv.invoice_legal_monetary_total.payable_amount == wants, "got %s want %s" % (inv.invoice_legal_monetary_total.payable_amount, wants)
assert inv.invoice_legal_monetary_total.payable_amount == wants, (
"got %s want %s" % (
inv.invoice_legal_monetary_total.payable_amount, wants))
def test_invalid_tipo_operacion_nota_debito():

View File

@@ -6,10 +6,7 @@
"""Tests for `facho` package."""
import pytest
# from datetime import datetime
import copy
from facho.fe import form
from facho.fe import form_xml
# from fixtures import *

View File

@@ -28,8 +28,12 @@
# ))
# xml = nomina.toFachoXML()
# 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',
# 'DiasTrabajados') == '30'
# assert
# xml.get_element_attribute('/nomina:NominaIndividual/Devengados/Basico',
# 'SueldoTrabajado') == '1000000.00'
# def test_adicionar_devengado_transporte():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -40,7 +44,9 @@
# 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():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -58,7 +64,9 @@
# 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():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -75,7 +83,8 @@
# 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():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -90,7 +99,8 @@
# xml = nomina.toFachoXML()
# 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():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -107,7 +117,9 @@
# xml = nomina.toFachoXML()
# 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():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -213,26 +225,62 @@
# ))
# xml = nomina.toFachoXML()
# expected_cune = 'b8f9b6c24de07ffd92ea5467433a3b69357cfaffa7c19722db94b2e0eca41d057085a54f484b5da15ff585e773b0b0ab'
# 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_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/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/@MunicipioCiudad') == '05001'
# 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/@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/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/Trabajador/@NumeroDocumento') == '800199436'
# assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad') == 'True'
# assert xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad/@CUNENov') == 'N0111'
# expected_cune =
# 'b8f9b6c24de07ffd92ea5467433a3b69357cfaffa7c19722db94b2e0eca41d057085a54f484
# b5da15ff585e773b0b0ab'
# 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_text_or_attribute('/nomina:NominaIndividual/NumeroSecuenciaX
# ML/@Numero') == 'N00001'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/NumeroSecuenciaX
# ML/@Consecutivo') == '00001'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionX
# ML/@Pais') == 'CO'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionX
# ML/@DepartamentoEstado') == '05'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/LugarGeneracionX
# ML/@MunicipioCiudad') == '05001'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@NI
# T') == '999999'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@DV
# ') == '2'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@So
# ftwareID') == 'xx'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/ProveedorXML/@So
# ftwareSC') 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/Empleador/@NIT')
# == '700085371'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/Trabajador/@Nume
# roDocumento') == '800199436'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad') ==
# 'True'
# assert
# xml.get_element_text_or_attribute('/nomina:NominaIndividual/Novedad/@CUNENov
# ') == 'N0111'
# # 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():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -249,11 +297,11 @@
# xml.add_extension(signer)
# 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
# def test_nomina_devengado_horas_extras_nocturnas():
# nomina = fe.nomina.DIANNominaIndividual()
@@ -277,7 +325,9 @@
# ))
# 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('HoraFin') == '2021-11-30T20:09:55'
# assert extras[0].get('Cantidad') == '1'
@@ -312,7 +362,9 @@
# ))
# 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('HoraFin') == '2021-11-30T20:09:55'
# assert extras[0].get('Cantidad') == '1'
@@ -327,7 +379,9 @@
# def test_nomina_devengado_horas_extras_diarias_dominicales_y_festivos():
# nomina = fe.nomina.DIANNominaIndividual()
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasDiariasDominicalesYFestivos(
#
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasDiariasDominicalesY
# Festivos(
# horas_extras=[
# fe.nomina.DevengadoHoraExtra(
# hora_inicio='2021-11-30T19:09:55',
@@ -347,7 +401,9 @@
# ))
# 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('HoraFin') == '2021-11-30T20:09:55'
# assert extras[0].get('Cantidad') == '1'
@@ -362,7 +418,9 @@
# def test_nomina_devengado_horas_recargo_diarias_dominicales_y_festivos():
# nomina = fe.nomina.DIANNominaIndividual()
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoDiariasDominicalesYFestivos(
#
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoDiariasDominicales
# YFestivos(
# horas_extras=[
# fe.nomina.DevengadoHoraExtra(
# hora_inicio='2021-11-30T19:09:55',
@@ -382,7 +440,9 @@
# ))
# 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('HoraFin') == '2021-11-30T20:09:55'
# assert extras[0].get('Cantidad') == '1'
@@ -398,7 +458,9 @@
# def test_nomina_devengado_horas_extras_nocturnas_dominicales_y_festivos():
# nomina = fe.nomina.DIANNominaIndividual()
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasNocturnasDominicalesYFestivos(
#
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasNocturnasDominicale
# sYFestivos(
# horas_extras=[
# fe.nomina.DevengadoHoraExtra(
# hora_inicio='2021-11-30T19:09:55',
@@ -418,7 +480,9 @@
# ))
# 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('HoraFin') == '2021-11-30T20:09:55'
# assert extras[0].get('Cantidad') == '1'
@@ -433,7 +497,9 @@
# def test_nomina_devengado_horas_recargo_nocturno_dominicales_y_festivos():
# nomina = fe.nomina.DIANNominaIndividual()
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoNocturnoDominicalesYFestivos(
#
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasRecargoNocturnoDominicale
# sYFestivos(
# horas_extras=[
# fe.nomina.DevengadoHoraExtra(
# hora_inicio='2021-11-30T19:09:55',
@@ -453,7 +519,9 @@
# ))
# 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('HoraFin') == '2021-11-30T20:09:55'
# assert extras[0].get('Cantidad') == '1'

View File

@@ -101,7 +101,9 @@
# 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():
@@ -119,13 +121,17 @@
# xml = nomina.toFachoXML()
# assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ComprobanteTotal') == '1000000.00'
# assert
# xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/Comp
# robanteTotal') == '1000000.00'
# def test_adicionar_reemplazar_asignar_predecesor():
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor(
#
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.
# Predecesor(
# numero = '123456',
# cune = 'ABC123456',
# fecha_generacion = '2021-11-16'
@@ -133,15 +139,23 @@
# xml = nomina.toFachoXML()
# 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/@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/Re
# emplazar/ReemplazandoPredecesor/@NumeroPred') == '123456'
# assert
# xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Re
# emplazar/ReemplazandoPredecesor/@CUNEPred') == 'ABC123456'
# assert
# xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Re
# emplazar/ReemplazandoPredecesor/@FechaGenPred') == '2021-11-16'
# def test_adicionar_reemplazar_eliminar_predecesor_opcional():
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor(
#
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.
# Predecesor(
# numero = '123456',
# cune = 'ABC123456',
# fecha_generacion = '2021-11-16'
@@ -150,13 +164,19 @@
# xml = nomina.toFachoXML()
# print(xml.tostring())
# 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/Reemplazar/Reemplaza
# ndoPredecesor') is not None
# assert
# xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoP
# redecesor') is None
# def test_adicionar_eliminar_reemplazar_predecesor_opcional():
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor(
#
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Pr
# edecesor(
# numero = '123456',
# cune = 'ABC123456',
# fecha_generacion = '2021-11-16'
@@ -164,8 +184,12 @@
# xml = nomina.toFachoXML()
# print(xml.tostring())
# 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/Eliminar/EliminandoP
# redecesor') is not None
# assert
# xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/Reemplaza
# ndoPredecesor') is None
# def test_adicionar_eliminar_devengado_comprobante_total():
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
@@ -182,12 +206,16 @@
# xml = nomina.toFachoXML()
# assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Eliminar/ComprobanteTotal') == '1000000.00'
# assert
# xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Eliminar/Compro
# banteTotal') == '1000000.00'
# def test_adicionar_eliminar_asignar_predecesor():
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor(
#
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Pr
# edecesor(
# numero = '123456',
# cune = 'ABC123456',
# fecha_generacion = '2021-11-16'
@@ -195,9 +223,15 @@
# xml = nomina.toFachoXML()
# 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/@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/El
# iminar/EliminandoPredecesor/@NumeroPred') == '123456'
# assert
# xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/El
# iminar/EliminandoPredecesor/@CUNEPred') == 'ABC123456'
# assert
# xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/El
# iminar/EliminandoPredecesor/@FechaGenPred') == '2021-11-16'
# def test_nomina_devengado_horas_extras_diarias():
# nomina = fe.nomina.DIANNominaIndividual()