changeset e49aaf8553e1 in modules/stock_lot:default details: https://hg.tryton.org/modules/stock_lot?cmd=changeset;node=e49aaf8553e1 description: Use dedicated model for products and lots by locations
issue9874 review314911002 diffstat: CHANGELOG | 2 + __init__.py | 1 + setup.py | 2 +- stock.py | 75 ++++++++++++++++++++++++++++++++++++++++- stock.xml | 62 ++++++++++++++------------------- view/lot_quantity_tree.xml | 9 ---- view/lots_by_locations_list.xml | 9 ++++ 7 files changed, 113 insertions(+), 47 deletions(-) diffs (278 lines): diff -r d2ddbe7787de -r e49aaf8553e1 CHANGELOG --- a/CHANGELOG Sat Dec 19 17:08:47 2020 +0100 +++ b/CHANGELOG Wed Dec 23 21:55:13 2020 +0100 @@ -1,3 +1,5 @@ +* Add lots_by_locations Model + Version 5.8.0 - 2020-11-02 * Bug fixes (see mercurial logs for details) * Remove support for Python 3.5 diff -r d2ddbe7787de -r e49aaf8553e1 __init__.py --- a/__init__.py Sat Dec 19 17:08:47 2020 +0100 +++ b/__init__.py Wed Dec 23 21:55:13 2020 +0100 @@ -10,6 +10,7 @@ Pool.register( stock.Lot, stock.LotByLocationContext, + stock.LotsByLocations, stock.LotByWarehouseContext, stock.Location, stock.Move, diff -r d2ddbe7787de -r e49aaf8553e1 setup.py --- a/setup.py Sat Dec 19 17:08:47 2020 +0100 +++ b/setup.py Wed Dec 23 21:55:13 2020 +0100 @@ -57,7 +57,7 @@ if local_version: version += '+' + '.'.join(local_version) -requires = [] +requires = ['python-sql'] for dep in info.get('depends', []): if not re.match(r'(ir|res)(\W|$)', dep): requires.append(get_require_version('trytond_%s' % dep)) diff -r d2ddbe7787de -r e49aaf8553e1 stock.py --- a/stock.py Sat Dec 19 17:08:47 2020 +0100 +++ b/stock.py Wed Dec 23 21:55:13 2020 +0100 @@ -3,8 +3,10 @@ import datetime from functools import wraps +from sql import Column + from trytond.i18n import gettext -from trytond.model import ModelView, ModelSQL, fields +from trytond.model import Model, ModelView, ModelSQL, fields from trytond.model.exceptions import AccessError, RequiredValidationError from trytond.pyson import Eval from trytond.pool import Pool, PoolMeta @@ -55,6 +57,11 @@ searcher='search_quantity') forecast_quantity = fields.Function(fields.Float('Forecast Quantity'), 'get_quantity', searcher='search_quantity') + default_uom = fields.Function( + fields.Many2One('product.uom', "Default UOM"), + 'on_change_with_default_uom') + default_uom_digits = fields.Function(fields.Integer("Default Unit Digits"), + 'on_change_with_default_uom_digits') @classmethod def __setup__(cls): @@ -76,6 +83,16 @@ return cls._search_quantity(name, location_ids, domain, grouping=('product', 'lot')) + @fields.depends('product') + def on_change_with_default_uom(self, name=None): + if self.product: + return self.product.default_uom.id + + @fields.depends('product') + def on_change_with_default_uom_digits(self, name=None): + if self.product: + return self.product.default_uom.digits + @classmethod @check_no_move def write(cls, *args): @@ -105,6 +122,62 @@ return self.forecast_date +class LotsByLocations(ModelSQL, ModelView): + "Lots by Locations" + __name__ = 'stock.lots_by_locations' + + lot = fields.Many2One('stock.lot', "Lot") + product = fields.Many2One('product.product', "Product") + quantity = fields.Function( + fields.Float( + "Quantity", digits=(16, Eval('default_uom_digits', 2)), + depends=['default_uom_digits']), + 'get_lot', searcher='search_lot') + forecast_quantity = fields.Function( + fields.Float( + "Forecast Quantity", digits=(16, Eval('default_uom_digits', 2)), + depends=['default_uom_digits']), + 'get_lot', searcher='search_lot') + default_uom = fields.Function( + fields.Many2One('product.uom', "Default UOM"), + 'get_lot', searcher='search_lot') + default_uom_digits = fields.Function( + fields.Integer("Default UOM Digits"), 'get_lot') + + @classmethod + def __setup__(cls): + super().__setup__() + cls._order.insert(0, ('lot', 'ASC')) + cls._order.insert(1, ('product', 'ASC')) + + @classmethod + def table_query(cls): + pool = Pool() + Lot = pool.get('stock.lot') + lot = Lot.__table__() + columns = [] + for fname, field in cls._fields.items(): + if not hasattr(field, 'set'): + if (isinstance(field, fields.Many2One) + and field.get_target() == Lot): + column = Column(lot, 'id') + else: + column = Column(lot, fname) + columns.append(column.as_(fname)) + return lot.select(*columns) + + def get_lot(self, name): + value = getattr(self.product, name) + if isinstance(value, Model): + value = value.id + return value + + @classmethod + def search_lot(cls, name, clause): + nested = clause[0].lstrip(name) + return [('lot.' + name + nested,) + tuple(clause[1:])] + + class LotByWarehouseContext(LotByLocationContext): "Lot by Warehouse" __name__ = 'stock.lots_by_warehouse.context' diff -r d2ddbe7787de -r e49aaf8553e1 stock.xml --- a/stock.xml Sat Dec 19 17:08:47 2020 +0100 +++ b/stock.xml Wed Dec 23 21:55:13 2020 +0100 @@ -14,12 +14,6 @@ <field name="type">tree</field> <field name="name">lot_tree</field> </record> - <record model="ir.ui.view" id="lot_quantity_view_tree"> - <field name="model">stock.lot</field> - <field name="type">tree</field> - <field name="priority" eval="20"/> - <field name="name">lot_quantity_tree</field> - </record> <record model="ir.action.act_window" id="act_lot_form"> <field name="name">Lots</field> @@ -60,39 +54,35 @@ <field name="name">lot_by_location_context_form</field> </record> - <record model="ir.action.act_window" id="act_lots_by_locations"> - <field name="name">Lots</field> - <field name="res_model">stock.lot</field> - <field name="context" eval="{'locations': Eval('active_ids')}" - pyson="1"/> + <record model="ir.ui.view" id="lots_by_locations_view_list"> + <field name="model">stock.lots_by_locations</field> + <field name="type">tree</field> + <field name="name">lots_by_locations_list</field> + </record> + + <record model="ir.action.act_window" id="act_lots_by_locations_relate"> + <field name="name">Lots by Locations</field> + <field name="res_model">stock.lots_by_locations</field> + <field name="context" eval="{'locations': Eval('active_ids')}" pyson="1"/> <field name="domain" eval="['OR', ('quantity', '!=', 0.0), ('forecast_quantity', '!=', 0.0)]" pyson="1"/> <field name="context_model">stock.lots_by_location.context</field> </record> - <record model="ir.action.act_window.view" - id="act_lots_by_locations_view1"> + <record model="ir.action.act_window.view" id="act_lots_by_locations_relate_view1"> <field name="sequence" eval="10"/> - <field name="view" ref="lot_quantity_view_tree"/> - <field name="act_window" ref="act_lots_by_locations"/> + <field name="view" ref="lots_by_locations_view_list"/> + <field name="act_window" ref="act_lots_by_locations_relate"/> </record> - <record model="ir.action.act_window.view" - id="act_lots_by_locations_view2"> - <field name="sequence" eval="20"/> - <field name="view" ref="lot_view_form"/> - <field name="act_window" ref="act_lots_by_locations"/> - </record> - <record model="ir.action.keyword" - id="act_lots_by_locations_keyword1"> + <record model="ir.action.keyword" id="act_lots_by_locations_relate_keyword1"> <field name="keyword">tree_open</field> <field name="model">stock.location,-1</field> - <field name="action" ref="act_lots_by_locations"/> + <field name="action" ref="act_lots_by_locations_relate"/> </record> - <record model="ir.action.keyword" - id="act_lots_by_locations_keyword2"> + <record model="ir.action.keyword" id="act_lots_by_locations_relate_keyword2"> <field name="keyword">form_relate</field> <field name="model">stock.location,-1</field> - <field name="action" ref="act_lots_by_locations"/> + <field name="action" ref="act_lots_by_locations_relate"/> </record> <record model="ir.ui.view" id="lots_by_warehouse_context_view_form"> @@ -101,9 +91,9 @@ <field name="name">lot_by_warehouse_context_form</field> </record> - <record model="ir.action.act_window" id="act_lots_by_warehouse"> + <record model="ir.action.act_window" id="act_lots_by_warehouse_relate"> <field name="name">Lots By Warehouse</field> - <field name="res_model">stock.lot</field> + <field name="res_model">stock.lots_by_locations</field> <field name="domain" eval="[If(Eval('active_ids', []) == [Eval('active_id')], (If(Eval('active_model') == 'product.template', 'product.template', 'product'), '=', Eval('active_id', -1)), (If(Eval('active_model') == 'product.template', 'product.template', 'product'), 'in', Eval('active_ids', []))), ['OR', ('quantity', '!=', 0.0), ('forecast_quantity', '!=', 0.0)]]" @@ -112,20 +102,20 @@ eval="None" /> <field name="context_model">stock.lots_by_warehouse.context</field> </record> - <record model="ir.action.act_window.view" id="act_lots_by_warehouse_view1"> + <record model="ir.action.act_window.view" id="act_lots_by_warehouse_relate_view1"> <field name="sequence" eval="10"/> - <field name="view" ref="lot_quantity_view_tree"/> - <field name="act_window" ref="act_lots_by_warehouse"/> + <field name="view" ref="lots_by_locations_view_list"/> + <field name="act_window" ref="act_lots_by_warehouse_relate"/> </record> - <record model="ir.action.keyword" id="act_lots_by_warehouse_keyword1"> + <record model="ir.action.keyword" id="act_lots_by_warehouse_relate_keyword1"> <field name="keyword">form_relate</field> <field name="model">product.template,-1</field> - <field name="action" ref="act_lots_by_warehouse"/> + <field name="action" ref="act_lots_by_warehouse_relate"/> </record> - <record model="ir.action.keyword" id="act_lots_by_warehouse_keyword2"> + <record model="ir.action.keyword" id="act_lots_by_warehouse_relate_keyword2"> <field name="keyword">form_relate</field> <field name="model">product.product,-1</field> - <field name="action" ref="act_lots_by_warehouse"/> + <field name="action" ref="act_lots_by_warehouse_relate"/> </record> <record model="ir.action.act_window" id="act_location_quantity_tree"> diff -r d2ddbe7787de -r e49aaf8553e1 view/lot_quantity_tree.xml --- a/view/lot_quantity_tree.xml Sat Dec 19 17:08:47 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -<?xml version="1.0"?> -<!-- This file is part of Tryton. The COPYRIGHT file at the top level of -this repository contains the full copyright notices and license terms. --> -<tree> - <field name="number"/> - <field name="product"/> - <field name="quantity"/> - <field name="forecast_quantity"/> -</tree> diff -r d2ddbe7787de -r e49aaf8553e1 view/lots_by_locations_list.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/view/lots_by_locations_list.xml Wed Dec 23 21:55:13 2020 +0100 @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<!-- This file is part of Tryton. The COPYRIGHT file at the top level of +this repository contains the full copyright notices and license terms. --> +<tree> + <field name="lot" expand="1"/> + <field name="product" expand="1"/> + <field name="quantity" symbol="default_uom"/> + <field name="forecast_quantity" symbol="default_uom"/> +</tree>