facho/fe/fe.py (DianZIP): creado zip nombrando segun DIAN
FossilOrigin-Name: 6df54d31796b2c119bd6b1bfe5f30fafa7adf0521907012509104f4b1e267d7e
This commit is contained in:
parent
10f021d0fd
commit
34032e8a45
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
|
*.bk
|
||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
@ -191,3 +191,6 @@ class FachoXML:
|
|||||||
|
|
||||||
def tostring(self):
|
def tostring(self):
|
||||||
return self.builder.tostring(self.root)
|
return self.builder.tostring(self.root)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.tostring()
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
from .fe import DianXMLExtensionSigner
|
from .fe import DianXMLExtensionSigner
|
||||||
from .fe import FeXML
|
from .fe import FeXML
|
||||||
from .fe import NAMESPACES
|
from .fe import NAMESPACES
|
||||||
|
from .fe import DianZIP
|
||||||
|
@ -6,8 +6,10 @@ import xmlsig
|
|||||||
import xades
|
import xades
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import OpenSSL
|
import OpenSSL
|
||||||
|
import zipfile
|
||||||
import warnings
|
import warnings
|
||||||
|
import hashlib
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
NAMESPACES = {
|
NAMESPACES = {
|
||||||
'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1',
|
'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1',
|
||||||
@ -124,3 +126,29 @@ class DianXMLExtensionSigner:
|
|||||||
return (dian_path, [signature])
|
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,6 +128,7 @@ class Invoice(DataValidator):
|
|||||||
self.invoice_customer = None
|
self.invoice_customer = None
|
||||||
self.invoice_supplier = None
|
self.invoice_supplier = None
|
||||||
self.invoice_lines = []
|
self.invoice_lines = []
|
||||||
|
self.errors = []
|
||||||
|
|
||||||
def set_period(self, startdate, enddate):
|
def set_period(self, startdate, enddate):
|
||||||
self.invoice_period_start = startdate
|
self.invoice_period_start = startdate
|
||||||
@ -151,7 +152,11 @@ class Invoice(DataValidator):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
errors_customer = [('customer.%s' % (field), err) for field, err in self.invoice_customer.validate()]
|
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()]
|
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):
|
def _calculate_legal_monetary_total(self):
|
||||||
for invline in self.invoice_lines:
|
for invline in self.invoice_lines:
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import io
|
||||||
|
import zipfile
|
||||||
|
|
||||||
import facho.fe.form as form
|
import facho.fe.form as form
|
||||||
from facho import fe
|
from facho import fe
|
||||||
@ -50,7 +52,7 @@ def simple_invoice():
|
|||||||
|
|
||||||
|
|
||||||
def test_invoicesimple_build(simple_invoice):
|
def test_invoicesimple_build(simple_invoice):
|
||||||
assert simple_invoice.validate() == []
|
assert simple_invoice.valid() == True
|
||||||
xml = form.DIANInvoiceXML(simple_invoice)
|
xml = form.DIANInvoiceXML(simple_invoice)
|
||||||
|
|
||||||
supplier_name = xml.get_element_text('/fe:Invoice/fe:AccountingSupplierParty/fe:Party/cac:PartyName/cbc:Name')
|
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):
|
def test_invoicesimple_build_with_cufe(simple_invoice):
|
||||||
assert simple_invoice.validate() == []
|
assert simple_invoice.valid() == True
|
||||||
xml = form.DIANInvoiceXML(simple_invoice)
|
xml = form.DIANInvoiceXML(simple_invoice)
|
||||||
cufe = xml.get_element_text('/fe:Invoice/cbc:UUID')
|
cufe = xml.get_element_text('/fe:Invoice/cbc:UUID')
|
||||||
assert cufe != ''
|
assert cufe != ''
|
||||||
|
|
||||||
|
|
||||||
def test_invoicesimple_xml_signed(simple_invoice):
|
def test_invoicesimple_xml_signed(simple_invoice):
|
||||||
assert simple_invoice.validate() == []
|
assert simple_invoice.valid() == True
|
||||||
xml = form.DIANInvoiceXML(simple_invoice)
|
xml = form.DIANInvoiceXML(simple_invoice)
|
||||||
|
|
||||||
signer = fe.DianXMLExtensionSigner('./tests/example.p12')
|
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')
|
elem = xml.find_or_create_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/ds:Signature')
|
||||||
assert elem.text is not None
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user