From 7a563a3789b456fdc2910d735178b8e802c00b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 15 Sep 2026 15:19:40 +0200 Subject: [PATCH] Include administrators in button states based on groups Since 6ebedcf8826e, administrators have no more groups. Closes #15097 --- modules/account_invoice/invoice.py | 18 ++++++++---- modules/production/production.py | 4 ++- .../purchase_blanket_agreement/purchase.py | 7 +++-- modules/sale_blanket_agreement/sale.py | 7 +++-- modules/stock/move.py | 4 ++- modules/stock/shipment.py | 28 +++++++++++++------ 6 files changed, 48 insertions(+), 20 deletions(-) diff --git a/modules/account_invoice/invoice.py b/modules/account_invoice/invoice.py index ecd32f7cd5..c2a03b95a1 100644 --- a/modules/account_invoice/invoice.py +++ b/modules/account_invoice/invoice.py @@ -115,14 +115,16 @@ class Invoice( 'readonly': ( Eval('has_report_cache', False) & ~Id('account', 'group_account_admin').in_( - Eval('context', {}).get('groups', []))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get('administrator', False)), }) description = fields.Char("Description", size=None, states={ 'readonly': ( (Eval('state') != 'draft') & ~Id('account', 'group_account_admin').in_( - Eval('context', {}).get('groups', []))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get('administrator', False)), }) validated_by = employee_field( "Validated By", @@ -305,7 +307,8 @@ class Invoice( 'readonly': ( (Eval('state') != 'draft') & ~Id('account', 'group_account_admin').in_( - Eval('context', {}).get('groups', []))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get('administrator', False)), }) origins = fields.Function(fields.Char('Origins'), 'get_origins') origin_invoices = fields.Function(fields.Many2Many( @@ -2581,7 +2584,8 @@ class InvoiceLine(sequence_ordered(), ModelSQL, ModelView, TaxableMixin): states={ 'readonly': (_states['readonly'] & ~Id('account', 'group_account_admin').in_( - Eval('context', {}).get('groups', []))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get('administrator', False)), }) summary = fields.Function( fields.Char('Summary'), 'on_change_with_summary', @@ -3247,7 +3251,8 @@ class InvoiceTax(sequence_ordered(), ModelSQL, ModelView): states={ 'readonly': (_states['readonly'] & ~Id('account', 'group_account_admin').in_( - Eval('context', {}).get('groups', []))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get('administrator', False)), }) sequence_number = fields.Function(fields.Integer('Sequence Number'), 'get_sequence_number') @@ -3292,7 +3297,8 @@ class InvoiceTax(sequence_ordered(), ModelSQL, ModelView): states={ 'readonly': (_states['readonly'] & ~Id('account', 'group_account_admin').in_( - Eval('context', {}).get('groups', []))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get('administrator', False)), }) del _states diff --git a/modules/production/production.py b/modules/production/production.py index 0757d0aae8..adb59ef090 100644 --- a/modules/production/production.py +++ b/modules/production/production.py @@ -207,7 +207,9 @@ class Production( | (Eval('state').in_(['running', 'done']) & ~Id('stock', 'group_stock_cancellation').in_( - Eval('context', {}).get('groups', [])))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get( + 'administrator', False))), 'depends': ['state'], }, 'draft': { diff --git a/modules/purchase_blanket_agreement/purchase.py b/modules/purchase_blanket_agreement/purchase.py index e101c50f90..770d5b1f2e 100644 --- a/modules/purchase_blanket_agreement/purchase.py +++ b/modules/purchase_blanket_agreement/purchase.py @@ -223,8 +223,11 @@ class BlanketAgreement(Workflow, ModelSQL, ModelView, ChatMixin): 'run': { 'invisible': ( (Eval('state') != 'draft') - & ~(Id('purchase', 'group_purchase_admin').in_( - Eval('context', {}).get('groups', [])) + & ~( + (Id('purchase', 'group_purchase_admin').in_( + Eval('context', {}).get('groups', [])) + | Eval('context', {}).get( + 'administrator', False)) & (Eval('state') == 'closed'))), 'readonly': (~Eval('lines') | (Eval('from_date', Date()) > Date())), diff --git a/modules/sale_blanket_agreement/sale.py b/modules/sale_blanket_agreement/sale.py index 4c2ac2da8c..b91c8ce841 100644 --- a/modules/sale_blanket_agreement/sale.py +++ b/modules/sale_blanket_agreement/sale.py @@ -224,8 +224,11 @@ class BlanketAgreement(Workflow, ModelSQL, ModelView, ChatMixin): 'run': { 'invisible': ( (Eval('state') != 'draft') - & ~(Id('sale', 'group_sale_admin').in_( - Eval('context', {}).get('groups', [])) + & ~( + (Id('sale', 'group_sale_admin').in_( + Eval('context', {}).get('groups', [])) + | Eval('context', {}).get( + 'administrator', False)) & (Eval('state') == 'closed'))), 'readonly': (~Eval('lines') | (Eval('from_date', Date()) > Date())), diff --git a/modules/stock/move.py b/modules/stock/move.py index 5b9157d52e..63c08340b2 100644 --- a/modules/stock/move.py +++ b/modules/stock/move.py @@ -497,7 +497,9 @@ class Move(Workflow, ModelSQL, ModelView): | ((Eval('state') == 'done') & ~Id('stock', 'group_stock_cancellation').in_( - Eval('context', {}).get('groups', [])))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get( + 'administrator', False))), 'readonly': Eval('shipment') | Eval('_parent_shipment'), 'depends': ['state', 'shipment'], }, diff --git a/modules/stock/shipment.py b/modules/stock/shipment.py index 4bb84738e6..6631590aea 100644 --- a/modules/stock/shipment.py +++ b/modules/stock/shipment.py @@ -515,7 +515,9 @@ class ShipmentIn( | ((Eval('state') == 'done') & ~Id('stock', 'group_stock_cancellation').in_( - Eval('context', {}).get('groups', [])))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get( + 'administrator', False))), 'depends': ['state'], }, 'draft': { @@ -927,7 +929,9 @@ class ShipmentInReturn( | ((Eval('state') == 'done') & ~Id('stock', 'group_stock_cancellation').in_( - Eval('context', {}).get('groups', [])))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get( + 'administrator', False))), 'depends': ['state'], }, 'draft': { @@ -1331,7 +1335,9 @@ class ShipmentOut( | ((Eval('state') == 'done') & ~Id('stock', 'group_stock_cancellation').in_( - Eval('context', {}).get('groups', [])))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get( + 'administrator', False))), 'depends': ['state'], }, 'draft': { @@ -2009,7 +2015,9 @@ class ShipmentOutReturn( | ((Eval('state') == 'done') & ~Id('stock', 'group_stock_cancellation').in_( - Eval('context', {}).get('groups', [])))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get( + 'administrator', False))), 'depends': ['state'], }, 'draft': { @@ -2523,7 +2531,9 @@ class ShipmentInternal( | (Eval('state').in_(['shipped', 'done']) & ~Id('stock', 'group_stock_cancellation').in_( - Eval('context', {}).get('groups', [])))), + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get( + 'administrator', False))), 'depends': ['state'], }, 'draft': { @@ -3044,9 +3054,11 @@ class Assign(Wizard): Button("Ignore", 'ignore', 'tryton-forward'), Button("Force", 'force', 'tryton-forward', states={ - 'invisible': ~Id('stock', - 'group_stock_force_assignment').in_( - Eval('context', {}).get('groups', [])), + 'invisible': ( + ~Id('stock', + 'group_stock_force_assignment').in_( + Eval('context', {}).get('groups', [])) + & ~Eval('context', {}).get('administrator', False)), }), ]) cancel = StateTransition()