se crea legal monetary total

FossilOrigin-Name: 8ae3dfadfe9b90b8cc5ad59d2a73f4c8a987c5aac498573e56754a2d32e9e2ae
This commit is contained in:
bit4bit 2021-06-27 02:16:16 +00:00
parent 2e8aa35b29
commit 507ddbe558
5 changed files with 94 additions and 12 deletions

View File

@ -99,7 +99,7 @@ class Amount:
return self.fromNumber(val) return self.fromNumber(val)
if isinstance(val, Amount): if isinstance(val, Amount):
return val return val
raise TypeError("cant cast to amount") raise TypeError("cant cast %s to amount" % (type(val)))
def __add__(self, rother): def __add__(self, rother):
other = self._cast(rother) other = self._cast(rother)

View File

@ -1,6 +1,8 @@
import facho.model as model import facho.model as model
import facho.model.fields as fields import facho.model.fields as fields
import facho.fe.form as form
from datetime import date, datetime from datetime import date, datetime
from copy import copy
class Name(model.Model): class Name(model.Model):
__name__ = 'Name' __name__ = 'Name'
@ -48,24 +50,44 @@ class AccountingSupplierParty(model.Model):
party = fields.Many2One(Party) party = fields.Many2One(Party)
class InvoicedQuantity(model.Model): class Quantity(model.Model):
__name__ = 'InvoiceQuantity' __name__ = 'Quantity'
code = fields.Attribute('unitCode', default='NAR') code = fields.Attribute('unitCode', default='NAR')
value = fields.Virtual(default=0, update_internal=True)
def __default_set__(self, value):
self.value = value
return value
def __mul__(self, other):
return form.Amount(self.value) * other.value
class Amount(model.Model): class Amount(model.Model):
__name__ = 'Amount' __name__ = 'Amount'
currency = fields.Attribute('currencyID', default='COP') currency = fields.Attribute('currencyID', default='COP')
value = fields.Virtual(default=form.Amount(0), update_internal=True)
def __default_set__(self, value):
self.value = value
return value
class Price(model.Model): class Price(model.Model):
__name__ = 'Price' __name__ = 'Price'
amount = fields.Many2One(Amount, name='PriceAmount') amount = fields.Many2One(Amount, name='PriceAmount')
value = fields.Virtual(default=form.Amount(0))
def __default_set__(self, value): def __default_set__(self, value):
self.amount = value self.amount = value
self.value = value
return value
def __mul__(self, other):
return self.value * other.value
class Percent(model.Model): class Percent(model.Model):
__name__ = 'Percent' __name__ = 'Percent'
@ -103,12 +125,51 @@ class TaxTotal(model.Model):
tax_amount = fields.Many2One(Amount, name='TaxAmount') tax_amount = fields.Many2One(Amount, name='TaxAmount')
subtotals = fields.One2Many(TaxSubTotal) subtotals = fields.One2Many(TaxSubTotal)
class AllowanceCharge(model.Model):
__name__ = 'AllowanceCharge'
amount = fields.Many2One(Amount)
is_discount = fields.Virtual(default=False)
def isCharge(self):
return self.is_discount == False
def isDiscount(self):
return self.is_discount == True
class InvoiceLine(model.Model): class InvoiceLine(model.Model):
__name__ = 'InvoiceLine' __name__ = 'InvoiceLine'
quantity = fields.Many2One(InvoicedQuantity) quantity = fields.Many2One(Quantity, name='InvoicedQuantity')
taxtotal = fields.Many2One(TaxTotal) taxtotal = fields.Many2One(TaxTotal)
price = fields.Many2One(Price) price = fields.Many2One(Price)
amount = fields.Many2One(Amount, name='LineExtensionAmount')
allowance_charge = fields.One2Many(AllowanceCharge)
@fields.on_change(['price', 'quantity'])
def update_amount(self, name, value):
charge = form.AmountCollection(self.allowance_charge)\
.filter(lambda charge: charge.isCharge())\
.map(lambda charge: charge.amount)\
.sum()
discount = form.AmountCollection(self.allowance_charge)\
.filter(lambda charge: charge.isDiscount())\
.map(lambda charge: charge.amount)\
.sum()
total = self.quantity * self.price
self.amount = total + charge - discount
class LegalMonetaryTotal(model.Model):
__name__ = 'LegalMonetaryTotal'
line_extension_amount = fields.Many2One(Amount, name='LineExtensionAmount', default=form.Amount(0))
tax_exclusive_amount = fields.Many2One(Amount, name='TaxExclusiveAmount')
tax_inclusive_amount = fields.Many2One(Amount, name='TaxInclusiveAmount')
charge_total_amount = fields.Many2One(Amount, name='ChargeTotalAmount')
payable_amount = fields.Many2One(Amount, name='PayableAmount')
class Invoice(model.Model): class Invoice(model.Model):
__name__ = 'Invoice' __name__ = 'Invoice'
@ -123,6 +184,12 @@ class Invoice(model.Model):
supplier = fields.Many2One(AccountingSupplierParty) supplier = fields.Many2One(AccountingSupplierParty)
customer = fields.Many2One(AccountingCustomerParty) customer = fields.Many2One(AccountingCustomerParty)
lines = fields.One2Many(InvoiceLine) lines = fields.One2Many(InvoiceLine)
legal_monetary_total = fields.Many2One(LegalMonetaryTotal)
@fields.on_change(['lines'])
def update_legal_monetary_total(self, name, value):
for line in self.lines:
self.legal_monetary_total.line_extension_amount.value += line.amount.value
def set_issue(self, name, value): def set_issue(self, name, value):
if not isinstance(value, datetime): if not isinstance(value, datetime):

