Se adiciona xml de AllowanceCharge para documento
FossilOrigin-Name: 93cd9530bb2f63a2803b8a32a5aceeeda015eff2d26c96e95a13dbb9193cad82
This commit is contained in:
		| @@ -396,6 +396,43 @@ class InvoiceDocumentReference(BillingReference): | ||||
|     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 | ||||
| class InvoiceLine: | ||||
|     # RESOLUCION 0004: pagina 155 | ||||
| @@ -409,6 +446,13 @@ class InvoiceLine: | ||||
|     # de subtotal | ||||
|     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 | ||||
|     def total_amount(self): | ||||
|         return self.quantity * self.price.amount | ||||
| @@ -459,42 +503,6 @@ class LegalMonetaryTotal: | ||||
|             - 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): | ||||
|     def __str__(self): | ||||
| @@ -593,7 +601,7 @@ class Invoice: | ||||
|  | ||||
|         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) | ||||
|  | ||||
|     def add_invoice_line(self, line: InvoiceLine): | ||||
|   | ||||
| @@ -543,7 +543,23 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|                              invoice_line.price.quantity, | ||||
|                              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): | ||||
|         """adiciona etiquetas a FEXML y retorna FEXML | ||||
|         en caso de fallar validacion retorna None""" | ||||
| @@ -579,6 +595,7 @@ class DIANInvoiceXML(fe.FeXML): | ||||
|         fexml.set_invoice_totals(invoice) | ||||
|         fexml.set_invoice_lines(invoice) | ||||
|         fexml.set_payment_mean(invoice) | ||||
|         fexml.set_allowance_charge(invoice) | ||||
|         fexml.set_billing_reference(invoice) | ||||
|  | ||||
|         return fexml | ||||
|   | ||||
| @@ -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() | ||||
|     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.calculate() | ||||
|  | ||||
|   | ||||
| @@ -6,9 +6,13 @@ | ||||
| """Tests for `facho` package.""" | ||||
|  | ||||
| import pytest | ||||
| from datetime import datetime | ||||
|  | ||||
| from facho.fe import form | ||||
| from facho.fe import form_xml | ||||
|  | ||||
| from fixtures import * | ||||
|  | ||||
| def test_import_DIANInvoiceXML(): | ||||
|     try: | ||||
|         form_xml.DIANInvoiceXML | ||||
| @@ -27,3 +31,29 @@ def test_import_DIANCreditNoteXML(): | ||||
|         form_xml.DIANCreditNoteXML | ||||
|     except AttributeError: | ||||
|         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' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user