changeset 695c8ac24f64 in modules/stock:default
details: https://hg.tryton.org/modules/stock?cmd=changeset&node=695c8ac24f64
description:
        Allow shipments to be automatically assigned

        issue9513
        review318011002
diffstat:

 CHANGELOG    |   1 +
 ir.py        |   4 ++++
 move.py      |  26 +++++++++++++++++++++++++-
 shipment.py  |  58 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 shipment.xml |  49 ++++++++++++++++++++++++++++++++++++-------------
 5 files changed, 119 insertions(+), 19 deletions(-)

diffs (273 lines):

diff -r 57b7fe208133 -r 695c8ac24f64 CHANGELOG
--- a/CHANGELOG Sun Apr 11 22:25:13 2021 +0100
+++ b/CHANGELOG Mon Apr 12 18:33:33 2021 +0200
@@ -1,3 +1,4 @@
+* Allow shipments to be automatically assigned
 * Rename inventory count quantity_added to quantity
 * Add document source on move of product quantities by warehouse
 * Add relate from assigned shipment to products quantities by warehouse
diff -r 57b7fe208133 -r 695c8ac24f64 ir.py
--- a/ir.py     Sun Apr 11 22:25:13 2021 +0100
+++ b/ir.py     Mon Apr 12 18:33:33 2021 +0200
@@ -18,4 +18,8 @@
                     "Reschedule Supplier Return Shipments"),
                 ('stock.shipment.internal|reschedule',
                     "Reschedule Internal Shipments"),
+                ('stock.shipment.out|assign_cron',
+                    "Assign Customer Shipments"),
+                ('stock.shipment.internal|assign_cron',
+                    "Assign Internal Shipments"),
                 ])
diff -r 57b7fe208133 -r 695c8ac24f64 move.py
--- a/move.py   Sun Apr 11 22:25:13 2021 +0100
+++ b/move.py   Mon Apr 12 18:33:33 2021 +0200
@@ -301,7 +301,8 @@
         'on_change_with_cost_price_required')
     assignation_required = fields.Function(
         fields.Boolean('Assignation Required'),
-        'on_change_with_assignation_required')
+        'on_change_with_assignation_required',
+        searcher='search_assignation_required')
 
     @classmethod
     def __setup__(cls):
@@ -488,6 +489,29 @@
                 self.quantity
                 and self.from_location.type in {'storage', 'view'})
 
+    @classmethod
+    def search_assignation_required(cls, name, clause):
+        operators = {
+            '=': 'in',
+            '!=': 'not in',
+            }
+        reverse = {
+            '=': '!=',
+            '!=': '=',
+            }
+        if clause[1] in operators:
+            if not clause[2]:
+                operator = reverse[clause[1]]
+            else:
+                operator = clause[1]
+            return [
+                ('quantity', '!=', 0),
+                ('from_location.type', operators[operator], [
+                        'storage', 'view']),
+                ]
+        else:
+            return []
+
     @staticmethod
     def _get_shipment():
         'Return list of Model names for shipment Reference'
diff -r 57b7fe208133 -r 695c8ac24f64 shipment.py
--- a/shipment.py       Sun Apr 11 22:25:13 2021 +0100
+++ b/shipment.py       Mon Apr 12 18:33:33 2021 +0200
@@ -30,6 +30,12 @@
 
 
 class ShipmentAssignMixin(ShipmentMixin):
+    _assign_moves_field = None
+
+    partially_assigned = fields.Function(
+        fields.Boolean("Partially Assigned"),
+        'get_partially_assigned',
+        searcher='search_partially_assigned')
 
     @classmethod
     def assign_wizard(cls, shipments):
@@ -37,7 +43,7 @@
 
     @property
     def assign_moves(self):
-        raise NotImplementedError
+        return getattr(self, self._assign_moves_field)
 
     @dualmethod
     @ModelView.button
@@ -65,6 +71,48 @@
                 })
         cls.assign(shipments)
 
