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.date = date
class CreditNoteDocumentReference(BillingReference):
pass
class DebitNoteDocumentReference(BillingReference):
pass
class InvoiceDocumentReference(BillingReference):
pass
@dataclass
class InvoiceLine:
@ -338,9 +346,19 @@ class AllowanceCharge:
self.charge_indicator = False
class NationalSalesInvoiceDocumentType(str):
def __str__(self):
return '01'
class CreditNoteDocumentType(str):
def __str__(self):
return '91'
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_end = None
self.invoice_issue = None
@ -355,6 +373,8 @@ class Invoice:
self.invoice_allowance_charge = []
self.invoice_prepaid_payment = []
self.invoice_billing_reference = None
self.invoice_type_code = str(type_code)
def set_period(self, startdate, enddate):
self.invoice_period_start = startdate
@ -441,3 +461,15 @@ class Invoice:
for invline in self.invoice_lines:
invline.calculate()
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

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

View File

@ -30,11 +30,11 @@ class DIANInvoiceXML(fe.FeXML):
#DIAN 1.7.-2020: FAJ06
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name',
invoice.invoice_supplier.name)
#DIAN 1.7.-2020: CAJ07, CAJ08
#DIAN 1.7.-2020: FAJ07
fexml.placeholder_for('./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address')
#DIAN 1.7.-2020: FAJ08
#DIAN 1.7.-2020: CAJ09
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:ID',
@ -47,7 +47,7 @@ class DIANInvoiceXML(fe.FeXML):
#DIAN 1.7.-2020: CAJ11
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CountrySubentity',
invoice.invoice_supplier.address.countrysubentity.name)
#DIAN 1.7.-2020: FAJ12
#DIAN 1.7.-2020: CAJ12
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CountrySubentityCode',
@ -384,19 +384,36 @@ class DIANInvoiceXML(fe.FeXML):
invoice.invoice_legal_monetary_total.payable_amount)
def set_billing_reference(fexml, invoice):
if invoice.invoice_billing_reference is None:
return
def _set_invoice_document_reference(fexml, reference):
fexml._do_set_billing_reference(reference, 'cac:InvoiceDocumentReference')
fexml.placeholder_for('./cac:BillingReference')
fexml.placeholder_for('./cac:BillingReference/cac:InvoiceDocumentReference')
fexml.set_element('./cac:BillingReference/cac:InvoiceDocumentReference/cbc:ID',
invoice.invoice_billing_reference.ident)
def _set_credit_note_document_reference(fexml, reference):
fexml._do_set_billing_reference(reference, 'cac:CreditNoteDocumentReference')
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',
invoice.invoice_billing_reference.uuid,
reference.uuid,
schemeName='CUFE-SHA384')
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):
tax_amount_for = defaultdict(lambda: defaultdict(lambda: 0.0))
@ -469,10 +486,6 @@ class DIANInvoiceXML(fe.FeXML):
def tag_document_concilied(fexml):
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):
next_append = False
for index, invoice_line in enumerate(invoice.invoice_lines):
@ -519,14 +532,15 @@ class DIANInvoiceXML(fe.FeXML):
fexml.set_element('./cbc:IssueDate', invoice.invoice_issue.strftime('%Y-%m-%d'))
#DIAN 1.7.-2020: FAD10
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(),
listAgencyID='195',
listAgencyName='No matching global declaration available for the validation root',
listURI='http://www.dian.gov.co')
fexml.set_element('./cbc:%sTypeCode' % (fexml.tag_document()),
invoice.invoice_type_code,
listAgencyID='195',
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('./cac:%sPeriod/cbc:StartDate' % (fexml.tag_document()),
invoice.invoice_period_start.strftime('%Y-%m-%d'))
fexml.set_element('./cac:%sPeriod/cbc:EndDate' % (fexml.tag_document()),
invoice.invoice_period_end.strftime('%Y-%m-%d'))
@ -545,10 +559,3 @@ class DIANInvoiceXML(fe.FeXML):
def customize(fexml, invoice):
"""adiciona etiquetas a FEXML y retorna FEXML
en caso de fallar validacion retorna None"""

View File

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

View File

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