From f4c2282e3d86e3e99f8ec287751789653d1eb9c4 Mon Sep 17 00:00:00 2001 From: "bit4bit@riseup.net" Date: Mon, 2 Nov 2020 01:13:16 +0000 Subject: [PATCH] facho/fe/form.py a modulo. * facho/fe/form/query.py: utilidades. FossilOrigin-Name: a1486421fcfcf6bda1e3b4901f3fc3fe86b7156852571aad74274d5b7ce3778a --- facho/fe/__init__.py | 1 + facho/fe/fe.py | 4 + facho/fe/{form.py => form/__init__.py} | 2 +- facho/fe/form/query.py | 23 ++++ tests/fixtures.py | 146 +++++++++++++++++++++++++ tests/test_fe_form.py | 144 +----------------------- tests/test_query.py | 26 +++++ 7 files changed, 202 insertions(+), 144 deletions(-) rename facho/fe/{form.py => form/__init__.py} (99%) create mode 100644 facho/fe/form/query.py create mode 100644 tests/fixtures.py create mode 100644 tests/test_query.py diff --git a/facho/fe/__init__.py b/facho/fe/__init__.py index 590426f..072d3c3 100644 --- a/facho/fe/__init__.py +++ b/facho/fe/__init__.py @@ -1,4 +1,5 @@ from .fe import FeXML +from .fe import fe_from_string from .fe import NAMESPACES from .fe import DianXMLExtensionSigner from .fe import DianXMLExtensionSoftwareSecurityCode diff --git a/facho/fe/fe.py b/facho/fe/fe.py index 2b5c0b8..ca1d158 100644 --- a/facho/fe/fe.py +++ b/facho/fe/fe.py @@ -48,6 +48,10 @@ NAMESPACES = { 'sig': 'http://www.w3.org/2000/09/xmldsig#', } +def fe_from_string(document: str) -> FachoXML: + xml = LXMLBuilder.from_string(document) + return FachoXML(xml, nsmap=NAMESPACES) + from contextlib import contextmanager @contextmanager def mock_xades_policy(): diff --git a/facho/fe/form.py b/facho/fe/form/__init__.py similarity index 99% rename from facho/fe/form.py rename to facho/fe/form/__init__.py index 79f7188..46768c4 100644 --- a/facho/fe/form.py +++ b/facho/fe/form/__init__.py @@ -11,7 +11,7 @@ import decimal from decimal import Decimal import typing -from .data.dian import codelist +from ..data.dian import codelist DECIMAL_PRECISION = 6 diff --git a/facho/fe/form/query.py b/facho/fe/form/query.py new file mode 100644 index 0000000..054037d --- /dev/null +++ b/facho/fe/form/query.py @@ -0,0 +1,23 @@ +""" +utilidades +""" + +from .. import form +from ..fe import fe_from_string +from datetime import datetime + +def billing_reference(xmldocument: str, klass: form.BillingReference) -> form.BillingReference: + """ + construye BillingReference desde XMLDOCUMENT + usando KLASS como clase. + """ + if not issubclass(klass, form.BillingReference): + raise TypeError('klass expected subclass of BillingReference') + + fachoxml = fe_from_string(xmldocument) + + uid = fachoxml.get_element_text('./cbc:ID') + uuid = fachoxml.get_element_text('./cbc:UUID') + issue_date = fachoxml.get_element_text('./cbc:IssueDate') + date = datetime.strptime(issue_date, '%Y-%m-%d') + return klass(ident=uid, uuid=uuid, date=date) diff --git a/tests/fixtures.py b/tests/fixtures.py new file mode 100644 index 0000000..57cf5c8 --- /dev/null +++ b/tests/fixtures.py @@ -0,0 +1,146 @@ +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('1234', 'xx', datetime.now())) + inv.set_period(datetime.now(), datetime.now()) + inv.set_issue(datetime.now()) + inv.set_ident('ABC123') + inv.set_operation_type('30') + 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'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + inv.set_customer(form.Party( + name = 'facho-customer', + ident = form.PartyIdentification('321', '', '31'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + return inv + +@pytest.fixture +def simple_credit_note_without_lines(): + 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_supplier(form.Party( + name = 'facho-supplier', + ident = form.PartyIdentification('123','', '31'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + inv.set_customer(form.Party( + name = 'facho-customer', + ident = form.PartyIdentification('321', '', '31'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + return inv + +@pytest.fixture +def simple_invoice_without_lines(): + inv = form.NationalSalesInvoice() + inv.set_period(datetime.now(), datetime.now()) + 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_supplier(form.Party( + name = 'facho-supplier', + ident = form.PartyIdentification('123','', '31'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + inv.set_customer(form.Party( + name = 'facho-customer', + ident = form.PartyIdentification('321', '', '31'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + return inv + +@pytest.fixture +def simple_invoice(): + inv = form.NationalSalesInvoice() + inv.set_period(datetime.now(), datetime.now()) + 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_supplier(form.Party( + name = 'facho-supplier', + ident = form.PartyIdentification('123','', '31'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + inv.set_customer(form.Party( + name = 'facho-customer', + ident = form.PartyIdentification('321','', '31'), + responsability_code = form.Responsability(['O-07']), + responsability_regime_code = '48', + organization_code = '1', + address = form.Address( + '', '', form.City('05001', 'Medellín'), + form.Country('CO', 'Colombia'), + form.CountrySubentity('05', 'Antioquia')) + )) + inv.add_invoice_line(form.InvoiceLine( + quantity = 1, + description = 'producto facho', + item = form.StandardItem('test', 9999), + price = form.Price(form.Amount(100.0), '01', ''), + tax = form.TaxTotal( + tax_amount = form.Amount(0.0), + taxable_amount = form.Amount(0.0), + subtotals = [ + form.TaxSubTotal( + percent = 19.0, + ) + ] + ) + )) + return inv diff --git a/tests/test_fe_form.py b/tests/test_fe_form.py index 5bd730a..56e1b51 100644 --- a/tests/test_fe_form.py +++ b/tests/test_fe_form.py @@ -14,149 +14,7 @@ import facho.fe.form as form from facho import fe from facho.fe.form_xml import DIANInvoiceXML, DIANCreditNoteXML, DIANDebitNoteXML -@pytest.fixture -def simple_debit_note_without_lines(): - inv = form.DebitNote(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('30') - 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'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - inv.set_customer(form.Party( - name = 'facho-customer', - ident = form.PartyIdentification('321', '', '31'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - return inv - -@pytest.fixture -def simple_credit_note_without_lines(): - 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_supplier(form.Party( - name = 'facho-supplier', - ident = form.PartyIdentification('123','', '31'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - inv.set_customer(form.Party( - name = 'facho-customer', - ident = form.PartyIdentification('321', '', '31'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - return inv - -@pytest.fixture -def simple_invoice_without_lines(): - inv = form.NationalSalesInvoice() - inv.set_period(datetime.now(), datetime.now()) - 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_supplier(form.Party( - name = 'facho-supplier', - ident = form.PartyIdentification('123','', '31'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - inv.set_customer(form.Party( - name = 'facho-customer', - ident = form.PartyIdentification('321', '', '31'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - return inv - -@pytest.fixture -def simple_invoice(): - inv = form.NationalSalesInvoice() - inv.set_period(datetime.now(), datetime.now()) - 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_supplier(form.Party( - name = 'facho-supplier', - ident = form.PartyIdentification('123','', '31'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - inv.set_customer(form.Party( - name = 'facho-customer', - ident = form.PartyIdentification('321','', '31'), - responsability_code = form.Responsability(['O-07']), - responsability_regime_code = '48', - organization_code = '1', - address = form.Address( - '', '', form.City('05001', 'Medellín'), - form.Country('CO', 'Colombia'), - form.CountrySubentity('05', 'Antioquia')) - )) - inv.add_invoice_line(form.InvoiceLine( - quantity = 1, - description = 'producto facho', - item = form.StandardItem('test', 9999), - price = form.Price(form.Amount(100.0), '01', ''), - tax = form.TaxTotal( - tax_amount = form.Amount(0.0), - taxable_amount = form.Amount(0.0), - subtotals = [ - form.TaxSubTotal( - percent = 19.0, - ) - ] - ) - )) - return inv - +from fixtures import * def test_invoicesimple_build(simple_invoice): xml = DIANInvoiceXML(simple_invoice) diff --git a/tests/test_query.py b/tests/test_query.py new file mode 100644 index 0000000..0faf899 --- /dev/null +++ b/tests/test_query.py @@ -0,0 +1,26 @@ +#!/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 + +import facho.fe.form as form +from facho import fe +from facho.fe.form_xml import DIANInvoiceXML, DIANCreditNoteXML, DIANDebitNoteXML + +from fixtures import * + +from facho.fe.form import query + +def test_query_billing_reference(simple_invoice): + xml = DIANInvoiceXML(simple_invoice) + cufe_extension = fe.DianXMLExtensionCUFE(simple_invoice) + xml.add_extension(cufe_extension) + out = xml.tostring() + + reference = query.billing_reference(out, form.BillingReference) + assert isinstance(reference, form.BillingReference) + assert reference.ident != '' + assert reference.uuid != '' + assert reference.date != ''