From 34032e8a4590507d0c69804a762acef21bf1602a Mon Sep 17 00:00:00 2001 From: "bit4bit@riseup.net" Date: Sat, 23 May 2020 20:04:57 +0000 Subject: [PATCH] facho/fe/fe.py (DianZIP): creado zip nombrando segun DIAN FossilOrigin-Name: 6df54d31796b2c119bd6b1bfe5f30fafa7adf0521907012509104f4b1e267d7e --- .gitignore | 1 + facho/facho.py | 3 +++ facho/fe/__init__.py | 1 + facho/fe/fe.py | 30 +++++++++++++++++++++++++++++- facho/fe/form.py | 9 +++++++-- tests/test_fe_form.py | 19 ++++++++++++++++--- 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 1b9da19..9c46d92 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ __pycache__/ *.py[cod] *$py.class +*.bk # C extensions *.so diff --git a/facho/facho.py b/facho/facho.py index 82c0397..e4e17e0 100644 --- a/facho/facho.py +++ b/facho/facho.py @@ -191,3 +191,6 @@ class FachoXML: def tostring(self): return self.builder.tostring(self.root) + + def __str__(self): + return self.tostring() diff --git a/facho/fe/__init__.py b/facho/fe/__init__.py index cacda42..7206887 100644 --- a/facho/fe/__init__.py +++ b/facho/fe/__init__.py @@ -1,3 +1,4 @@ from .fe import DianXMLExtensionSigner from .fe import FeXML from .fe import NAMESPACES +from .fe import DianZIP diff --git a/facho/fe/fe.py b/facho/fe/fe.py index 63fc0dc..085d1e4 100644 --- a/facho/fe/fe.py +++ b/facho/fe/fe.py @@ -6,8 +6,10 @@ import xmlsig import xades from datetime import datetime import OpenSSL - +import zipfile import warnings +import hashlib +from contextlib import contextmanager NAMESPACES = { 'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1', @@ -124,3 +126,29 @@ class DianXMLExtensionSigner: return (dian_path, [signature]) + +class DianZIP: + + # RESOLUCION 0001: pagina 540 + MAX_FILES = 50 + + def __init__(self, file_like): + self.zipfile = zipfile.ZipFile(file_like, mode='w') + self.num_files = 0 + + def add_invoice_xml(self, name, xml_data): + self.num_files += 1 + # TODO cual es la norma para los nombres de archivos? + m = hashlib.sha256() + m.update(name.encode('utf-8')) + filename = m.hexdigest() + '.xml' + with self.zipfile.open(filename, 'w') as fp: + fp.write(xml_data.encode('utf-8')) + + return filename + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + return self.zipfile.close() diff --git a/facho/fe/form.py b/facho/fe/form.py index 6c44201..d3b04b9 100644 --- a/facho/fe/form.py +++ b/facho/fe/form.py @@ -128,7 +128,8 @@ class Invoice(DataValidator): self.invoice_customer = None self.invoice_supplier = None self.invoice_lines = [] - + self.errors = [] + def set_period(self, startdate, enddate): self.invoice_period_start = startdate self.invoice_period_end = enddate @@ -151,7 +152,11 @@ class Invoice(DataValidator): def validate(self): errors_customer = [('customer.%s' % (field), err) for field, err in self.invoice_customer.validate()] errors_supplier = [('supplier.%s' % (field), err) for field, err in self.invoice_customer.validate()] - return errors_customer + errors_supplier + self.errors = errors_customer + errors_supplier + + def valid(self): + self.validate() + return not self.errors def _calculate_legal_monetary_total(self): for invline in self.invoice_lines: diff --git a/tests/test_fe_form.py b/tests/test_fe_form.py index 4616140..0fe4db9 100644 --- a/tests/test_fe_form.py +++ b/tests/test_fe_form.py @@ -7,6 +7,8 @@ import pytest from datetime import datetime +import io +import zipfile import facho.fe.form as form from facho import fe @@ -50,7 +52,7 @@ def simple_invoice(): def test_invoicesimple_build(simple_invoice): - assert simple_invoice.validate() == [] + assert simple_invoice.valid() == True xml = form.DIANInvoiceXML(simple_invoice) supplier_name = xml.get_element_text('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/cac:PartyName/cbc:Name') @@ -67,14 +69,14 @@ def test_invoicesimple_build(simple_invoice): def test_invoicesimple_build_with_cufe(simple_invoice): - assert simple_invoice.validate() == [] + assert simple_invoice.valid() == True 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() == [] + assert simple_invoice.valid() == True xml = form.DIANInvoiceXML(simple_invoice) signer = fe.DianXMLExtensionSigner('./tests/example.p12') @@ -84,3 +86,14 @@ def test_invoicesimple_xml_signed(simple_invoice): elem = xml.find_or_create_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ds:Signature') assert elem.text is not None + +def test_invoicesimple_zip(simple_invoice): + xml_invoice = form.DIANInvoiceXML(simple_invoice) + + zipdata = io.BytesIO() + with fe.DianZIP(zipdata) as dianzip: + name_invoice = dianzip.add_invoice_xml(simple_invoice.invoice_ident, str(xml_invoice)) + + with zipfile.ZipFile(zipdata) as dianzip: + xml_data = dianzip.open(name_invoice).read().decode('utf-8') + assert xml_data == str(xml_invoice)