first commit
This commit is contained in:
192
modules/product_measurements/product.py
Normal file
192
modules/product_measurements/product.py
Normal file
@@ -0,0 +1,192 @@
|
||||
# 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.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Bool, Eval, Id
|
||||
|
||||
NON_MEASURABLE = ['service']
|
||||
|
||||
|
||||
class Template(metaclass=PoolMeta):
|
||||
__name__ = 'product.template'
|
||||
|
||||
length = fields.Float(
|
||||
"Length", digits='length_uom',
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
},
|
||||
help="Length for 1 default unit of measure.")
|
||||
length_uom = fields.Many2One(
|
||||
'product.uom', "Length UoM",
|
||||
domain=[('category', '=', Id('product', 'uom_cat_length'))],
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
'required': Bool(Eval('length')),
|
||||
},
|
||||
help="The Unit of Measure for the length.")
|
||||
height = fields.Float(
|
||||
"Height", digits='height_uom',
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
},
|
||||
help="Height for 1 default unit of measure.")
|
||||
height_uom = fields.Many2One(
|
||||
'product.uom', 'Height UoM',
|
||||
domain=[('category', '=', Id('product', 'uom_cat_length'))],
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
'required': Bool(Eval('height')),
|
||||
},
|
||||
help="The Unit of Measure for the height.")
|
||||
width = fields.Float(
|
||||
"Width", digits='width_uom',
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
},
|
||||
help="Width for 1 default unit of measure.")
|
||||
width_uom = fields.Many2One(
|
||||
'product.uom', 'Width UoM',
|
||||
domain=[('category', '=', Id('product', 'uom_cat_length'))],
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
'required': Bool(Eval('width')),
|
||||
},
|
||||
help="The Unit of Measure for the width.")
|
||||
volume = fields.Float(
|
||||
"Volume", digits='volume_uom',
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
'readonly': (Bool(Eval('length'))
|
||||
& Bool(Eval('height')) & Bool(Eval('width'))),
|
||||
},
|
||||
help="Volume for 1 default unit of measure.")
|
||||
volume_uom = fields.Many2One(
|
||||
'product.uom', "Volume UoM",
|
||||
domain=[('category', '=', Id('product', 'uom_cat_volume'))],
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
'required': Bool(Eval('volume')),
|
||||
},
|
||||
help="The Unit of Measure for the volume.")
|
||||
weight = fields.Float(
|
||||
"Weight", digits='weight_uom',
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
},
|
||||
help="Weight for 1 default unit of measure.")
|
||||
weight_uom = fields.Many2One('product.uom', 'Weight UoM',
|
||||
domain=[('category', '=', Id('product', 'uom_cat_weight'))],
|
||||
states={
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
'required': Bool(Eval('weight')),
|
||||
},
|
||||
help="The Unit of Measure for the weight.")
|
||||
|
||||
@fields.depends('volume', 'volume_uom',
|
||||
'length', 'length_uom',
|
||||
'height', 'height_uom',
|
||||
'width', 'width_uom')
|
||||
def on_change_with_volume(self):
|
||||
pool = Pool()
|
||||
ModelData = pool.get('ir.model.data')
|
||||
Uom = pool.get('product.uom')
|
||||
|
||||
if not all([self.volume_uom, self.length, self.length_uom,
|
||||
self.height, self.height_uom, self.width, self.width_uom]):
|
||||
if all([self.length, self.height, self.width]):
|
||||
return
|
||||
return self.volume
|
||||
|
||||
meter = Uom(ModelData.get_id('product', 'uom_meter'))
|
||||
cubic_meter = Uom(ModelData.get_id('product', 'uom_cubic_meter'))
|
||||
|
||||
length = Uom.compute_qty(
|
||||
self.length_uom, self.length, meter, round=False)
|
||||
height = Uom.compute_qty(
|
||||
self.height_uom, self.height, meter, round=False)
|
||||
width = Uom.compute_qty(
|
||||
self.width_uom, self.width, meter, round=False)
|
||||
|
||||
return Uom.compute_qty(
|
||||
cubic_meter, length * height * width, self.volume_uom)
|
||||
|
||||
@classmethod
|
||||
def view_attributes(cls):
|
||||
return super().view_attributes() + [
|
||||
('//page[@id="measurements"]', 'states', {
|
||||
'invisible': Eval('type').in_(NON_MEASURABLE),
|
||||
})]
|
||||
|
||||
|
||||
class Product(metaclass=PoolMeta):
|
||||
__name__ = 'product.product'
|
||||
|
||||
|
||||
class PriceList(metaclass=PoolMeta):
|
||||
__name__ = 'product.price_list'
|
||||
|
||||
def get_context_formula(self, product, quantity, uom, pattern=None):
|
||||
pool = Pool()
|
||||
UoM = pool.get('product.uom')
|
||||
ModelData = pool.get('ir.model.data')
|
||||
|
||||
liter = UoM(ModelData.get_id('product', 'uom_liter'))
|
||||
kilogram = UoM(ModelData.get_id('product', 'uom_kilogram'))
|
||||
|
||||
context = super().get_context_formula(
|
||||
product, quantity, uom, pattern=pattern)
|
||||
volume = weight = 0
|
||||
if product:
|
||||
if product.volume is not None:
|
||||
volume = UoM.compute_qty(
|
||||
product.volume_uom, product.volume, liter, round=False)
|
||||
if product.weight is not None:
|
||||
weight = UoM.compute_qty(
|
||||
product.weight_uom, product.weight, kilogram, round=False)
|
||||
context['names']['volume'] = Decimal(str(volume))
|
||||
context['names']['weight'] = Decimal(str(weight))
|
||||
return context
|
||||
|
||||
|
||||
class PriceListLine(metaclass=PoolMeta):
|
||||
__name__ = 'product.price_list.line'
|
||||
|
||||
volume_uom = fields.Many2One(
|
||||
'product.uom', "Volume UoM",
|
||||
domain=[('category', '=', Id('product', 'uom_cat_volume'))],
|
||||
help="Leave empty for liter.")
|
||||
weight_uom = fields.Many2One(
|
||||
'product.uom', "Weight UoM",
|
||||
domain=[('category', '=', Id('product', 'uom_cat_weight'))],
|
||||
help="Leave empty for kilogram.")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls.formula.help += ("\n"
|
||||
"-volume: the volume of 1 unit of product\n"
|
||||
"-weight: the weight of 1 unit of product")
|
||||
|
||||
def get_unit_price(self, **context):
|
||||
pool = Pool()
|
||||
UoM = pool.get('product.uom')
|
||||
ModelData = pool.get('ir.model.data')
|
||||
|
||||
if self.volume_uom:
|
||||
context['names'] = context['names'].copy()
|
||||
liter = UoM(ModelData.get_id('product', 'uom_liter'))
|
||||
volume = UoM.compute_qty(
|
||||
liter, float(context['names']['volume']), self.volume_uom,
|
||||
round=False)
|
||||
context['names']['volume'] = Decimal(str(volume))
|
||||
if self.weight_uom:
|
||||
context['names'] = context['names'].copy()
|
||||
kilogram = UoM(ModelData.get_id('product', 'uom_kilogram'))
|
||||
weight = UoM.compute_qty(
|
||||
kilogram, float(context['names']['weight']), self.weight_uom,
|
||||
round=False)
|
||||
context['names']['weight'] = Decimal(str(weight))
|
||||
return super().get_unit_price(**context)
|
||||
Reference in New Issue
Block a user