nuevo tipo nota credito.

* facho/fe/form.py(NationalSalesInvoice): para facturas de venta
  nacional.
* facho/fe/form.py(CreditNote): para nota creditos.

FossilOrigin-Name: 0590af5ac99b2476943dfeacb11ba8cd801012e409b2b594479229df75ddb484
This commit is contained in:
bit4bit@riseup.net 2020-10-29 01:41:08 +00:00
parent 1c4d9bee75
commit 8707319036
5 changed files with 74 additions and 38 deletions

View File

@ -271,6 +271,14 @@ class BillingReference:
self.uuid = uuid self.uuid = uuid
self.date = date self.date = date
class CreditNoteDocumentReference(BillingReference):
pass
class DebitNoteDocumentReference(BillingReference):
pass
class InvoiceDocumentReference(BillingReference):
pass
@dataclass @dataclass
class InvoiceLine: class InvoiceLine:
@ -338,9 +346,19 @@ class AllowanceCharge:
self.charge_indicator = False self.charge_indicator = False
class NationalSalesInvoiceDocumentType(str):
def __str__(self):
return '01'
class CreditNoteDocumentType(str):
def __str__(self):
return '91'
class Invoice: class Invoice:
def __init__(self): def __init__(self, type_code: str):
if str(type_code) not in codelist.TipoDocumento:
raise ValueError("type_code [%s] not found")
self.invoice_period_start = None self.invoice_period_start = None
self.invoice_period_end = None self.invoice_period_end = None
self.invoice_issue = None self.invoice_issue = None
@ -355,6 +373,8 @@ class Invoice:
self.invoice_allowance_charge = [] self.invoice_allowance_charge = []
self.invoice_prepaid_payment = [] self.invoice_prepaid_payment = []
self.invoice_billing_reference = None self.invoice_billing_reference = None
self.invoice_type_code = str(type_code)
def set_period(self, startdate, enddate): def set_period(self, startdate, enddate):
self.invoice_period_start = startdate self.invoice_period_start = startdate
@ -441,3 +461,15 @@ class Invoice:
for invline in self.invoice_lines: for invline in self.invoice_lines:
invline.calculate() invline.calculate()
self._calculate_legal_monetary_total() self._calculate_legal_monetary_total()
class NationalSalesInvoice(Invoice):
def __init__(self):
super().__init__(NationalSalesInvoiceDocumentType())
class CreditNote(Invoice):
def __init__(self, invoice_document_reference: BillingReference):
if not isinstance(invoice_document_reference, BillingReference):
raise TypeError('invoice_document_reference invalid type')
self.invoice_billing_reference = invoice_document_reference

View File

@ -18,6 +18,3 @@ class DIANCreditNoteXML(DIANInvoiceXML):
def tag_document_concilied(fexml): def tag_document_concilied(fexml):
return 'Credited' return 'Credited'
def document_type_code(fexml):
return codelist.TipoDocumento.by_name('Nota Crédito')['code']

View File

