Se adiciona xml de AllowanceCharge para documento

FossilOrigin-Name: 93cd9530bb2f63a2803b8a32a5aceeeda015eff2d26c96e95a13dbb9193cad82
This commit is contained in:
bit4bit 2020-12-02 18:46:18 +00:00
parent e571009945
commit 1143b26988
4 changed files with 94 additions and 39 deletions

View File

@ -396,6 +396,43 @@ class InvoiceDocumentReference(BillingReference):
date: fecha de emision de la nota credito relacionada date: fecha de emision de la nota credito relacionada
""" """
@dataclass
class AllowanceChargeReason:
code: str
reason: str
def __post_init__(self):
if self.code not in codelist.CodigoDescuento:
raise ValueError("code [%s] not found" % (self.code))
@dataclass
class AllowanceCharge:
#DIAN 1.7.-2020: FAQ03
charge_indicator: bool = True
amount: Amount = Amount(0.0)
reason: AllowanceChargeReason = None
def isCharge(self):
return self.charge_indicator == True
def isDiscount(self):
return self.charge_indicator == False
def asCharge(self):
self.charge_indicator = True
def asDiscount(self):
self.charge_indicator = False
def hasReason(self):
return self.reason is not None
class AllowanceChargeAsDiscount(AllowanceCharge):
def __init__(self, amount: Amount = Amount(0.0)):
self.charge_indicator = False
self.amount = amount
@dataclass @dataclass
class InvoiceLine: class InvoiceLine:
# RESOLUCION 0004: pagina 155 # RESOLUCION 0004: pagina 155
@ -409,6 +446,13 @@ class InvoiceLine:
# de subtotal # de subtotal
tax: typing.Optional[TaxTotal] tax: typing.Optional[TaxTotal]
allowance_charge = []
def add_allowance_charge(charge):
if not isinstance(charge, AllowanceCharge):
raise TypeError('charge invalid type expected AllowanceCharge')
self.allowance_charge.add(charge)
@property @property
def total_amount(self): def total_amount(self):
return self.quantity * self.price.amount return self.quantity * self.price.amount
@ -459,42 +503,6 @@ class LegalMonetaryTotal:
- self.prepaid_amount - self.prepaid_amount
@dataclass
class AllowanceChargeReason:
code: str
reason: str
def __post_init__(self):
if self.code not in codelist.CodigoDescuento:
raise ValueError("code [%s] not found" % (self.code))
@dataclass
class AllowanceCharge:
#DIAN 1.7.-2020: FAQ03
charge_indicator: bool = True
amount: Amount = Amount(0.0)
reason: AllowanceChargeReason = None
def isCharge(self):
return self.charge_indicator == True
def isDiscount(self):
return self.charge_indicator == False
def asCharge(self):
self.charge_indicator = True
def asDiscount(self):
self.charge_indicator = False
def hasReason(self):
return self.reason is not None
class AllowanceChargeAsDiscount(AllowanceCharge):
def __init__(self, amount: Amount = Amount(0.0)):
self.charge_indicator = False
self.amount = amount
class NationalSalesInvoiceDocumentType(str): class NationalSalesInvoiceDocumentType(str):
def __str__(self): def __str__(self):
@ -593,7 +601,7 @@ class Invoice:
self.invoice_operation_type = operation self.invoice_operation_type = operation
def add_allownace_charge(self, charge: AllowanceCharge): def add_allowance_charge(self, charge: AllowanceCharge):
self.invoice_allowance_charge.append(charge) self.invoice_allowance_charge.append(charge)
def add_invoice_line(self, line: InvoiceLine): def add_invoice_line(self, line: InvoiceLine):

View File

