se extrae libreria de etrivial

FossilOrigin-Name: 5cae2a8c5985850e97b3d416ba14a90c66e2c05e3a4f9c28fdbc767d6c29748f
This commit is contained in:
2020-05-23 18:56:22 +00:00
parent 6f9aa80527
commit 10f021d0fd
73 changed files with 33116 additions and 615 deletions

Binary file not shown.

100
tests/example.key Normal file
View File

@@ -0,0 +1,100 @@
-----BEGIN PRIVATE KEY-----
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
WNQaUlbaQE98jDqbQMPshtUjBLKOPjI=
-----END PRIVATE KEY-----

BIN
tests/example.p12 Normal file

Binary file not shown.

51
tests/example.pem Normal file
View File

@@ -0,0 +1,51 @@
-----BEGIN CERTIFICATE-----
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
CK3K
-----END CERTIFICATE-----

44
tests/test_client_dian.py Normal file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of facho. The COPYRIGHT file at the top level of
# 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):
super().__init__(username, password)
self.response = resp
def _open(self, service):
return None
def _close(self, conn):
pass
def _remote_service(self, conn, service):
def fake_remote(**kw):
return self.response
return fake_remote
def test_sopa_consultaresolucionesfacturacion():
expected_resp = {
'CodigoOperacion': 'OK',
'DescripcionOperacion': '',
'IdentificadorOperacion': '',
'RangoFacturacion': []
}
client_dian = FakeDianClient('user', 'pass', expected_resp)
resp = client_dian.request(dian.ConsultaResolucionesFacturacionPeticion(
'860046645', '800037646', '13a6a789-47ca-4728-adb8-372fca76e692'
))
assert resp.CodigoOperacion == 'OK'

16
tests/test_data.py Normal file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of facho. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
"""Tests for `facho` package."""
import pytest
import facho.fe.data.dian as dian
def test_dian():
assert dian.TipoResponsabilidad.short_name == 'TipoResponsabilidad'
assert dian.TipoResponsabilidad['Autorretenedor']['name'] == 'Autorretenedor'
assert dian.TipoOrganizacion.short_name == 'TipoOrganizacion'
assert dian.TipoOrganizacion['Persona Natural']['name'] == 'Persona Natural'

142
tests/test_facho.py Normal file
View File

@@ -0,0 +1,142 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of facho. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
"""Tests for `facho` package."""
import pytest
#from click.testing import CliRunner
from facho import facho
#from facho import cli
def test_facho_xml():
xml = facho.FachoXML('root')
invoice = xml.find_or_create_element('/root/Invoice')
assert xml.tostring() == '<root><Invoice/></root>'
invoice.text = 'Test'
assert xml.tostring() == '<root><Invoice>Test</Invoice></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]')
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')
assert xml.tostring() == '<root><Invoice/></root>'
xml.find_or_create_element('/root/Invoice')
assert xml.tostring() == '<root><Invoice/></root>'
xml.find_or_create_element('/root/Invoice')
assert xml.tostring() == '<root><Invoice/></root>'
xml.find_or_create_element('/root/Invoice/Line')
assert xml.tostring() == '<root><Invoice><Line/></Invoice></root>'
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')
invoice = xml.find_or_create_element('Invoice')
assert xml.tostring() == '<root><Invoice/></root>'
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/'
'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>'
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>'
def test_facho_xmlns_idempotent():
xml = facho.FachoXML('root', nsmap={
'ext': 'https://ext',
'sts': 'https://sts',
})
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>'
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>'
def test_facho_xml_set_element_with_format():
xml = facho.FachoXML('root')
invoice = 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')
invoice.set_element('/Invoice/Id', 1)
assert xml.tostring() == '<root><Invoice><Id>1</Id></Invoice></root>'
def test_facho_xml_fragments():
xml = facho.FachoXML('Invoice')
line = xml.fragment('/Invoice/Line')
line.set_element('/Line/Id', 1)
line = xml.fragment('/Invoice/Line', append=True)
line.set_element('/Line/Id', 2)
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>'
def test_facho_xml_nested_fragments():
xml = facho.FachoXML('Invoice')
party = xml.fragment('/Invoice/Party')
party.set_element('/Party/Name', 'test')
address = party.fragment('/Party/Address')
address.set_element('/Address/Line', 'line 1')
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>'
def test_facho_xml_get_element_text():
xml = facho.FachoXML('Invoice')
xml.set_element('/Invoice/ID', 'ABC123')
assert xml.get_element_text('/Invoice/ID') == 'ABC123'
line = xml.fragment('/Invoice/Line')
line.set_element('/Line/Quantity', 5)
assert line.get_element_text('/Line/Quantity', format_=int) == 5

37
tests/test_fe.py Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of facho. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import pytest
from facho import fe
def test_xmlsigned_build():
#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',
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
xml.add_extension(signer)
xml.attach_extensions()
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():
#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')
xml.add_extension(signer)
xml.attach_extensions()
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

86
tests/test_fe_form.py Normal file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of facho. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
"""Tests for `facho` package."""
import pytest
from datetime import datetime
import facho.fe.form as form
from facho import fe
@pytest.fixture
def simple_invoice():
inv = form.Invoice()
inv.set_period(datetime.now(), datetime.now())
inv.set_issue(datetime.now())
inv.set_ident('ABC123')
inv.set_supplier(form.Party(
name = 'facho-supplier',
ident = 123,
responsability_code = 'No aplica',
organization_code = 'Persona Natural'
))
inv.set_customer(form.Party(
name = 'facho-customer',
ident = 321,
responsability_code = 'No aplica',
organization_code = 'Persona Natural'
))
inv.add_invoice_line(form.InvoiceLine(
quantity = 1,
description = 'producto facho',
item_ident = 9999,
price_amount = 100.0,
tax = form.TaxTotal(
tax_amount = 0.0,
taxable_amount = 0.0,
subtotals = [
form.TaxSubTotal(
percent = 19.0,
)
]
)
))
return inv
def test_invoicesimple_build(simple_invoice):
assert simple_invoice.validate() == []
xml = form.DIANInvoiceXML(simple_invoice)
supplier_name = xml.get_element_text('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/cac:PartyName/cbc:Name')
assert supplier_name == simple_invoice.invoice_supplier.name
supplier_identification_number = xml.get_element_text('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/cac:PartyIdentification/cbc:ID')
assert int(supplier_identification_number) == simple_invoice.invoice_supplier.ident
customer_name = xml.get_element_text('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/cac:PartyName/cbc:Name')
assert customer_name == simple_invoice.invoice_customer.name
customer_identification_number = xml.get_element_text('/fe:Invoice/fe:AccountingCustomerParty/fe:Party/cac:PartyIdentification/cbc:ID')
assert int(customer_identification_number) == simple_invoice.invoice_customer.ident
def test_invoicesimple_build_with_cufe(simple_invoice):
assert simple_invoice.validate() == []
xml = form.DIANInvoiceXML(simple_invoice)
cufe = xml.get_element_text('/fe:Invoice/cbc:UUID')
assert cufe != ''
def test_invoicesimple_xml_signed(simple_invoice):
assert simple_invoice.validate() == []
xml = form.DIANInvoiceXML(simple_invoice)
signer = fe.DianXMLExtensionSigner('./tests/example.p12')
xml.add_extension(signer)
xml.attach_extensions()
elem = xml.find_or_create_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ds:Signature')
assert elem.text is not None