171 lines
6.5 KiB
Python
171 lines
6.5 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 trytond.i18n import gettext
|
|
from trytond.model import fields
|
|
from trytond.modules.product import uom_conversion_digits
|
|
from trytond.modules.product.exceptions import UOMValidationError
|
|
from trytond.pool import PoolMeta
|
|
from trytond.pyson import Bool, Eval
|
|
|
|
|
|
class PurchaseSecondaryMixin:
|
|
__slots__ = ()
|
|
purchase_secondary_uom = fields.Many2One(
|
|
'product.uom', "Purchase Secondary UoM",
|
|
domain=[
|
|
('category', '!=', Eval('default_uom_category', -1)),
|
|
],
|
|
help="The secondary Unit of Measure for purchases.")
|
|
purchase_secondary_uom_factor = fields.Float(
|
|
"Purchase Secondary UoM Factor", digits=uom_conversion_digits,
|
|
states={
|
|
'required': Bool(Eval('purchase_secondary_uom')),
|
|
'invisible': ~Eval('purchase_secondary_uom'),
|
|
},
|
|
help="The coefficient for the formula:\n"
|
|
"1 (purchase unit) = coefficient (secondary unit)")
|
|
purchase_secondary_uom_rate = fields.Float(
|
|
"Purchase Secondary UoM Rate", digits=uom_conversion_digits,
|
|
states={
|
|
'required': Bool(Eval('purchase_secondary_uom')),
|
|
'invisible': ~Eval('purchase_secondary_uom'),
|
|
},
|
|
help="The coefficient for the formula:\n"
|
|
"coefficient (purchase unit) = 1 (secondary unit)")
|
|
purchase_secondary_uom_category = fields.Function(
|
|
fields.Many2One(
|
|
'product.uom.category', "Purchase Secondary UoM Category"),
|
|
'on_change_with_purchase_secondary_uom_category',
|
|
searcher='search_purchase_secondary_uom_category')
|
|
|
|
@fields.depends('purchase_secondary_uom_factor')
|
|
def on_change_purchase_secondary_uom_factor(self):
|
|
if not self.purchase_secondary_uom_factor:
|
|
self.purchase_secondary_uom_rate = None
|
|
else:
|
|
self.purchase_secondary_uom_rate = round(
|
|
1. / self.purchase_secondary_uom_factor,
|
|
uom_conversion_digits[1])
|
|
|
|
@fields.depends('purchase_secondary_uom_rate')
|
|
def on_change_purchase_secondary_uom_rate(self):
|
|
if not self.purchase_secondary_uom_rate:
|
|
self.purchase_secondary_uom_factor = None
|
|
else:
|
|
self.purchase_secondary_uom_factor = round(
|
|
1. / self.purchase_secondary_uom_rate,
|
|
uom_conversion_digits[1])
|
|
|
|
@fields.depends('purchase_secondary_uom')
|
|
def on_change_with_purchase_secondary_uom_category(self, name=None):
|
|
if self.purchase_secondary_uom:
|
|
return self.purchase_secondary_uom.category
|
|
|
|
@classmethod
|
|
def search_purchase_secondary_uom_category(cls, name, clause):
|
|
return [('purchase_secondary_uom.category' + clause[0][len(name):],
|
|
*clause[1:])]
|
|
|
|
@property
|
|
def purchase_secondary_uom_normal_rate(self):
|
|
uom = self.purchase_secondary_uom
|
|
rate = self.purchase_secondary_uom_rate
|
|
if self.purchase_uom and rate and uom:
|
|
if self.purchase_uom.accurate_field == 'factor':
|
|
rate *= self.purchase_uom.factor
|
|
else:
|
|
rate /= self.purchase_uom.rate
|
|
if uom.accurate_field == 'factor':
|
|
rate /= uom.factor
|
|
else:
|
|
rate *= uom.rate
|
|
return rate
|
|
|
|
@property
|
|
def purchase_secondary_uom_normal_factor(self):
|
|
uom = self.purchase_secondary_uom
|
|
factor = self.purchase_secondary_uom_factor
|
|
if self.purchase_uom and factor and uom:
|
|
if uom.accurate_field == 'factor':
|
|
factor *= uom.factor
|
|
else:
|
|
factor /= uom.rate
|
|
if self.purchase_uom.accurate_field == 'factor':
|
|
factor /= self.purchase_uom.factor
|
|
else:
|
|
factor *= self.purchase_uom.rate
|
|
return factor
|
|
|
|
@classmethod
|
|
def validate_fields(cls, records, field_names):
|
|
super().validate_fields(records, field_names)
|
|
cls.check_purchase_secondary_uom_factor_and_rate(records, field_names)
|
|
|
|
@classmethod
|
|
def check_purchase_secondary_uom_factor_and_rate(
|
|
cls, records, field_names):
|
|
if field_names and not (field_names & {
|
|
'purchase_secondary_uom_factor',
|
|
'purchase_secondary_uom_rate'}):
|
|
return
|
|
for record in records:
|
|
factor = record.purchase_secondary_uom_factor
|
|
rate = record.purchase_secondary_uom_rate
|
|
if factor and rate:
|
|
new_rate = round(1. / factor, uom_conversion_digits[1])
|
|
new_factor = round(1. / rate, uom_conversion_digits[1])
|
|
if rate != new_rate and factor != new_factor:
|
|
raise UOMValidationError(
|
|
gettext('purchase_secondary_unit'
|
|
'.msg_secondary_uom_incompatible_factor_rate',
|
|
record=record.rec_ame))
|
|
|
|
|
|
class Template(PurchaseSecondaryMixin, metaclass=PoolMeta):
|
|
__name__ = 'product.template'
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super().__setup__()
|
|
cls.purchase_secondary_uom.states = {
|
|
'invisible': ~Eval('purchasable', False),
|
|
}
|
|
|
|
|
|
class Product(metaclass=PoolMeta):
|
|
__name__ = 'product.product'
|
|
|
|
@property
|
|
def purchase_secondary_uom_normal_rate(self):
|
|
return self.template.purchase_secondary_uom_normal_rate
|
|
|
|
@property
|
|
def purchase_secondary_uom_normal_factor(self):
|
|
return self.template.purchase_secondary_uom_normal_factor
|
|
|
|
|
|
class ProductSupplier(PurchaseSecondaryMixin, metaclass=PoolMeta):
|
|
__name__ = 'purchase.product_supplier'
|
|
|
|
default_uom_category = fields.Function(
|
|
fields.Many2One(
|
|
'product.uom.category', "Default UoM Category",
|
|
help="The category of the default Unit of Measure."),
|
|
'on_change_with_default_uom_category')
|
|
|
|
@fields.depends('template', '_parent_template.purchase_uom',
|
|
'product', '_parent_product.purchase_uom')
|
|
def on_change_with_default_uom_category(self, name=None):
|
|
if self.product and self.product.purchase_uom:
|
|
return self.product.purchase_uom.category
|
|
elif self.template and self.template.purchase_uom:
|
|
return self.template.purchase_uom.category
|
|
|
|
@property
|
|
def purchase_uom(self):
|
|
if self.product and self.product.purchase_uom:
|
|
return self.product.purchase_uom
|
|
elif self.template and self.template.purchase_uom:
|
|
return self.template.purchase_uom
|