From b0f7d452544cdab28d988cc4b679cfeb9a33d79e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 29 Apr 2025 09:31:05 +0200 Subject: [PATCH] Manage readonly wizard readonly wizards do not check for write access on the active model. Closes #13989 --- modules/account/account.py | 2 ++ modules/account/account.xml | 4 ---- modules/account/move.py | 2 ++ modules/account/tax.py | 1 + modules/account_move_line_grouping/account.py | 1 + modules/analytic_account/line.py | 1 + modules/production/bom.py | 1 + modules/project_invoice/project.py | 1 + modules/sale/sale.py | 1 + modules/sale/sale_reporting.py | 2 ++ modules/stock/product.py | 2 ++ trytond/CHANGELOG | 1 + trytond/doc/ref/wizard.rst | 7 +++++++ trytond/trytond/wizard/wizard.py | 10 ++++++---- 14 files changed, 28 insertions(+), 8 deletions(-) diff --git a/modules/account/account.py b/modules/account/account.py index 6964ef77f5..90907a9c52 100644 --- a/modules/account/account.py +++ b/modules/account/account.py @@ -421,6 +421,7 @@ class Type( class OpenType(Wizard): __name__ = 'account.account.open_type' + _readonly = True start = StateTransition() account = StateAction('account.act_account_balance_sheet') ledger_account = StateAction('account.act_account_general_ledger') @@ -2306,6 +2307,7 @@ class GeneralLedgerAccountParty(_GeneralLedgerAccount): class OpenGeneralLedgerAccountParty(Wizard): __name__ = 'account.general_ledger.account.party.open' start_state = 'open' + _readonly = True open = StateAction('account.act_general_ledger_line_form') def do_open(self, action): diff --git a/modules/account/account.xml b/modules/account/account.xml index 8acbb57bc5..e760751024 100644 --- a/modules/account/account.xml +++ b/modules/account/account.xml @@ -462,10 +462,6 @@ this repository contains the full copyright notices and license terms. --> account.account.type,-1 - - - - account.account diff --git a/modules/account/move.py b/modules/account/move.py index d35e3b065c..e4d074c8dc 100644 --- a/modules/account/move.py +++ b/modules/account/move.py @@ -1934,6 +1934,7 @@ class OpenJournalAsk(ModelView): class OpenJournal(Wizard): __name__ = 'account.move.open_journal' + _readonly = True start = StateTransition() ask = StateView('account.move.open_journal.ask', 'account.open_journal_ask_view_form', [ @@ -2003,6 +2004,7 @@ class OpenJournal(Wizard): class OpenAccount(Wizard): __name__ = 'account.move.open_account' start_state = 'open_' + _readonly = True open_ = StateAction('account.act_move_line_form') def do_open_(self, action): diff --git a/modules/account/tax.py b/modules/account/tax.py index f016eed00c..787abbfbd6 100644 --- a/modules/account/tax.py +++ b/modules/account/tax.py @@ -1841,6 +1841,7 @@ class TaxRuleLine(sequence_ordered(), ModelSQL, ModelView, MatchMixin): class OpenTaxCode(Wizard): __name__ = 'account.tax.open_code' start_state = 'open_' + _readonly = True open_ = StateAction('account.act_tax_line_form') def do_open_(self, action): diff --git a/modules/account_move_line_grouping/account.py b/modules/account_move_line_grouping/account.py index 9465a4c853..4f815f1432 100644 --- a/modules/account_move_line_grouping/account.py +++ b/modules/account_move_line_grouping/account.py @@ -250,6 +250,7 @@ class MoveLineGroup_MoveLine(ModelSQL): class OpenAccount(metaclass=PoolMeta): __name__ = 'account.move.open_account' + _readonly = True def do_open_(self, action): pool = Pool() diff --git a/modules/analytic_account/line.py b/modules/analytic_account/line.py index 942ccf880f..29e2617c5e 100644 --- a/modules/analytic_account/line.py +++ b/modules/analytic_account/line.py @@ -273,6 +273,7 @@ class MoveLine(metaclass=PoolMeta): class OpenAccount(Wizard): __name__ = 'analytic_account.line.open_account' start_state = 'open_' + _readonly = True open_ = StateAction('analytic_account.act_line_form') def do_open_(self, action): diff --git a/modules/production/bom.py b/modules/production/bom.py index 07d2a5d2b5..6d25039c4e 100644 --- a/modules/production/bom.py +++ b/modules/production/bom.py @@ -318,6 +318,7 @@ class OpenBOMTreeTree(ModelView): class OpenBOMTree(Wizard): __name__ = 'production.bom.tree.open' + _readonly = True start = StateView('production.bom.tree.open.start', 'production.bom_tree_open_start_view_form', [ diff --git a/modules/project_invoice/project.py b/modules/project_invoice/project.py index eca2165fae..cca22943be 100644 --- a/modules/project_invoice/project.py +++ b/modules/project_invoice/project.py @@ -673,6 +673,7 @@ class WorkInvoicedProgress(ModelView, ModelSQL): class OpenInvoice(Wizard): __name__ = 'project.open_invoice' start_state = 'open_' + _readonly = True open_ = StateAction('account_invoice.act_invoice_form') def do_open_(self, action): diff --git a/modules/sale/sale.py b/modules/sale/sale.py index fda1cafac0..bfcdcc1aa4 100644 --- a/modules/sale/sale.py +++ b/modules/sale/sale.py @@ -2564,6 +2564,7 @@ class ModifyHeader(Wizard): class OpenProduct(Wizard): __name__ = 'sale.open_product' + _readonly = True start = StateAction('sale.act_product') diff --git a/modules/sale/sale_reporting.py b/modules/sale/sale_reporting.py index ff382f2bd2..1d0a640a8b 100644 --- a/modules/sale/sale_reporting.py +++ b/modules/sale/sale_reporting.py @@ -910,6 +910,7 @@ class RegionTree(ModelSQL, ModelView): class OpenRegionTree(Wizard): __name__ = 'sale.reporting.region.tree.open' + _readonly = True start = StateAction('sale.act_reporting_country_tree') @@ -1051,6 +1052,7 @@ class CountryTree(UnionMixin, Abstract, ModelView): class OpenCountryTree(Wizard): __name__ = 'sale.reporting.country.tree.open' + _readonly = True start = StateTransition() country = StateAction('sale.act_reporting_country_time_series') diff --git a/modules/stock/product.py b/modules/stock/product.py index a9869baa7a..37a7599e9d 100644 --- a/modules/stock/product.py +++ b/modules/stock/product.py @@ -576,6 +576,7 @@ class ProductByLocationContext(ModelView): class OpenProductQuantitiesByWarehouse(Wizard): __name__ = 'stock.product_quantities_warehouse.open' start_state = 'open_' + _readonly = True open_ = StateAction('stock.act_product_quantities_warehouse') def do_open_(self, action): @@ -869,6 +870,7 @@ class ProductQuantitiesByWarehouseContext(ModelView): class OpenProductQuantitiesByWarehouseMove(Wizard): __name__ = 'stock.product_quantities_warehouse.move.open' start_state = 'open_' + _readonly = True open_ = StateAction('stock.act_product_quantities_warehouse_move') def do_open_(self, action): diff --git a/trytond/CHANGELOG b/trytond/CHANGELOG index 5193bfd39a..40cd3a2095 100644 --- a/trytond/CHANGELOG +++ b/trytond/CHANGELOG @@ -1,3 +1,4 @@ +* Manage readonly wizard * Export Many2One and Reference using record name * Support import of one2many as list of name * Support export of xxx2many fields as list of name diff --git a/trytond/doc/ref/wizard.rst b/trytond/doc/ref/wizard.rst index 5bfd45ec18..3a21f49813 100644 --- a/trytond/doc/ref/wizard.rst +++ b/trytond/doc/ref/wizard.rst @@ -37,6 +37,13 @@ Class attributes are: deletion of the wizard and it may return one of the :ref:`client side action keywords `. +.. attribute:: Wizard._readonly + + A boolean to set :attr:`trytond.transaction.Transaction.readonly` when + executing the wizard. + When set to ``True``, ``write`` access on the ``active_model`` is not + needed. + .. attribute:: Wizard.__rpc__ Same as :attr:`trytond.model.Model.__rpc__`. diff --git a/trytond/trytond/wizard/wizard.py b/trytond/trytond/wizard/wizard.py index fc19ab8a3a..7cf830e1a5 100644 --- a/trytond/trytond/wizard/wizard.py +++ b/trytond/trytond/wizard/wizard.py @@ -198,6 +198,7 @@ class Wizard(URLMixin, PoolBase): __no_slots__ = True # To allow setting State start_state = 'start' end_state = 'end' + _readonly = False @classmethod def __setup__(cls): @@ -205,7 +206,7 @@ class Wizard(URLMixin, PoolBase): cls.__rpc__ = { 'create': RPC(readonly=False), 'delete': RPC(readonly=False), - 'execute': RPC(readonly=False, check_access=False), + 'execute': RPC(readonly=cls._readonly, check_access=False), } # Copy states @@ -248,9 +249,10 @@ class Wizard(URLMixin, PoolBase): ActionWizard = pool.get('ir.action.wizard') User = pool.get('res.user') Group = pool.get('res.group') - context = Transaction().context + transaction = Transaction() + context = transaction.context - if Transaction().user == 0: + if transaction.user == 0: return with check_access(): @@ -284,7 +286,7 @@ class Wizard(URLMixin, PoolBase): gettext( 'ir.msg_context_groups', groups=', '.join(g.rec_name for g in groups))) - elif model and model != 'ir.ui.menu': + elif model and model != 'ir.ui.menu' and not transaction.readonly: if (not callable(getattr(Model, 'table_query', None)) or Model.write.__func__ != ModelSQL.write.__func__): ModelAccess.check(model, 'write')