Files
tryton/modules/stock_ethanol/stock.py
T

222 lines
7.9 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 itertools import groupby
from sql import Null
from sql.conditionals import Coalesce
from trytond.model import Check, ModelSQL, fields
from trytond.modules.company.model import CompanyValueMixin
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, Id
class Configuration(metaclass=PoolMeta):
__name__ = 'stock.configuration'
ethanol_volume_uom = fields.MultiValue(
fields.Many2One(
'product.uom', "Alcohol Volume UoM", required=True,
domain=[('category', '=', Id('product', 'uom_cat_volume'))]))
@classmethod
def multivalue_model(cls, field):
pool = Pool()
if field == 'ethanol_volume_uom':
return pool.get('stock.configuration.ethanol')
return super().multivalue_model(field)
@classmethod
def default_ethanol_volume_uom(cls, **pattern):
model = cls.multivalue_model('ethanol_volume_uom')
return model.default_ethanol_volume_uom()
class ConfigurationEthanol(ModelSQL, CompanyValueMixin):
"Stock Configuration Ethanol"
__name__ = 'stock.configuration.ethanol'
ethanol_volume_uom = fields.Many2One(
'product.uom', "Ethanol Volume UoM", required=True,
domain=[('category', '=', Id('product', 'uom_cat_volume'))])
@classmethod
def default_ethanol_volume_uom(cls):
pool = Pool()
UoM = pool.get('product.uom')
ModelData = pool.get('ir.model.data')
return UoM(ModelData.get_id('product', 'uom_liter')).id
class Move(metaclass=PoolMeta):
__name__ = 'stock.move'
contain_ethanol = fields.Function(
fields.Boolean("Contain Alcohol"),
'on_change_with_contain_ethanol', searcher='search_contain_ethanol')
ethanol_by_volume = fields.Function(fields.Float(
"Alcohol By Volume", digits=(1, 4),
states={
'invisible': ~Eval('contain_ethanol'),
},
help="How much ethanol/alcohol is contained "
"in a given volume at 20 degrees Celsius."),
'on_change_with_ethanol_by_volume')
internal_ethanol_volume = fields.Float(
"Internal Alcohol Volume", readonly=True,
states={
'invisible': ~Eval('ethanol_volume_required', False),
'required': Eval('ethanol_volume_required', False),
},
help="The volume of ethanol/alcohol moved in liter.")
ethanol_volume = fields.Function(
fields.Float(
"Alcohol Volume", digits='ethanol_volume_unit',
states={
'invisible': ~Eval('ethanol_volume_required'),
},
help="The volume of ethanol/alcohol moved."),
'get_ethanol_volume')
ethanol_volume_unit = fields.Function(
fields.Many2One(
'product.uom', "Alcohol Volume UoM",
states={
'invisible': ~Eval('ethanol_volume_required'),
}),
'get_ethanol_volume_unit')
ethanol_volume_required = fields.Function(
fields.Boolean("Alcohol Volume Required"),
'on_change_with_ethanol_volume_required',
searcher='search_ethanol_volume_required')
@classmethod
def __setup__(cls):
super().__setup__()
t = cls.__table__()
cls._sql_constraints += [
('check_move_internal_ethanol_volume_pos',
Check(t,
(t.internal_ethanol_volume == Null)
| (t.internal_ethanol_volume >= 0)),
'stock.msg_move_internal_ethanol_volume_positive'),
]
@fields.depends('product')
def on_change_with_contain_ethanol(self, name=None):
if self.product:
return self.product.contain_ethanol
@classmethod
def search_contain_ethanol(cls, name, clause):
return [('product.' + clause[0], *clause[1:])]
@fields.depends('product')
def on_change_with_ethanol_by_volume(self, name=None):
if self.product:
return self.product.ethanol_by_volume_used
@classmethod
def order_ethanol_by_volume(cls, tables):
pool = Pool()
Product = pool.get('product.product')
Template = pool.get('product.template')
table, _ = tables[None]
if 'product' not in tables:
product = Product.__table__()
product_tables = tables['product'] = {
None: (product, table.product == product.id),
}
else:
product_tables = tables['product']
if 'template' not in product_tables:
template = Template.__table__()
product_tables['template'] = {
None: (template, product.template == template.id),
}
else:
template, _ = product_tables['template']
return [
Coalesce(product.ethanol_by_volume, template.ethanol_by_volume)]
@classmethod
def get_ethanol_volume(cls, moves, name):
pool = Pool()
UoM = pool.get('product.uom')
ModelData = pool.get('ir.model.data')
liter = UoM(ModelData.get_id('product', 'uom_liter'))
volumes = {}
for move in moves:
if move.internal_ethanol_volume is not None:
volume = UoM.compute_qty(
liter, move.internal_ethanol_volume,
move.ethanol_volume_unit)
else:
volume = None
volumes[move.id] = volume
return volumes
@classmethod
def get_ethanol_volume_unit(cls, moves, name):
pool = Pool()
Configuration = pool.get('stock.configuration')
configuration = Configuration(1)
units = {}
for company, moves in groupby(moves, key=lambda m: m.company):
uom = configuration.get_multivalue(
'ethanol_volume_uom', company=company.id)
for move in moves:
units[move.id] = uom.id
return units
@fields.depends('product')
def on_change_with_ethanol_volume_required(self, name=None):
if self.product:
return self.product.contain_ethanol
@classmethod
def search_ethanol_volume_required(cls, name, clause):
return [('product.contain_ethanol', *clause[1:])]
@classmethod
def default_internal_ethanol_volume(cls):
# default value before compute of the field
return 0
@fields.depends('product', methods=['on_change_with_internal_quantity'])
def on_change_with_internal_ethanol_volume(self):
pool = Pool()
UoM = pool.get('product.uom')
ModelData = pool.get('ir.model.data')
liter = UoM(ModelData.get_id('product', 'uom_liter'))
quantity = self.on_change_with_internal_quantity()
if quantity is not None and self.product:
return self.product.compute_ethanol_volume(
quantity, self.product.default_uom, liter, round=False)
def compute_fields(self, field_names=None):
cls = self.__class__
values = super().compute_fields(field_names=field_names)
if (field_names is None
or (cls.internal_ethanol_volume.on_change_with & field_names)):
internal_ethanol_volume = (
self.on_change_with_internal_ethanol_volume())
if (getattr(self, 'internal_ethanol_volume', None)
!= internal_ethanol_volume):
values['internal_ethanol_volume'] = internal_ethanol_volume
return values
class ProductsByLocations(metaclass=PoolMeta):
__name__ = 'stock.products_by_locations'
ethanol_volume = fields.Function(
fields.Float(
"Alcohol Volume", digits='ethanol_volume_unit'),
'get_product', searcher='search_product')
ethanol_volume_unit = fields.Function(
fields.Many2One('product.uom', "Alcohol Volume UoM"),
'get_product')