se crea legal monetary total
FossilOrigin-Name: 8ae3dfadfe9b90b8cc5ad59d2a73f4c8a987c5aac498573e56754a2d32e9e2ae
This commit is contained in:
parent
2e8aa35b29
commit
507ddbe558
@ -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)
|
||||||
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user