152 lines
5.8 KiB
Python
152 lines
5.8 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from decimal import Decimal
|
|
|
|
from trytond.model import fields
|
|
from trytond.modules.currency.fields import Monetary
|
|
from trytond.modules.product import price_digits, round_price
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.pyson import Eval
|
|
|
|
|
|
class Line(metaclass=PoolMeta):
|
|
__name__ = 'sale.line'
|
|
|
|
base_price = Monetary(
|
|
"Base Price", currency='currency', digits=price_digits,
|
|
states={
|
|
'invisible': Eval('type') != 'line',
|
|
'readonly': Eval('sale_state') != 'draft',
|
|
})
|
|
|
|
discount_rate = fields.Function(fields.Numeric(
|
|
"Discount Rate", digits=(None, 4),
|
|
states={
|
|
'invisible': Eval('type') != 'line',
|
|
'readonly': Eval('sale_state') != 'draft',
|
|
}),
|
|
'on_change_with_discount_rate', setter='set_discount_rate')
|
|
discount_amount = fields.Function(Monetary(
|
|
"Discount Amount", currency='currency', digits=price_digits,
|
|
states={
|
|
'invisible': Eval('type') != 'line',
|
|
'readonly': Eval('sale_state') != 'draft',
|
|
}),
|
|
'on_change_with_discount_amount', setter='set_discount_amount')
|
|
|
|
discount = fields.Function(fields.Char(
|
|
"Discount",
|
|
states={
|
|
'invisible': ~Eval('discount'),
|
|
}),
|
|
'on_change_with_discount')
|
|
|
|
@fields.depends(
|
|
methods=[
|
|
'compute_base_price', 'on_change_with_discount_rate',
|
|
'on_change_with_discount_amount', 'on_change_with_discount'])
|
|
def on_change_product(self):
|
|
super().on_change_product()
|
|
if self.product:
|
|
self.base_price = self.compute_base_price()
|
|
self.discount_rate = self.on_change_with_discount_rate()
|
|
self.discount_amount = self.on_change_with_discount_amount()
|
|
self.discount = self.on_change_with_discount()
|
|
|
|
@fields.depends('product', 'unit')
|
|
def compute_base_price(self):
|
|
pool = Pool()
|
|
Uom = pool.get('product.uom')
|
|
if (self.product
|
|
and (price := self.product.list_price_used) is not None):
|
|
if self.unit:
|
|
price = Uom.compute_price(
|
|
self.product.default_uom, price, self.unit)
|
|
return round_price(price)
|
|
|
|
@fields.depends(
|
|
methods=[
|
|
'compute_base_price', 'on_change_with_discount_rate',
|
|
'on_change_with_discount_amount', 'on_change_with_discount'])
|
|
def on_change_quantity(self):
|
|
super().on_change_quantity()
|
|
self.base_price = self.compute_base_price()
|
|
self.discount_rate = self.on_change_with_discount_rate()
|
|
self.discount_amount = self.on_change_with_discount_amount()
|
|
self.discount = self.on_change_with_discount()
|
|
|
|
@fields.depends('unit_price', 'base_price')
|
|
def on_change_with_discount_rate(self, name=None):
|
|
if self.unit_price is None or not self.base_price:
|
|
return
|
|
rate = 1 - self.unit_price / self.base_price
|
|
return rate.quantize(
|
|
Decimal(1) / 10 ** self.__class__.discount_rate.digits[1])
|
|
|
|
@fields.depends(
|
|
'base_price', 'discount_rate',
|
|
methods=['on_change_with_discount_amount', 'on_change_with_discount',
|
|
'on_change_with_amount'])
|
|
def on_change_discount_rate(self):
|
|
if self.base_price is not None and self.discount_rate is not None:
|
|
self.unit_price = round_price(
|
|
self.base_price * (1 - self.discount_rate))
|
|
self.discount_amount = self.on_change_with_discount_amount()
|
|
self.discount = self.on_change_with_discount()
|
|
self.amount = self.on_change_with_amount()
|
|
|
|
@classmethod
|
|
def set_discount_rate(cls, lines, name, value):
|
|
pass
|
|
|
|
@fields.depends('unit_price', 'base_price')
|
|
def on_change_with_discount_amount(self, name=None):
|
|
if self.unit_price is None or self.base_price is None:
|
|
return
|
|
return round_price(self.base_price - self.unit_price)
|
|
|
|
@fields.depends(
|
|
'base_price', 'discount_amount',
|
|
methods=['on_change_with_discount_rate', 'on_change_with_discount',
|
|
'on_change_with_amount'])
|
|
def on_change_discount_amount(self):
|
|
if self.base_price is not None and self.discount_amount is not None:
|
|
self.unit_price = round_price(
|
|
self.base_price - self.discount_amount)
|
|
self.discount_rate = self.on_change_with_discount_rate()
|
|
self.discount = self.on_change_with_discount()
|
|
self.amount = self.on_change_with_amount()
|
|
|
|
@classmethod
|
|
def set_discount_amount(cls, lines, name, value):
|
|
pass
|
|
|
|
@fields.depends(
|
|
'sale', '_parent_sale.currency',
|
|
methods=[
|
|
'on_change_with_discount_rate', 'on_change_with_discount_amount'])
|
|
def on_change_with_discount(self, name=None):
|
|
pool = Pool()
|
|
Lang = pool.get('ir.lang')
|
|
lang = Lang.get()
|
|
rate = self.on_change_with_discount_rate()
|
|
if not rate or rate % Decimal('0.01'):
|
|
amount = self.on_change_with_discount_amount()
|
|
if amount:
|
|
if self.sale and self.sale.currency:
|
|
return lang.currency(
|
|
amount, self.sale.currency, digits=price_digits[1])
|
|
else:
|
|
return lang.format_number(
|
|
amount, digits=price_digits[1], monetary=True)
|
|
else:
|
|
return lang.format('%i', rate * 100) + '%'
|
|
|
|
@classmethod
|
|
def view_attributes(cls):
|
|
return super().view_attributes() + [
|
|
('/form//label[@id="discount"]', 'states', {
|
|
'invisible': Eval('type') != 'line',
|
|
}, ['type']),
|
|
]
|