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>