details:   https://code.tryton.org/tryton/commit/67f4e98f0dc8
branch:    default
user:      Cédric Krier <[email protected]>
date:      Wed Feb 11 10:41:09 2026 +0100
description:
        Add a group that is allowed to cancel done shipments and moves

        Closes #13899
diffstat:

 modules/stock/CHANGELOG   |   1 +
 modules/stock/move.py     |   9 +++++++--
 modules/stock/shipment.py |  36 ++++++++++++++++++++++++++++++------
 modules/stock/stock.xml   |   8 ++++++++
 4 files changed, 46 insertions(+), 8 deletions(-)

diffs (133 lines):

diff -r 378a156b6625 -r 67f4e98f0dc8 modules/stock/CHANGELOG
--- a/modules/stock/CHANGELOG   Wed Feb 25 09:08:24 2026 +0100
+++ b/modules/stock/CHANGELOG   Wed Feb 11 10:41:09 2026 +0100
@@ -1,3 +1,4 @@
+* Add a group that is allowed to cancel done shipments and moves
 
 Version 7.8.0 - 2025-12-15
 --------------------------
diff -r 378a156b6625 -r 67f4e98f0dc8 modules/stock/move.py
--- a/modules/stock/move.py     Wed Feb 25 09:08:24 2026 +0100
+++ b/modules/stock/move.py     Wed Feb 11 10:41:09 2026 +0100
@@ -18,7 +18,7 @@
 from trytond.model.exceptions import AccessError
 from trytond.modules.product import price_digits, round_price
 from trytond.pool import Pool
-from trytond.pyson import Bool, Eval, If, TimeDelta
+from trytond.pyson import Bool, Eval, Id, If, TimeDelta
 from trytond.tools import cached_property, grouped_slice, reduce_ids
 from trytond.transaction import Transaction, without_check_access
 
@@ -464,7 +464,12 @@
                 ))
         cls._buttons.update({
                 'cancel': {
-                    'invisible': ~Eval('state').in_(['draft', 'assigned']),
+                    'invisible': (
+                        (Eval('state') == 'cancelled')
+                        | ((Eval('state') == 'done')
+                            & ~Id('stock',
+                                'group_stock_cancellation').in_(
+                                Eval('context', {}).get('groups', [])))),
                     'readonly': Eval('shipment') | Eval('_parent_shipment'),
                     'depends': ['state', 'shipment'],
                     },
diff -r 378a156b6625 -r 67f4e98f0dc8 modules/stock/shipment.py
--- a/modules/stock/shipment.py Wed Feb 25 09:08:24 2026 +0100
+++ b/modules/stock/shipment.py Wed Feb 11 10:41:09 2026 +0100
@@ -511,7 +511,12 @@
                 ))
         cls._buttons.update({
                 'cancel': {
-                    'invisible': Eval('state').in_(['cancelled', 'done']),
+                    'invisible': (
+                        (Eval('state') == 'cancelled')
+                        | ((Eval('state') == 'done')
+                            & ~Id('stock',
+                                'group_stock_cancellation').in_(
+                                Eval('context', {}).get('groups', [])))),
                     'depends': ['state'],
                     },
                 'draft': {
@@ -914,7 +919,12 @@
                 ))
         cls._buttons.update({
                 'cancel': {
-                    'invisible': Eval('state').in_(['cancelled', 'done']),
+                    'invisible': (
+                        (Eval('state') == 'cancelled')
+                        | ((Eval('state') == 'done')
+                            & ~Id('stock',
+                                'group_stock_cancellation').in_(
+                                Eval('context', {}).get('groups', [])))),
                     'depends': ['state'],
                     },
                 'draft': {
@@ -1314,7 +1324,12 @@
                 ))
         cls._buttons.update({
                 'cancel': {
-                    'invisible': Eval('state').in_(['cancelled', 'done']),
+                    'invisible': (
+                        (Eval('state') == 'cancelled')
+                        | ((Eval('state') == 'done')
+                            & ~Id('stock',
+                                'group_stock_cancellation').in_(
+                                Eval('context', {}).get('groups', [])))),
                     'depends': ['state'],
                     },
                 'draft': {
@@ -1984,7 +1999,12 @@
                 ))
         cls._buttons.update({
                 'cancel': {
-                    'invisible': Eval('state').in_(['cancelled', 'done']),
+                    'invisible': (
+                        (Eval('state') == 'cancelled')
+                        | ((Eval('state') == 'done')
+                            & ~Id('stock',
+                                'group_stock_cancellation').in_(
+                                Eval('context', {}).get('groups', [])))),
                     'depends': ['state'],
                     },
                 'draft': {
@@ -2489,8 +2509,12 @@
                 ))
         cls._buttons.update({
                 'cancel': {
-                    'invisible': Eval('state').in_(
-                        ['cancelled', 'shipped', 'done']),
+                    'invisible': (
+                        (Eval('state') == 'cancelled')
+                        | (Eval('state').in_(['shipped', 'done'])
+                            & ~Id('stock',
+                                'group_stock_cancellation').in_(
+                                Eval('context', {}).get('groups', [])))),
                     'depends': ['state'],
                     },
                 'draft': {
diff -r 378a156b6625 -r 67f4e98f0dc8 modules/stock/stock.xml
--- a/modules/stock/stock.xml   Wed Feb 25 09:08:24 2026 +0100
+++ b/modules/stock/stock.xml   Wed Feb 11 10:41:09 2026 +0100
@@ -14,6 +14,10 @@
             <field name="name">Stock Force Assignment</field>
             <field name="parent" ref="group_stock"/>
         </record>
+        <record model="res.group" id="group_stock_cancellation">
+            <field name="name">Stock Cancellation</field>
+            <field name="parent" ref="group_stock"/>
+        </record>
         <record model="res.user-res.group"
             id="user_admin_group_stock_admin">
             <field name="user" ref="res.user_admin"/>
@@ -29,6 +33,10 @@
             <field name="user" ref="res.user_admin"/>
             <field name="group" ref="group_stock_force_assignment"/>
         </record>
+        <record model="res.user-res.group" 
id="user_admin_group_stock_cancellation">
+            <field name="user" ref="res.user_admin"/>
+            <field name="group" ref="group_stock_cancellation"/>
+        </record>
 
         <record model="ir.ui.icon" id="stock_icon">
             <field name="name">tryton-stock</field>

Reply via email to