changeset 6b5f97da147a in modules/stock_lot:default
details: https://hg.tryton.org/modules/stock_lot?cmd=changeset&node=6b5f97da147a
description:
        Add lot traceability

        issue10792
        review387871002
diffstat:

 CHANGELOG               |    1 +
 __init__.py             |    1 +
 stock.py                |  118 ++++++++++++++++++++++++++++++++++++++++++++++++
 stock.xml               |  111 ++++++++++++++++++++++++++++++++++++++------
 view/lot_form.xml       |    5 ++
 view/lot_trace_tree.xml |   10 ++++
 6 files changed, 229 insertions(+), 17 deletions(-)

diffs (309 lines):

diff -r aa9101381f03 -r 6b5f97da147a CHANGELOG
--- a/CHANGELOG Thu Feb 03 23:13:27 2022 +0100
+++ b/CHANGELOG Sat Mar 19 22:44:15 2022 +0100
@@ -1,3 +1,4 @@
+* Add lot traceability
 * Add support for Python 3.10
 * Remove support for Python 3.6
 
diff -r aa9101381f03 -r 6b5f97da147a __init__.py
--- a/__init__.py       Thu Feb 03 23:13:27 2022 +0100
+++ b/__init__.py       Sat Mar 19 22:44:15 2022 +0100
@@ -12,6 +12,7 @@
 def register():
     Pool.register(
         stock.Lot,
+        stock.LotTrace,
         stock.LotByLocationContext,
         stock.LotsByLocations,
         stock.LotByWarehouseContext,
diff -r aa9101381f03 -r 6b5f97da147a stock.py
--- a/stock.py  Thu Feb 03 23:13:27 2022 +0100
+++ b/stock.py  Sat Mar 19 22:44:15 2022 +0100
@@ -89,6 +89,10 @@
         cls._modify_no_move = [
             ('product', None, 'stock_lot.msg_change_product'),
             ]
+        cls._buttons.update({
+                'upward_traces': {},
+                'downward_traces': {},
+                })
 
     @classmethod
     def get_quantity(cls, lots, name):
@@ -139,6 +143,120 @@
     def write(cls, *args):
         super(Lot, cls).write(*args)
 
+    @classmethod
+    @ModelView.button_action('stock_lot.act_lot_trace_upward_relate')
+    def upward_traces(cls, lots):
+        pass
+
+    @classmethod
+    @ModelView.button_action('stock_lot.act_lot_trace_downward_relate')
+    def downward_traces(cls, lots):
+        pass
+
+
+class LotTrace(ModelSQL, ModelView):
+    "Lot Trace"
+    __name__ = 'stock.lot.trace'
+
+    product = fields.Many2One(
+        'product.product', "Product",
+        context={
+            'company': Eval('company', -1),
+            },
+        depends=['company'])
+    lot = fields.Many2One('stock.lot', "Lot")
+
+    quantity = fields.Float("Quantity", digits='unit')
+    unit = fields.Many2One('product.uom', "Unit")
+
+    company = fields.Many2One('company.company', "Company")
+    date = fields.Date("Date")
+    shipment = fields.Reference("Shipment", 'get_shipments')
+    document = fields.Function(
+        fields.Reference("Document", 'get_documents'), 'get_document')
+
+    upward_traces = fields.Function(
+        fields.Many2Many(
+            'stock.lot.trace', None, None, "Upward Traces"),
+        'get_upward_traces')
+    downward_traces = fields.Function(
+        fields.Many2Many(
+            'stock.lot.trace', None, None, "Downward Traces"),
+        'get_downward_traces')
+
+    @classmethod
+    def __setup__(cls):
+        super().__setup__()
+        cls._order.insert(0, ('date', 'ASC'))
+
+    @classmethod
+    def table_query(cls):
+        pool = Pool()
+        Move = pool.get('stock.move')
+        move = Move.__table__()
+        return (
+            move.select(
+                *cls._columns(move),
+                where=move.state == 'done'))
+
+    @classmethod
+    def _columns(cls, move):
+        return [
+            move.id.as_('id'),
+            move.create_uid.as_('create_uid'),
+            move.create_date.as_('create_date'),
+            move.write_uid.as_('write_uid'),
+            move.write_date.as_('write_date'),
+            move.product.as_('product'),
+            move.lot.as_('lot'),
+            move.quantity.as_('quantity'),
+            move.uom.as_('unit'),
+            move.company.as_('company'),
+            move.effective_date.as_('date'),
+            move.shipment.as_('shipment'),
+            ]
+
+    def get_rec_name(self, name):
+        return self.document.rec_name if self.document else str(self.id)
+
+    @classmethod
+    def get_shipments(cls):
+        pool = Pool()
+        Move = pool.get('stock.move')
+        return Move.get_shipment()
+
+    @classmethod
+    def get_documents(cls):
+        return cls.get_shipments()
+
+    def get_document(self, name):
+        if self.shipment:
+            return str(self.shipment)
+
+    @classmethod
+    def _is_trace_move(cls, move):
+        return move.state == 'done'
+
+    @classmethod
+    def _trace_move_order_key(cls, move):
+        return (move.effective_date,)
+
+    def get_upward_traces(self, name):
+        return list(map(int, sorted(filter(
+                        self._is_trace_move, self._get_upward_traces()),
+                    key=self._trace_move_order_key)))
+
+    def _get_upward_traces(self):
+        return set()
+
+    def get_downward_traces(self, name):
+        return list(map(int, sorted(filter(
+                        self._is_trace_move, self._get_downward_traces()),
+                    key=self._trace_move_order_key)))
+
+    def _get_downward_traces(self):
+        return set()
+
 
 class LotByLocationContext(ModelView):
     'Lot by Location'
diff -r aa9101381f03 -r 6b5f97da147a stock.xml
--- a/stock.xml Thu Feb 03 23:13:27 2022 +0100
+++ b/stock.xml Sat Mar 19 22:44:15 2022 +0100
@@ -51,6 +51,100 @@
             <field name="perm_delete" eval="True"/>
         </record>
 
+        <record model="ir.model.button" id="lot_upward_traces_button">
+            <field name="name">upward_traces</field>
+            <field name="string">Upward Traces</field>
+            <field name="model" search="[('model', '=', 'stock.lot')]"/>
+        </record>
+
+        <record model="ir.model.button" id="lot_downward_traces_button">
+            <field name="name">downward_traces</field>
+            <field name="string">Downward Traces</field>
+            <field name="model" search="[('model', '=', 'stock.lot')]"/>
+        </record>
+
+        <record model="ir.ui.view" id="lot_trace_view_tree_upward">
+            <field name="model">stock.lot.trace</field>
+            <field name="type">tree</field>
+            <field name="field_childs">upward_traces</field>
+            <field name="name">lot_trace_tree</field>
+        </record>
+
+        <record model="ir.ui.view" id="lot_trace_view_tree_downward">
+            <field name="model">stock.lot.trace</field>
+            <field name="type">tree</field>
+            <field name="field_childs">downward_traces</field>
+            <field name="name">lot_trace_tree</field>
+        </record>
+
+        <record model="ir.action.act_window" id="act_lot_trace_upward_relate">
+            <field name="name">Upward Traces</field>
+            <field name="res_model">stock.lot.trace</field>
+            <field
+                name="domain"
+                eval="[('lot', 'in', Eval('active_ids', []))]"
+                pyson="1"/>
+        </record>
+        <record model="ir.action.act_window.view" 
id="act_lot_trace_upward_relate_view1">
+            <field name="sequence" eval="10"/>
+            <field name="view" ref="lot_trace_view_tree_upward"/>
+            <field name="act_window" ref="act_lot_trace_upward_relate"/>
+        </record>
+        <record model="ir.action.keyword" 
id="act_lot_trace_upward_relate_keyword1">
+            <field name="keyword">form_relate</field>
+            <field name="model">stock.lot,-1</field>
+            <field name="action" ref="act_lot_trace_upward_relate"/>
+        </record>
+
+        <record model="ir.action.act_window" 
id="act_lot_trace_downward_relate">
+            <field name="name">Downward Traces</field>
+            <field name="res_model">stock.lot.trace</field>
+            <field
+                name="domain"
+                eval="[('lot', 'in', Eval('active_ids', []))]"
+                pyson="1"/>
+        </record>
+        <record model="ir.action.act_window.view" 
id="act_lot_trace_downward_relate_view1">
+            <field name="sequence" eval="10"/>
+            <field name="view" ref="lot_trace_view_tree_downward"/>
+            <field name="act_window" ref="act_lot_trace_downward_relate"/>
+        </record>
+        <record model="ir.action.keyword" 
id="act_lot_trace_downward_relate_keyword1">
+            <field name="keyword">form_relate</field>
+            <field name="model">stock.lot,-1</field>
+            <field name="action" ref="act_lot_trace_downward_relate"/>
+        </record>
+
+        <record model="ir.rule.group" id="rule_group_lot_trace_companies">
+            <field name="name">User in companies</field>
+            <field name="model" search="[('model', '=', 'stock.lot.trace')]"/>
+            <field name="global_p" eval="True"/>
+        </record>
+        <record model="ir.rule" id="rule_lot_trace_companies">
+            <field
+                name="domain"
+                eval="[('company', 'in', Eval('companies', []))]"
+                pyson="1"/>
+            <field name="rule_group" ref="rule_group_lot_trace_companies"/>
+        </record>
+
+        <record model="ir.model.access" id="access_lot_trace">
+            <field name="model" search="[('model', '=', 'stock.lot.trace')]"/>
+            <field name="perm_read" eval="False"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
+
+        <record model="ir.model.access" id="access_lot_trace_group_stock">
+            <field name="model" search="[('model', '=', 'stock.lot.trace')]"/>
+            <field name="group" ref="stock.group_stock"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
+
         <record model="ir.ui.view" id="lots_by_location_context_view_form">
             <field name="model">stock.lots_by_location.context</field>
             <field name="type">form</field>
@@ -163,23 +257,6 @@
             <field name="action" ref="act_location_quantity_list"/>
         </record>
 
-        <record model="ir.action.act_window" id="act_move_form_relate_lot">
-            <field name="name">Moves</field>
-            <field name="res_model">stock.move</field>
-            <field name="domain"
-                eval="[If(Eval('active_ids', []) == [Eval('active_id')], 
('lot', '=', Eval('active_id')), ('lot', 'in', Eval('active_ids')))]"
-                pyson="1"/>
-            <field name="order"
-                eval="[('effective_date', 'DESC'), ('planned_date', 'DESC')]"
-                pyson="1"/>
-        </record>
-        <record model="ir.action.keyword"
-            id="act_move_form_relate_lot_keyword1">
-            <field name="keyword">form_relate</field>
-            <field name="model">stock.lot,-1</field>
-            <field name="action" ref="act_move_form_relate_lot"/>
-        </record>
-
         <record model="ir.ui.view" id="move_view_form">
             <field name="model">stock.move</field>
             <field name="inherit" ref="stock.move_view_form"/>
diff -r aa9101381f03 -r 6b5f97da147a view/lot_form.xml
--- a/view/lot_form.xml Thu Feb 03 23:13:27 2022 +0100
+++ b/view/lot_form.xml Sat Mar 19 22:44:15 2022 +0100
@@ -6,4 +6,9 @@
     <field name="number"/>
     <label name="product"/>
     <field name="product"/>
+
+    <group id="relates" colspan="4" col="-1">
+        <button name="upward_traces" icon="tryton-arrow-up"/>
+        <button name="downward_traces" icon="tryton-arrow-down"/>
+    </group>
 </form>
diff -r aa9101381f03 -r 6b5f97da147a view/lot_trace_tree.xml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/view/lot_trace_tree.xml   Sat Mar 19 22:44:15 2022 +0100
@@ -0,0 +1,10 @@
+<?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="document" expand="2"/>
+    <field name="product" expand="1"/>
+    <field name="lot" expand="1"/>
+    <field name="quantity" symbol="unit"/>
+    <field name="date"/>
+</tree>

Reply via email to