+    @classmethod
+    def _get_assign_domain(cls):
+        pool = Pool()
+        Date = pool.get('ir.date')
+        return [
+            ('state', '=', 'waiting'),
+            ('planned_date', '=', Date.today()),
+            ]
+
+    @classmethod
+    def assign_cron(cls):
+        shipments = cls.search(cls._get_assign_domain())
+        cls.assign_try(shipments)
+
+    def get_partially_assigned(self, name):
+        return any(m.state == 'assigned' for m in self.assign_moves
+            if m.assignation_required)
+
+    @classmethod
+    def search_partially_assigned(cls, name, clause):
+        operators = {
+            '=': 'where',
+            '!=': 'not where',
+            }
+        reverse = {
+            '=': '!=',
+            '!=': '=',
+            }
+        if clause[1] in operators:
+            if not clause[2]:
+                operator = reverse[clause[1]]
+            else:
+                operator = clause[1]
+            return [
+                (cls._assign_moves_field, operators[operator], [
+                        ('state', '=', 'assigned'),
+                        ('assignation_required', '=', True),
+                        ]),
+                ]
+        else:
+            return []
+
 
 class ShipmentIn(ShipmentMixin, Workflow, ModelSQL, ModelView):
     "Supplier Shipment"
@@ -515,6 +563,8 @@
     "Supplier Return Shipment"
     __name__ = 'stock.shipment.in.return'
     _rec_name = 'number'
