facho/fe/fe.py (DianZIP): creado zip nombrando segun DIAN
FossilOrigin-Name: 6df54d31796b2c119bd6b1bfe5f30fafa7adf0521907012509104f4b1e267d7e
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,6 +3,7 @@ | ||||
| __pycache__/ | ||||
| *.py[cod] | ||||
| *$py.class | ||||
| *.bk | ||||
|  | ||||
| # C extensions | ||||
| *.so | ||||
|   | ||||
| @@ -191,3 +191,6 @@ class FachoXML: | ||||
|  | ||||
|     def tostring(self): | ||||
|         return self.builder.tostring(self.root) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.tostring() | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| from .fe import DianXMLExtensionSigner | ||||
| from .fe import FeXML | ||||
| from .fe import NAMESPACES | ||||
| from .fe import DianZIP | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user