diff --git a/facho/fe/form/__init__.py b/facho/fe/form/__init__.py index 395c748..69add30 100644 --- a/facho/fe/form/__init__.py +++ b/facho/fe/form/__init__.py @@ -71,6 +71,12 @@ class Amount: rounding=decimal.ROUND_HALF_EVEN )) self.currency = currency + def fromNumber(self, val): + return Amount(val, currency=self.currency) + + def round(self, prec): + #return Amount(self.amount.quantize(Decimal('1.' + '0' * prec), rounding=decimal.ROUND_HALF_EVEN)) + return Amount(round(self.amount, prec)) def __round__(self, prec): return round(self.amount, prec) @@ -88,17 +94,27 @@ class Amount: raise AmountCurrencyError() return round(self.amount, DECIMAL_PRECISION) == round(other.amount, DECIMAL_PRECISION) - def __add__(self, other): + def _cast(self, val): + if type(val) in [int, float]: + return self.fromNumber(val) + if isinstance(val, Amount): + return val + raise TypeError("cant cast to amount") + + def __add__(self, rother): + other = self._cast(rother) if not self.is_same_currency(other): raise AmountCurrencyError() return Amount(self.amount + other.amount, self.currency) - def __sub__(self, other): + def __sub__(self, rother): + other = self._cast(rother) if not self.is_same_currency(other): raise AmountCurrencyError() return Amount(self.amount - other.amount, self.currency) - def __mul__(self, other): + def __mul__(self, rother): + other = self._cast(rother) if not self.is_same_currency(other): raise AmountCurrencyError() return Amount(self.amount * other.amount, self.currency) @@ -125,18 +141,16 @@ class Quantity: self.code = code def __mul__(self, other): - if isinstance(other, Amount): - return Amount(self.value) * other return self.value * other def __lt__(self, other): - if isinstance(other, Amount): - return Amount(self.value) < other return self.value < other def __str__(self): return str(self.value) + def __repr__(self): + return str(self) @dataclass class Item: @@ -323,11 +337,15 @@ class Price: amount: Amount type_code: str type: str + quantity: int = 1 def __post_init__(self): if self.type_code not in codelist.CodigoPrecioReferencia: raise ValueError("type_code [%s] not found" % (self.type_code)) + if not isinstance(self.quantity, int): + raise ValueError("quantity must be int") + self.amount *= self.quantity @dataclass class PaymentMean: diff --git a/facho/fe/form_xml/invoice.py b/facho/fe/form_xml/invoice.py index 40bfe2d..279fcfb 100644 --- a/facho/fe/form_xml/invoice.py +++ b/facho/fe/form_xml/invoice.py @@ -540,7 +540,7 @@ class DIANInvoiceXML(fe.FeXML): line.set_element('./cac:Price/cbc:PriceAmount', invoice_line.price.amount, currencyID=invoice_line.price.amount.currency.code) #DIAN 1.7.-2020: FBB04 line.set_element('./cac:Price/cbc:BaseQuantity', - invoice_line.quantity, + invoice_line.price.quantity, unitCode=invoice_line.quantity.code) diff --git a/tests/test_amount.py b/tests/test_amount.py index 76a0d8c..fdc99fe 100644 --- a/tests/test_amount.py +++ b/tests/test_amount.py @@ -20,3 +20,14 @@ def test_amount_equals(): assert price1 == price2 assert price1 == form.Amount(100) + form.Amount(10) assert price1 == form.Amount(10) * form.Amount(10) + form.Amount(10) + assert form.Amount(110) == (form.Amount(1.10) * form.Amount(100)) + +def test_round(): + # Entre 0 y 5 Mantener el dígito menos significativo + assert form.Amount(1.133).round(2) == form.Amount(1.13) + # Entre 6 y 9 Incrementar el dígito menos significativo + assert form.Amount(1.166).round(2) == form.Amount(1.17) + # 5, y el segundo dígito siguiente al dígito menos significativo es cero o par Mantener el dígito menos significativo + assert str(form.Amount(1.1560).round(2)) == str(form.Amount(1.15)) + # 5, y el segundo dígito siguiente al dígito menos significativo es impar Incrementar el dígito menos significativo + assert form.Amount(1.1569).round(2) == form.Amount(1.157) diff --git a/tests/test_fe_form.py b/tests/test_fe_form.py index 2c01b96..02dc430 100644 --- a/tests/test_fe_form.py +++ b/tests/test_fe_form.py @@ -170,6 +170,7 @@ def test_invoice_cufe(simple_invoice_without_lines): 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'