fache/fe/fe.py(DianXMLExtensionCUDE): nuevo.
FossilOrigin-Name: edced6a3095b29e92295242a73ac4654498abe458d4037b21eb13a4b351d60fd
This commit is contained in:
parent
9ab8238736
commit
1429a01f91
@ -3,8 +3,11 @@ from .fe import NAMESPACES
|
||||
from .fe import DianXMLExtensionSigner
|
||||
from .fe import DianXMLExtensionSoftwareSecurityCode
|
||||
from .fe import DianXMLExtensionCUFE
|
||||
from .fe import DianXMLExtensionCUDE
|
||||
from .fe import DianXMLExtensionInvoiceAuthorization
|
||||
from .fe import DianXMLExtensionSoftwareProvider
|
||||
from .fe import DianXMLExtensionAuthorizationProvider
|
||||
from .fe import DianZIP
|
||||
from .fe import AMBIENTE_PRUEBAS
|
||||
from .fe import AMBIENTE_PRODUCCION
|
||||
from . import form_xml
|
||||
|
137
facho/fe/fe.py
137
facho/fe/fe.py
@ -14,6 +14,10 @@ from contextlib import contextmanager
|
||||
from .data.dian import codelist
|
||||
from . import form
|
||||
|
||||
AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code']
|
||||
AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code']
|
||||
|
||||
|
||||
SCHEME_AGENCY_ATTRS = {
|
||||
'schemeAgencyName': 'CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)',
|
||||
'schemeAgencyID': '195'
|
||||
@ -76,20 +80,18 @@ class FeXML(FachoXML):
|
||||
.replace("xmlns:fe", "xmlns")
|
||||
|
||||
|
||||
class DianXMLExtensionCUFE(FachoXMLExtension):
|
||||
AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code']
|
||||
AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code']
|
||||
|
||||
def __init__(self, invoice, tipo_ambiente = AMBIENTE_PRUEBAS, clave_tecnica = ''):
|
||||
class DianXMLExtensionCUDFE(FachoXMLExtension):
|
||||
|
||||
def __init__(self, invoice, tipo_ambiente = AMBIENTE_PRUEBAS):
|
||||
self.tipo_ambiente = tipo_ambiente
|
||||
self.clave_tecnica = clave_tecnica
|
||||
self.invoice = invoice
|
||||
|
||||
def _tipo_ambiente(self):
|
||||
return int(self.tipo_ambiente)
|
||||
|
||||
def build(self, fachoxml):
|
||||
cufe = self._generate_cufe(self.invoice, fachoxml)
|
||||
cufe = self._generate_cufe(fachoxml)
|
||||
fachoxml.set_element('./cbc:UUID', cufe,
|
||||
schemeID=self.tipo_ambiente,
|
||||
schemeName='CUFE-SHA384')
|
||||
@ -105,49 +107,38 @@ class DianXMLExtensionCUFE(FachoXMLExtension):
|
||||
def issue_date(self, datetime_):
|
||||
return datetime_.strftime('%Y-%m-%d')
|
||||
|
||||
def formatVars(self, invoice):
|
||||
NumFac = invoice.invoice_ident
|
||||
FecFac = self.issue_date(invoice.invoice_issue)
|
||||
HoraFac = self.issue_time(invoice.invoice_issue)
|
||||
def buildVars(self):
|
||||
invoice = self.invoice
|
||||
build_vars = {}
|
||||
build_vars['NumFac'] = invoice.invoice_ident
|
||||
build_vars['FecFac'] = self.issue_date(invoice.invoice_issue)
|
||||
build_vars['HoraFac'] = self.issue_time(invoice.invoice_issue)
|
||||
# PAG 601
|
||||
ValorBruto = invoice.invoice_legal_monetary_total.line_extension_amount
|
||||
ValorTotalPagar = invoice.invoice_legal_monetary_total.payable_amount
|
||||
build_vars['ValorBruto'] = invoice.invoice_legal_monetary_total.line_extension_amount
|
||||
build_vars['ValorTotalPagar'] = invoice.invoice_legal_monetary_total.payable_amount
|
||||
ValorImpuestoPara = {}
|
||||
CodImpuesto1 = 1
|
||||
CodImpuesto2 = 4
|
||||
CodImpuesto3 = 3
|
||||
build_vars['CodImpuesto1'] = 1
|
||||
build_vars['CodImpuesto2'] = 4
|
||||
build_vars['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, form.Amount(0.0))
|
||||
ValorImpuestoPara[codigo_impuesto] += subtotal.tax_amount
|
||||
build_vars['ValorImpuestoPara'] = ValorImpuestoPara
|
||||
build_vars['NitOFE'] = invoice.invoice_supplier.ident
|
||||
build_vars['NumAdq'] = invoice.invoice_customer.ident
|
||||
build_vars['TipoAmb'] = self._tipo_ambiente()
|
||||
|
||||
NitOFE = invoice.invoice_supplier.ident
|
||||
NumAdq = invoice.invoice_customer.ident
|
||||
TipoAmb = self._tipo_ambiente()
|
||||
ClTec = str(self.clave_tecnica)
|
||||
return build_vars
|
||||
|
||||
return [
|
||||
'%s' % NumFac,
|
||||
'%s' % FecFac,
|
||||
'%s' % HoraFac,
|
||||
'%.02f' % round(ValorBruto, 2),
|
||||
'%02d' % CodImpuesto1,
|
||||
'%.02f' % round(ValorImpuestoPara.get(CodImpuesto1, 0.0), 2),
|
||||
'%02d' % CodImpuesto2,
|
||||
'%.02f' % round(ValorImpuestoPara.get(CodImpuesto2, 0.0), 2),
|
||||
'%02d' % CodImpuesto3,
|
||||
'%.02f' % round(ValorImpuestoPara.get(CodImpuesto3, 0.0), 2),
|
||||
'%.02f' % round(ValorTotalPagar, 2),
|
||||
'%s' % NitOFE,
|
||||
'%s' % NumAdq,
|
||||
'%s' % ClTec,
|
||||
'%d' % TipoAmb,
|
||||
]
|
||||
|
||||
def _generate_cufe(self, invoice, fachoxml):
|
||||
formatVars = self.formatVars(invoice)
|
||||
def formatVars(self, invoice):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _generate_cufe(self, fachoxml):
|
||||
formatVars = self.formatVars()
|
||||
cufe = "".join(formatVars)
|
||||
|
||||
# crear hash...
|
||||
@ -156,6 +147,74 @@ class DianXMLExtensionCUFE(FachoXMLExtension):
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
class DianXMLExtensionCUFE(DianXMLExtensionCUDFE):
|
||||
def __init__(self, invoice, tipo_ambiente = AMBIENTE_PRUEBAS, clave_tecnica = ''):
|
||||
self.tipo_ambiente = tipo_ambiente
|
||||
self.clave_tecnica = clave_tecnica
|
||||
self.invoice = invoice
|
||||
|
||||
def buildVars(self):
|
||||
build_vars = super().buildVars()
|
||||
build_vars['ClTec'] = str(self.clave_tecnica)
|
||||
return build_vars
|
||||
|
||||
def formatVars(self):
|
||||
build_vars = self.buildVars()
|
||||
CodImpuesto1 = build_vars['CodImpuesto1']
|
||||
CodImpuesto2 = build_vars['CodImpuesto2']
|
||||
CodImpuesto3 = build_vars['CodImpuesto3']
|
||||
return [
|
||||
'%s' % build_vars['NumFac'],
|
||||
'%s' % build_vars['FecFac'],
|
||||
'%s' % build_vars['HoraFac'],
|
||||
'%.02f' % round(build_vars['ValorBruto'], 2),
|
||||
'%02d' % CodImpuesto1,
|
||||
'%.02f' % round(build_vars['ValorImpuestoPara'].get(CodImpuesto1, 0.0), 2),
|
||||
'%02d' % CodImpuesto2,
|
||||
'%.02f' % round(build_vars['ValorImpuestoPara'].get(CodImpuesto2, 0.0), 2),
|
||||
'%02d' % CodImpuesto3,
|
||||
'%.02f' % round(build_vars['ValorImpuestoPara'].get(CodImpuesto3, 0.0), 2),
|
||||
'%.02f' % round(build_vars['ValorTotalPagar'], 2),
|
||||
'%s' % build_vars['NitOFE'],
|
||||
'%s' % build_vars['NumAdq'],
|
||||
'%s' % build_vars['ClTec'],
|
||||
'%d' % build_vars['TipoAmb'],
|
||||
]
|
||||
|
||||
class DianXMLExtensionCUDE(DianXMLExtensionCUDFE):
|
||||
def __init__(self, invoice, software_pin, tipo_ambiente = AMBIENTE_PRUEBAS):
|
||||
self.tipo_ambiente = tipo_ambiente
|
||||
self.software_pin = software_pin
|
||||
self.invoice = invoice
|
||||
|
||||
def buildVars(self):
|
||||
build_vars = super().buildVars()
|
||||
build_vars['Software-PIN'] = str(self.software_pin)
|
||||
return build_vars
|
||||
|
||||
def formatVars(self):
|
||||
build_vars = self.buildVars()
|
||||
CodImpuesto1 = build_vars['CodImpuesto1']
|
||||
CodImpuesto2 = build_vars['CodImpuesto2']
|
||||
CodImpuesto3 = build_vars['CodImpuesto3']
|
||||
return [
|
||||
'%s' % build_vars['NumFac'],
|
||||
'%s' % build_vars['FecFac'],
|
||||
'%s' % build_vars['HoraFac'],
|
||||
'%.02f' % round(build_vars['ValorBruto'], 2),
|
||||
'%02d' % CodImpuesto1,
|
||||
'%.02f' % round(build_vars['ValorImpuestoPara'].get(CodImpuesto1, 0.0), 2),
|
||||
'%02d' % CodImpuesto2,
|
||||
'%.02f' % round(build_vars['ValorImpuestoPara'].get(CodImpuesto2, 0.0), 2),
|
||||
'%02d' % CodImpuesto3,
|
||||
'%.02f' % round(build_vars['ValorImpuestoPara'].get(CodImpuesto3, 0.0), 2),
|
||||
'%.02f' % round(build_vars['ValorTotalPagar'], 2),
|
||||
'%s' % build_vars['NitOFE'],
|
||||
'%s' % build_vars['NumAdq'],
|
||||
'%s' % build_vars['Software-PIN'],
|
||||
'%d' % build_vars['TipoAmb'],
|
||||
]
|
||||
|
||||
class DianXMLExtensionSoftwareProvider(FachoXMLExtension):
|
||||
# RESOLUCION 0004: pagina 108
|
||||
|
||||
@ -300,7 +359,7 @@ class DianXMLExtensionInvoiceSource(FachoXMLExtension):
|
||||
listAgencyID="6",
|
||||
listAgencyName="United Nations Economic Commission for Europe",
|
||||
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1")
|
||||
|
||||
|
||||
|
||||
class DianXMLExtensionInvoiceAuthorization(FachoXMLExtension):
|
||||
# RESOLUCION 0004: pagina 106
|
||||
|
@ -470,6 +470,8 @@ class NationalSalesInvoice(Invoice):
|
||||
|
||||
class CreditNote(Invoice):
|
||||
def __init__(self, invoice_document_reference: BillingReference):
|
||||
super().__init__(CreditNoteDocumentType())
|
||||
|
||||
if not isinstance(invoice_document_reference, BillingReference):
|
||||
raise TypeError('invoice_document_reference invalid type')
|
||||
self.invoice_billing_reference = invoice_document_reference
|
||||
|
@ -12,7 +12,39 @@ import zipfile
|
||||
|
||||
import facho.fe.form as form
|
||||
from facho import fe
|
||||
from facho.fe.form_xml import DIANInvoiceXML
|
||||
from facho.fe.form_xml import DIANInvoiceXML, DIANCreditNoteXML
|
||||
|
||||
@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('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_without_lines():
|
||||
@ -207,10 +239,10 @@ def test_invoice_cufe(simple_invoice_without_lines):
|
||||
|
||||
cufe_extension = fe.DianXMLExtensionCUFE(
|
||||
simple_invoice,
|
||||
tipo_ambiente = fe.DianXMLExtensionCUFE.AMBIENTE_PRODUCCION,
|
||||
tipo_ambiente = fe.AMBIENTE_PRODUCCION,
|
||||
clave_tecnica = '693ff6f2a553c3646a063436fd4dd9ded0311471'
|
||||
)
|
||||
formatVars = cufe_extension.formatVars(simple_invoice)
|
||||
formatVars = cufe_extension.formatVars()
|
||||
#NumFac
|
||||
assert formatVars[0] == '323200000129', "NumFac"
|
||||
#FecFac
|
||||
@ -246,3 +278,37 @@ def test_invoice_cufe(simple_invoice_without_lines):
|
||||
cufe = xml_invoice.get_element_text('/fe:Invoice/cbc:UUID')
|
||||
# RESOLUCION 004: pagina 689
|
||||
assert cufe == '8bb918b19ba22a694f1da11c643b5e9de39adf60311cf179179e9b33381030bcd4c3c3f156c506ed5908f9276f5bd9b4'
|
||||
|
||||
|
||||
def test_credit_note_cude(simple_credit_note_without_lines):
|
||||
simple_invoice = simple_credit_note_without_lines
|
||||
simple_invoice.invoice_ident = '8110007871'
|
||||
simple_invoice.invoice_issue = datetime.strptime('2019-01-12 07:00:00-05:00', '%Y-%m-%d %H:%M:%S%z')
|
||||
simple_invoice.invoice_supplier.ident = form.PartyIdentification('900373076', '5', '31')
|
||||
simple_invoice.invoice_customer.ident = form.PartyIdentification('8355990', '5', '31')
|
||||
simple_invoice.add_invoice_line(form.InvoiceLine(
|
||||
quantity = 1,
|
||||
description = 'producto',
|
||||
item = form.StandardItem('test', 111),
|
||||
price = form.Price(form.Amount(5_000), '01', ''),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
tax_scheme_ident = '01',
|
||||
percent = 19.0
|
||||
)])
|
||||
))
|
||||
|
||||
simple_invoice.calculate()
|
||||
xml_invoice = DIANCreditNoteXML(simple_invoice)
|
||||
|
||||
cude_extension = fe.DianXMLExtensionCUDE(
|
||||
simple_invoice,
|
||||
'12301',
|
||||
tipo_ambiente = fe.AMBIENTE_PRODUCCION,
|
||||
)
|
||||
|
||||
xml_invoice.add_extension(cude_extension)
|
||||
cude = xml_invoice.get_element_text('/fe:CreditNote/cbc:UUID')
|
||||
# pag 612
|
||||
assert cude == '907e4444decc9e59c160a2fb3b6659b33dc5b632a5008922b9a62f83f757b1c448e47f5867f2b50dbdb96f48c7681168'
|
||||
|
Loading…
Reference in New Issue
Block a user