+    _assign_moves_field = 'moves'
+
     effective_date = fields.Date('Effective Date',
         states={
             'readonly': Eval('state').in_(['cancelled', 'done']),
@@ -830,10 +880,6 @@
     def assign_wizard(cls, shipments):
         pass
 
-    @property
-    def assign_moves(self):
-        return self.moves
-
     @dualmethod
     @ModelView.button
     def assign_try(cls, shipments, with_childs=None):
@@ -880,6 +926,7 @@
     "Customer Shipment"
     __name__ = 'stock.shipment.out'
     _rec_name = 'number'
+    _assign_moves_field = 'moves'
     effective_date = fields.Date('Effective Date',
         states={
             'readonly': Eval('state').in_(['cancelled', 'done']),
@@ -1934,6 +1981,7 @@
     "Internal Shipment"
     __name__ = 'stock.shipment.internal'
     _rec_name = 'number'
+    _assign_moves_field = 'moves'
     effective_date = fields.Date('Effective Date',
         states={
             'readonly': Eval('state').in_(['cancelled', 'done']),
diff -r 57b7fe208133 -r 695c8ac24f64 shipment.xml
--- a/shipment.xml      Sun Apr 11 22:25:13 2021 +0100
+++ b/shipment.xml      Mon Apr 12 18:33:33 2021 +0200
@@ -93,18 +93,26 @@
             <field name="act_window" ref="act_shipment_in_return_form"/>
         </record>
         <record model="ir.action.act_window.domain"
-            id="act_shipment_in_return_form_domain_assigned">
-            <field name="name">Assigned</field>
-            <field name="sequence" eval="30"/>
-            <field name="domain" eval="[('state', '=', 'assigned')]" 
pyson="1"/>
+            id="act_shipment_in_return_form_domain_waiting">
+            <field name="name">Waiting</field>
+            <field name="sequence" eval="20"/>
+            <field name="domain" eval="[('state', '=', 'waiting')]" pyson="1"/>
             <field name="count" eval="True"/>
             <field name="act_window" ref="act_shipment_in_return_form"/>
         </record>
         <record model="ir.action.act_window.domain"
-            id="act_shipment_in_return_form_domain_waiting">
-            <field name="name">Waiting</field>
-            <field name="sequence" eval="20"/>
-            <field name="domain" eval="[('state', '=', 'waiting')]" pyson="1"/>
+            id="act_shipment_in_return_form_domain_available">
+            <field name="name">Partially Assigned</field>
+            <field name="sequence" eval="30"/>
+            <field name="domain" eval="[('partially_assigned', '=', 'True')]" 
pyson="1"/>
+            <field name="count" eval="True"/>
+            <field name="act_window" ref="act_shipment_in_return_form"/>
+        </record>
+        <record model="ir.action.act_window.domain"
+            id="act_shipment_in_return_form_domain_assigned">
+            <field name="name">Assigned</field>
+            <field name="sequence" eval="40"/>
+            <field name="domain" eval="[('state', '=', 'assigned')]" 
pyson="1"/>
             <field name="count" eval="True"/>
             <field name="act_window" ref="act_shipment_in_return_form"/>
         </record>
@@ -163,23 +171,30 @@
             <field name="count" eval="True"/>
             <field name="act_window" ref="act_shipment_out_form"/>
         </record>
+        <record model="ir.action.act_window.domain" 
id="act_shipment_out_form_domain_available">
+            <field name="name">Partially Assigned</field>
+            <field name="sequence" eval="30"/>
+            <field name="domain" eval="[('partially_assigned', '=', True)]" 
pyson="1"/>
+            <field name="count" eval="True"/>
+            <field name="act_window" ref="act_shipment_out_form"/>
+        </record>
         <record model="ir.action.act_window.domain" 
id="act_shipment_out_form_domain_assigned">
             <field name="name">Assigned</field>
-            <field name="sequence" eval="30"/>
+            <field name="sequence" eval="40"/>
             <field name="domain" eval="[('state', '=', 'assigned')]" 
pyson="1"/>
             <field name="count" eval="True"/>
             <field name="act_window" ref="act_shipment_out_form"/>
         </record>
         <record model="ir.action.act_window.domain" 
id="act_shipment_out_form_domain_picked">
             <field name="name">Picked</field>
-            <field name="sequence" eval="40"/>
+            <field name="sequence" eval="50"/>
             <field name="domain" eval="[('state', '=', 'picked')]" pyson="1"/>
             <field name="count" eval="True"/>
             <field name="act_window" ref="act_shipment_out_form"/>
         </record>
         <record model="ir.action.act_window.domain" 
id="act_shipment_out_form_domain_packed">
             <field name="name">Packed</field>
-            <field name="sequence" eval="50"/>
+            <field name="sequence" eval="60"/>
             <field name="domain" eval="[('state', '=', 'packed')]" pyson="1"/>
             <field name="count" eval="True"/>
             <field name="act_window" ref="act_shipment_out_form"/>
@@ -248,9 +263,17 @@
             <field name="act_window" ref="act_shipment_internal_form"/>
         </record>
         <record model="ir.action.act_window.domain"
+            id="act_shipment_internal_form_domain_available">
+            <field name="name">Partially Assigned</field>
+            <field name="sequence" eval="30"/>
+            <field name="domain" eval="[('partially_assigned', '=', True)]" 
pyson="1"/>
+            <field name="count" eval="True"/>
+            <field name="act_window" ref="act_shipment_internal_form"/>
+        </record>
+        <record model="ir.action.act_window.domain"
             id="act_shipment_internal_form_domain_assigned">
             <field name="name">Assigned</field>
-            <field name="sequence" eval="30"/>
+            <field name="sequence" eval="40"/>
             <field name="domain" eval="[('state', '=', 'assigned')]" 
pyson="1"/>
             <field name="count" eval="True"/>
             <field name="act_window" ref="act_shipment_internal_form"/>
@@ -258,7 +281,7 @@
         <record model="ir.action.act_window.domain"
             id="act_shipment_internal_form_domain_shipped">
             <field name="name">Shipped</field>
-            <field name="sequence" eval="40"/>
+            <field name="sequence" eval="50"/>
             <field name="domain" eval="[('state', '=', 'shipped')]" pyson="1"/>
             <field name="act_window" ref="act_shipment_internal_form"/>
         </record>

Reply via email to