@ -543,6 +543,22 @@ class DIANInvoiceXML(fe.FeXML):
invoice_line.price.quantity, invoice_line.price.quantity,
unitCode=invoice_line.quantity.code) unitCode=invoice_line.quantity.code)
def set_allowance_charge(fexml, invoice):
for idx, charge in enumerate(invoice.invoice_allowance_charge):
next_append = idx > 0
fexml.append_allowance_charge(fexml, idx + 1, charge, append=next_append)
def append_allowance_charge(fexml, parent, idx, charge, append=False):
line = fexml.fragment('./cac:AllowanceCharge', append=append)
#DIAN 1.7.-2020: FAQ02
line.set_element('./cbc:ID', idx)
#DIAN 1.7.-2020: FAQ03
line.set_element('./cbc:ChargeIndicator', str(charge.charge_indicator).lower())
if charge.reason:
line.set_element('./cbc:AllowanceChargeReasonCode', charge.reason.code)
line.set_element('./cbc:allowanceChargeReason', charge.reason.reason)
fexml.set_element_amount_for(line, './cbc:Amount', charge.amount)
def attach_invoice(fexml, invoice): def attach_invoice(fexml, invoice):
"""adiciona etiquetas a FEXML y retorna FEXML """adiciona etiquetas a FEXML y retorna FEXML
@ -579,6 +595,7 @@ class DIANInvoiceXML(fe.FeXML):
fexml.set_invoice_totals(invoice) fexml.set_invoice_totals(invoice)
fexml.set_invoice_lines(invoice) fexml.set_invoice_lines(invoice)
fexml.set_payment_mean(invoice) fexml.set_payment_mean(invoice)
fexml.set_allowance_charge(invoice)
fexml.set_billing_reference(invoice) fexml.set_billing_reference(invoice)
return fexml return fexml

View File

@ -61,7 +61,7 @@ def test_FAU10():
] ]
) )
)) ))
inv.add_allownace_charge(form.AllowanceCharge(amount=form.Amount(19.0))) inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
inv.calculate() inv.calculate()
assert inv.invoice_legal_monetary_total.line_extension_amount == form.Amount(100.0) assert inv.invoice_legal_monetary_total.line_extension_amount == form.Amount(100.0)
@ -89,7 +89,7 @@ def test_FAU14():
] ]
) )
)) ))
inv.add_allownace_charge(form.AllowanceCharge(amount=form.Amount(19.0))) inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
inv.add_prepaid_payment(form.PrePaidPayment(paid_amount = form.Amount(50.0))) inv.add_prepaid_payment(form.PrePaidPayment(paid_amount = form.Amount(50.0)))
inv.calculate() inv.calculate()

View File

@ -6,9 +6,13 @@
"""Tests for `facho` package.""" """Tests for `facho` package."""
import pytest import pytest
from datetime import datetime
from facho.fe import form
from facho.fe import form_xml from facho.fe import form_xml
from fixtures import *
def test_import_DIANInvoiceXML(): def test_import_DIANInvoiceXML():
try: try:
form_xml.DIANInvoiceXML form_xml.DIANInvoiceXML
@ -27,3 +31,29 @@ def test_import_DIANCreditNoteXML():
form_xml.DIANCreditNoteXML form_xml.DIANCreditNoteXML
except AttributeError: except AttributeError:
pytest.fail("unexpected not found") pytest.fail("unexpected not found")
def test_FAU10(simple_invoice_without_lines):
inv = simple_invoice_without_lines
inv.add_invoice_line(form.InvoiceLine(
quantity = form.Quantity(1, '94'),
description = 'producto facho',
item = form.StandardItem(9999),
price = form.Price(
amount = form.Amount(100.0),
type_code = '01',
type = 'x'
),
tax = form.TaxTotal(
subtotals = [
form.TaxSubTotal(
percent = 19.0,
)
]
)
))
inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
xml = form_xml.DIANInvoiceXML(inv)
assert xml.get_element_text('./cac:AllowanceCharge/cbc:ID') == '1'
assert xml.get_element_text('./cac:AllowanceCharge/cbc:ChargeIndicator') == 'true'
assert xml.get_element_text('./cac:AllowanceCharge/cbc:Amount') == '19.0'