se extrae generacion de CUFE a DianXMLExtensionCUFE
FossilOrigin-Name: 964ad19875edfc7f6990f795396eeeb4c66809eefe93303b1479d6c3ad2e2484
This commit is contained in:
parent
5d564ef149
commit
52632babb2
@ -80,12 +80,13 @@ def generate_invoice(private_key, passphrase, scriptname):
|
||||
|
||||
invoice = module.invoice()
|
||||
invoice.calculate()
|
||||
xml = form.DIANInvoiceXML(invoice)
|
||||
params = module.params()
|
||||
xml = form.DIANInvoiceXML(invoice, **params)
|
||||
|
||||
extensions = module.extensions(invoice)
|
||||
for extension in extensions:
|
||||
xml.add_extension(extension)
|
||||
|
||||
|
||||
if private_key:
|
||||
signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase)
|
||||
xml.add_extension(signer)
|
||||
|
@ -136,7 +136,7 @@ class FachoXML:
|
||||
elem = self.set_element('/'+ root_tag + xpath, elements)
|
||||
else:
|
||||
for new_element in elements:
|
||||
elem = self.find_or_create_element('/'+ root_tag + xpath)
|
||||
elem = self.find_or_create_element('/' + root_tag + xpath)
|
||||
self.builder.append(elem, new_element)
|
||||
|
||||
def fragment(self, xpath, append=False):
|
||||
|
@ -2,4 +2,5 @@ from .fe import FeXML
|
||||
from .fe import NAMESPACES
|
||||
from .fe import DianXMLExtensionSigner
|
||||
from .fe import DianXMLExtensionSoftwareSecurityCode
|
||||
from .fe import DianXMLExtensionCUFE
|
||||
from .fe import DianZIP
|
||||
|
@ -10,6 +10,7 @@ import zipfile
|
||||
import warnings
|
||||
import hashlib
|
||||
from contextlib import contextmanager
|
||||
from .data import dian
|
||||
|
||||
NAMESPACES = {
|
||||
'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1',
|
||||
@ -39,7 +40,74 @@ class FeXML(FachoXML):
|
||||
#self.find_or_create_element(self._cn)
|
||||
|
||||
|
||||
class DianXMLExtensionCUFE(FachoXMLExtension):
|
||||
AMBIENTE_PRUEBAS = 'Pruebas'
|
||||
AMBIENTE_PRODUCCION = 'Producción'
|
||||
|
||||
def __init__(self, invoice, tipo_ambiente = AMBIENTE_PRUEBAS, clave_tecnica = ''):
|
||||
self.tipo_ambiente = tipo_ambiente
|
||||
self.clave_tecnica = clave_tecnica
|
||||
self.invoice = invoice
|
||||
|
||||
def _tipo_ambiente(self):
|
||||
return int(dian.TipoAmbiente[self.tipo_ambiente]['code'])
|
||||
|
||||
def build(self, fachoxml):
|
||||
cufe = self._generate_cufe(self.invoice, fachoxml)
|
||||
fachoxml.set_element('/fe:Invoice/cbc:UUID[schemaName="CUFE-SHA384"]', cufe)
|
||||
fachoxml.set_element('/fe:Invoice/cbc:ProfileExecutionID', self._tipo_ambiente())
|
||||
return '', []
|
||||
|
||||
def _generate_cufe(self, invoice, fachoxml):
|
||||
NumFac = invoice.invoice_ident
|
||||
FecFac = fachoxml.issue_date(invoice.invoice_issue)
|
||||
HoraFac = fachoxml.issue_time(invoice.invoice_issue)
|
||||
ValorBruto = invoice.invoice_legal_monetary_total.line_extension_amount
|
||||
ValorTotalPagar = invoice.invoice_legal_monetary_total.payable_amount
|
||||
ValorImpuestoPara = {}
|
||||
ValorImpuesto1 = 0.0
|
||||
CodImpuesto1 = 1
|
||||
ValorImpuesto2 = 0.0
|
||||
CodImpuesto2 = 4
|
||||
ValorImpuesto3 = 0.0
|
||||
CodImpuesto3 = 3
|
||||
for invoice_line in invoice.invoice_lines:
|
||||
for subtotal in invoice_line.tax.subtotals:
|
||||
# TODO cual es la naturaleza de tax_scheme_ident?
|
||||
codigo_impuesto = int(subtotal.tax_scheme_ident)
|
||||
ValorImpuestoPara.setdefault(codigo_impuesto, 0.0)
|
||||
ValorImpuestoPara[codigo_impuesto] += subtotal.tax_amount
|
||||
|
||||
NitOFE = invoice.invoice_supplier.ident
|
||||
NumAdq = invoice.invoice_customer.ident
|
||||
TipoAmb = self._tipo_ambiente()
|
||||
ClTec = str(self.clave_tecnica)
|
||||
|
||||
formatVars = [
|
||||
'%s' % NumFac,
|
||||
'%s' % FecFac,
|
||||
'%s' % HoraFac,
|
||||
'%.02f' % ValorBruto,
|
||||
'%02d' % CodImpuesto1,
|
||||
'%.02f' % ValorImpuestoPara.get(CodImpuesto1, 0.0),
|
||||
'%02d' % CodImpuesto2,
|
||||
'%.02f' % ValorImpuestoPara.get(CodImpuesto2, 0.0),
|
||||
'%02d' % CodImpuesto3,
|
||||
'%.02f' % ValorImpuestoPara.get(CodImpuesto3, 0.0),
|
||||
'%.02f' % ValorTotalPagar,
|
||||
'%s' % NitOFE,
|
||||
'%s' % NumAdq,
|
||||
'%s' % ClTec,
|
||||
'%d' % TipoAmb,
|
||||
]
|
||||
cufe = "".join(formatVars)
|
||||
|
||||
# crear hash...
|
||||
h = hashlib.sha384()
|
||||
h.update(cufe.encode('utf-8'))
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
class DianXMLExtensionSoftwareSecurityCode(FachoXMLExtension):
|
||||
# RESOLUCION 0001: pagina 535
|
||||
|
||||
|
@ -92,7 +92,6 @@ class Invoice:
|
||||
self.invoice_period_end = None
|
||||
self.invoice_issue = None
|
||||
self.invoice_ident = None
|
||||
self.invoice_cufe = None
|
||||
self.invoice_legal_monetary_total = LegalMonetaryTotal(0, 0, 0, 0, 0)
|
||||
self.invoice_customer = None
|
||||
self.invoice_supplier = None
|
||||
@ -168,19 +167,12 @@ class DianResolucion0001Validator:
|
||||
def valid(self):
|
||||
return not self.errors
|
||||
|
||||
|
||||
class DIANInvoiceXML(fe.FeXML):
|
||||
AMBIENTE_PRUEBAS = 'Pruebas'
|
||||
AMBIENTE_PRODUCCION = 'Producción'
|
||||
|
||||
def __init__(self, invoice, tipo_ambiente = AMBIENTE_PRUEBAS, clave_tecnica = ''):
|
||||
super().__init__('Invoice', 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
|
||||
self.tipo_ambiente = tipo_ambiente
|
||||
self.clave_tecnica = clave_tecnica
|
||||
self.attach_invoice(invoice)
|
||||
|
||||
def _tipo_ambiente(self):
|
||||
return int(dian.TipoAmbiente[self.tipo_ambiente]['code'])
|
||||
class DIANInvoiceXML(fe.FeXML):
|
||||
|
||||
def __init__(self, invoice):
|
||||
super().__init__('Invoice', 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
|
||||
self.attach_invoice(invoice)
|
||||
|
||||
def attach_invoice(self, invoice):
|
||||
"""adiciona etiquetas a FEXML y retorna FEXML
|
||||
@ -189,11 +181,7 @@ class DIANInvoiceXML(fe.FeXML):
|
||||
|
||||
invoice.calculate()
|
||||
|
||||
cufe = self._generate_cufe(invoice)
|
||||
|
||||
fexml.set_element('/fe:Invoice/cbc:ProfileExecutionID', self._tipo_ambiente())
|
||||
fexml.set_element('/fe:Invoice/cbc:ID', invoice.invoice_ident)
|
||||
fexml.set_element('/fe:Invoice/cbc:UUID[schemaName="CUFE-SHA384"]', cufe)
|
||||
fexml.set_element('/fe:Invoice/cbc:IssueDate', self.issue_date(invoice.invoice_issue))
|
||||
fexml.set_element('/fe:Invoice/cbc:IssueTime', self.issue_time(invoice.invoice_issue))
|
||||
fexml.set_element('/fe:Invoice/cac:InvoicePeriod/cbc:StartDate', invoice.invoice_period_start.strftime('%Y-%m-%d'))
|
||||
@ -265,53 +253,4 @@ class DIANInvoiceXML(fe.FeXML):
|
||||
return datetime_.strftime('%H:%M:%S%z')
|
||||
def issue_date(self, datetime_):
|
||||
return datetime_.strftime('%Y-%m-%d')
|
||||
|
||||
def _generate_cufe(self, invoice):
|
||||
NumFac = invoice.invoice_ident
|
||||
FecFac = self.issue_date(invoice.invoice_issue)
|
||||
HoraFac = self.issue_time(invoice.invoice_issue)
|
||||
ValorBruto = invoice.invoice_legal_monetary_total.line_extension_amount
|
||||
ValorTotalPagar = invoice.invoice_legal_monetary_total.payable_amount
|
||||
ValorImpuestoPara = {}
|
||||
ValorImpuesto1 = 0.0
|
||||
CodImpuesto1 = 1
|
||||
ValorImpuesto2 = 0.0
|
||||
CodImpuesto2 = 4
|
||||
ValorImpuesto3 = 0.0
|
||||
CodImpuesto3 = 3
|
||||
for invoice_line in invoice.invoice_lines:
|
||||
for subtotal in invoice_line.tax.subtotals:
|
||||
# TODO cual es la naturaleza de tax_scheme_ident?
|
||||
codigo_impuesto = int(subtotal.tax_scheme_ident)
|
||||
ValorImpuestoPara.setdefault(codigo_impuesto, 0.0)
|
||||
ValorImpuestoPara[codigo_impuesto] += subtotal.tax_amount
|
||||
|
||||
NitOFE = invoice.invoice_supplier.ident
|
||||
NumAdq = invoice.invoice_customer.ident
|
||||
TipoAmb = self._tipo_ambiente()
|
||||
ClTec = str(self.clave_tecnica)
|
||||
|
||||
formatVars = [
|
||||
'%s' % NumFac,
|
||||
'%s' % FecFac,
|
||||
'%s' % HoraFac,
|
||||
'%.02f' % ValorBruto,
|
||||
'%02d' % CodImpuesto1,
|
||||
'%.02f' % ValorImpuestoPara.get(CodImpuesto1, 0.0),
|
||||
'%02d' % CodImpuesto2,
|
||||
'%.02f' % ValorImpuestoPara.get(CodImpuesto2, 0.0),
|
||||
'%02d' % CodImpuesto3,
|
||||
'%.02f' % ValorImpuestoPara.get(CodImpuesto3, 0.0),
|
||||
'%.02f' % ValorTotalPagar,
|
||||
'%s' % NitOFE,
|
||||
'%s' % NumAdq,
|
||||
'%s' % ClTec,
|
||||
'%d' % TipoAmb,
|
||||
]
|
||||
cufe = "".join(formatVars)
|
||||
|
||||
# crear hash...
|
||||
h = hashlib.sha384()
|
||||
h.update(cufe.encode('utf-8'))
|
||||
return h.hexdigest()
|
||||
|
||||
|
@ -94,6 +94,9 @@ def test_invoicesimple_build_with_cufe(simple_invoice):
|
||||
simple_invoice.validate(invoice_validator)
|
||||
assert invoice_validator.valid() == True
|
||||
xml = form.DIANInvoiceXML(simple_invoice)
|
||||
cufe_extension = fe.DianXMLExtensionCUFE(simple_invoice)
|
||||
xml.add_extension(cufe_extension)
|
||||
xml.attach_extensions()
|
||||
cufe = xml.get_element_text('/fe:Invoice/cbc:UUID')
|
||||
assert cufe != ''
|
||||
|
||||
@ -139,6 +142,9 @@ def test_invoice_line_count_numeric(simple_invoice):
|
||||
|
||||
def test_invoice_profileexecutionid(simple_invoice):
|
||||
xml_invoice = form.DIANInvoiceXML(simple_invoice)
|
||||
cufe_extension = fe.DianXMLExtensionCUFE(simple_invoice)
|
||||
xml_invoice.add_extension(cufe_extension)
|
||||
xml_invoice.attach_extensions()
|
||||
id_ = xml_invoice.get_element_text('/fe:Invoice/cbc:ProfileExecutionID', format_=int)
|
||||
assert id_ == 2
|
||||
|
||||
@ -190,9 +196,15 @@ def test_invoice_cufe(simple_invoice_without_lines):
|
||||
def issue_date(self, datetime_):
|
||||
return '2019-01-16'
|
||||
|
||||
xml_invoice = FakeDIANInvoiceXML(simple_invoice,
|
||||
tipo_ambiente = form.DIANInvoiceXML.AMBIENTE_PRODUCCION,
|
||||
clave_tecnica = '693ff6f2a553c3646a063436fd4dd9ded0311471')
|
||||
xml_invoice = FakeDIANInvoiceXML(simple_invoice)
|
||||
|
||||
cufe_extension = fe.DianXMLExtensionCUFE(
|
||||
simple_invoice,
|
||||
tipo_ambiente = fe.DianXMLExtensionCUFE.AMBIENTE_PRODUCCION,
|
||||
clave_tecnica = '693ff6f2a553c3646a063436fd4dd9ded0311471'
|
||||
)
|
||||
xml_invoice.add_extension(cufe_extension)
|
||||
xml_invoice.attach_extensions()
|
||||
cufe = xml_invoice.get_element_text('/fe:Invoice/cbc:UUID')
|
||||
# RESOLUCION 004: pagina 689
|
||||
assert cufe == '8bb918b19ba22a694f1da11c643b5e9de39adf60311cf179179e9b33381030bcd4c3c3f156c506ed5908f9276f5bd9b4'
|
||||
|
Loading…
Reference in New Issue
Block a user