@ -384,19 +384,36 @@ class DIANInvoiceXML(fe.FeXML):
invoice.invoice_legal_monetary_total.payable_amount) invoice.invoice_legal_monetary_total.payable_amount)
def set_billing_reference(fexml, invoice): def _set_invoice_document_reference(fexml, reference):
if invoice.invoice_billing_reference is None: fexml._do_set_billing_reference(reference, 'cac:InvoiceDocumentReference')
return
fexml.placeholder_for('./cac:BillingReference') def _set_credit_note_document_reference(fexml, reference):
fexml.placeholder_for('./cac:BillingReference/cac:InvoiceDocumentReference') fexml._do_set_billing_reference(reference, 'cac:CreditNoteDocumentReference')
fexml.set_element('./cac:BillingReference/cac:InvoiceDocumentReference/cbc:ID',
invoice.invoice_billing_reference.ident) def _set_debit_note_document_reference(fexml, reference):
fexml._do_set_billing_reference(reference, 'cac:DebitNoteDocumentReference')
def _do_set_billing_reference(fexml, reference, tag_document):
fexml.set_element('./cac:BillingReference/%s/cbc:ID' %(tag_document),
reference.ident)
fexml.set_element('./cac:BillingReference/cac:InvoiceDocumentReference/cbc:UUID', fexml.set_element('./cac:BillingReference/cac:InvoiceDocumentReference/cbc:UUID',
invoice.invoice_billing_reference.uuid, reference.uuid,
schemeName='CUFE-SHA384') schemeName='CUFE-SHA384')
fexml.set_element('./cac:BillingReference/cac:InvoiceDocumentReference/cbc:IssueDate', fexml.set_element('./cac:BillingReference/cac:InvoiceDocumentReference/cbc:IssueDate',
invoice.invoice_billing_reference.date) reference.date)
def set_billing_reference(fexml, invoice):
reference = invoice.invoice_billing_reference
if reference is None:
return
if isinstance(reference, DebitNoteDocumentReference):
return fexml._set_debit_note_document_reference(reference)
if isinstance(reference, CreditNoteDocumentReference):
return fexml._set_credit_note_document_reference(reference)
if isinstance(reference, InvoiceDocumentReference):
return fexml._set_invoice_document_reference(reference)
def set_invoice_totals(fexml, invoice): def set_invoice_totals(fexml, invoice):
tax_amount_for = defaultdict(lambda: defaultdict(lambda: 0.0)) tax_amount_for = defaultdict(lambda: defaultdict(lambda: 0.0))
@ -469,10 +486,6 @@ class DIANInvoiceXML(fe.FeXML):
def tag_document_concilied(fexml): def tag_document_concilied(fexml):
return 'Invoiced' return 'Invoiced'
# abstract method
def document_type_code(fexml):
return codelist.TipoDocumento.by_name('Factura de Venta Nacional')['code']
def set_invoice_lines(fexml, invoice): def set_invoice_lines(fexml, invoice):
next_append = False next_append = False
for index, invoice_line in enumerate(invoice.invoice_lines): for index, invoice_line in enumerate(invoice.invoice_lines):
@ -519,10 +532,11 @@ class DIANInvoiceXML(fe.FeXML):
fexml.set_element('./cbc:IssueDate', invoice.invoice_issue.strftime('%Y-%m-%d')) fexml.set_element('./cbc:IssueDate', invoice.invoice_issue.strftime('%Y-%m-%d'))
#DIAN 1.7.-2020: FAD10 #DIAN 1.7.-2020: FAD10
fexml.set_element('./cbc:IssueTime', invoice.invoice_issue.strftime('%H:%M:%S-05:00')) fexml.set_element('./cbc:IssueTime', invoice.invoice_issue.strftime('%H:%M:%S-05:00'))
fexml.set_element('./cbc:%sTypeCode' % (fexml.tag_document()), fexml.document_type_code(), fexml.set_element('./cbc:%sTypeCode' % (fexml.tag_document()),
listAgencyID='195', invoice.invoice_type_code,
listAgencyName='No matching global declaration available for the validation root', listAgencyID='195',
listURI='http://www.dian.gov.co') listAgencyName='No matching global declaration available for the validation root',
listURI='http://www.dian.gov.co')
fexml.set_element('./cbc:LineCountNumeric', len(invoice.invoice_lines)) fexml.set_element('./cbc:LineCountNumeric', len(invoice.invoice_lines))
fexml.set_element('./cac:%sPeriod/cbc:StartDate' % (fexml.tag_document()), fexml.set_element('./cac:%sPeriod/cbc:StartDate' % (fexml.tag_document()),
invoice.invoice_period_start.strftime('%Y-%m-%d')) invoice.invoice_period_start.strftime('%Y-%m-%d'))
@ -545,10 +559,3 @@ class DIANInvoiceXML(fe.FeXML):
def customize(fexml, invoice): def customize(fexml, invoice):
"""adiciona etiquetas a FEXML y retorna FEXML """adiciona etiquetas a FEXML y retorna FEXML
en caso de fallar validacion retorna None""" en caso de fallar validacion retorna None"""

View File

@ -16,7 +16,7 @@ from facho.fe.form_xml import DIANInvoiceXML
@pytest.fixture @pytest.fixture
def simple_invoice_without_lines(): def simple_invoice_without_lines():
inv = form.Invoice() inv = form.NationalSalesInvoice()
inv.set_period(datetime.now(), datetime.now()) inv.set_period(datetime.now(), datetime.now())
inv.set_issue(datetime.now()) inv.set_issue(datetime.now())
inv.set_ident('ABC123') inv.set_ident('ABC123')
@ -48,7 +48,7 @@ def simple_invoice_without_lines():
@pytest.fixture @pytest.fixture
def simple_invoice(): def simple_invoice():
inv = form.Invoice() inv = form.NationalSalesInvoice()
inv.set_period(datetime.now(), datetime.now()) inv.set_period(datetime.now(), datetime.now())
inv.set_issue(datetime.now()) inv.set_issue(datetime.now())
inv.set_ident('ABC123') inv.set_ident('ABC123')

View File

@ -14,7 +14,7 @@ import facho.fe.form as form
from facho import fe from facho import fe
def test_invoice_legalmonetary(): def test_invoice_legalmonetary():
inv = form.Invoice() inv = form.NationalSalesInvoice()
inv.add_invoice_line(form.InvoiceLine( inv.add_invoice_line(form.InvoiceLine(
quantity = 1, quantity = 1,
description = 'producto facho', description = 'producto facho',
@ -40,7 +40,7 @@ def test_invoice_legalmonetary():
def test_FAU10(): def test_FAU10():
inv = form.Invoice() inv = form.NationalSalesInvoice()
inv.add_invoice_line(form.InvoiceLine( inv.add_invoice_line(form.InvoiceLine(
quantity = 1, quantity = 1,
description = 'producto facho', description = 'producto facho',
@ -68,7 +68,7 @@ def test_FAU10():
def test_FAU14(): def test_FAU14():
inv = form.Invoice() inv = form.NationalSalesInvoice()
inv.add_invoice_line(form.InvoiceLine( inv.add_invoice_line(form.InvoiceLine(
quantity = 1, quantity = 1,
description = 'producto facho', description = 'producto facho',