View File

@ -19,7 +19,7 @@ class ModelBase(object, metaclass=ModelMeta):
obj = super().__new__(cls, *args, **kwargs) obj = super().__new__(cls, *args, **kwargs)
obj._xml_attributes = {} obj._xml_attributes = {}
obj._fields = {} obj._fields = {}
obj._text = "" obj._value = None
obj._namespace_prefix = None obj._namespace_prefix = None
obj._on_change_fields = defaultdict(list) obj._on_change_fields = defaultdict(list)
obj._order_fields = [] obj._order_fields = []
@ -72,7 +72,7 @@ class ModelBase(object, metaclass=ModelMeta):
def _set_content(self, value): def _set_content(self, value):
default = self.__default_set__(value) default = self.__default_set__(value)
if default is not None: if default is not None:
self._text = str(default) self._value = default
def _hook_before_xml(self): def _hook_before_xml(self):
self.__before_xml__() self.__before_xml__()
@ -116,7 +116,9 @@ class ModelBase(object, metaclass=ModelMeta):
content += value.to_xml() content += value.to_xml()
elif isinstance(value, str): elif isinstance(value, str):
content += value content += value
content += self._text
if self._value is not None:
content += str(self._value)
if content == "": if content == "":
return "<%s%s%s/>" % (ns, tag, attributes) return "<%s%s%s/>" % (ns, tag, attributes)

View File

@ -17,9 +17,10 @@ class _RelationProxy():
def __setattr__(self, attr, value): def __setattr__(self, attr, value):
# TODO(bit4bit) hacemos proxy al sistema de notificacion de cambios # TODO(bit4bit) hacemos proxy al sistema de notificacion de cambios
# algo burdo, se usa __dict__ para saltarnos el __getattr__ y generar un fallo por recursion # algo burdo, se usa __dict__ para saltarnos el __getattr__ y generar un fallo por recursion
response = setattr(self._obj, attr, value)
for fun in self.__dict__['_inst']._on_change_fields[self.__dict__['_attribute']]: for fun in self.__dict__['_inst']._on_change_fields[self.__dict__['_attribute']]:
fun(self.__dict__['_inst'], self.__dict__['_attribute'], value) fun(self.__dict__['_inst'], self.__dict__['_attribute'], value)
return setattr(self._obj, attr, value) return response
class _Relation(): class _Relation():
def __init__(self, creator, inst, attribute): def __init__(self, creator, inst, attribute):

View File

@ -20,9 +20,21 @@ def test_simple_invoice():
invoice.customer.party.id = '800199436' invoice.customer.party.id = '800199436'
line = invoice.lines.create() line = invoice.lines.create()
line.quantity = form.Quantity(1, '94') line.quantity = 1
line.price = form.Amount(5_000) line.price = form.Amount(5_000)
subtotal = line.taxtotal.subtotals.create() subtotal = line.taxtotal.subtotals.create()
subtotal.percent = 19.0 subtotal.percent = 19.0
assert '<Invoice><ID>323200000129</ID><IssueDate>2019-01-16T10:53:10-05:00</IssueDate><IssueTime>10:5310-05:00</IssueTime><AccountingSupplierParty><Party><ID>700085371</ID></Party></AccountingSupplierParty><AccountingCustomerParty><Party><ID>800199436</ID></Party></AccountingCustomerParty><InvoiceLine><InvoicedQuantity unitCode="NAR">1</InvoicedQuantity><TaxTotal><TaxSubTotal><TaxCategory><Percent>19.0</Percent><TaxScheme><ID>01</ID><Name>IVA</Name></TaxScheme></TaxCategory></TaxSubTotal></TaxTotal><Price><PriceAmount currencyID="COP">5000.0</PriceAmount>5000.0</Price><LineExtensionAmount currencyID="COP">5000.0</LineExtensionAmount></InvoiceLine><LegalMonetaryTotal><LineExtensionAmount currencyID="COP">35000.0</LineExtensionAmount></LegalMonetaryTotal></Invoice>' == invoice.to_xml()
assert '<Invoice><ID>323200000129</ID><IssueDate>2019-01-16T10:53:10-05:00</IssueDate><IssueTime>10:5310-05:00</IssueTime><AccountingSupplierParty><Party><ID>700085371</ID></Party></AccountingSupplierParty><AccountingCustomerParty><Party><ID>800199436</ID></Party></AccountingCustomerParty><InvoiceLine><InvoiceQuantity unitCode="NAR">1.0</InvoiceQuantity><TaxTotal><TaxSubTotal><TaxCategory><Percent>19.0</Percent><TaxScheme><ID>01</ID><Name>IVA</Name></TaxScheme></TaxCategory></TaxSubTotal></TaxTotal><Price><PriceAmount currencyID="COP">5000.0</PriceAmount></Price></InvoiceLine></Invoice>' == invoice.to_xml() def _test_simple_invoice_cufe():
invoice = model.Invoice()
invoice.id = '323200000129'
invoice.issue = datetime.strptime('2019-01-16 10:53:10-05:00', '%Y-%m-%d %H:%M:%S%z')
invoice.supplier.party.id = '700085371'
invoice.customer.party.id = '800199436'
line = invoice.lines.create()
line.quantity = form.Quantity(1, '94')
line.price = form.Amount(1_500_000)
subtotal = line.taxtotal.subtotals.create()
subtotal.percent = 19.0