Skip to content

[19.0][FIX] fordward port of missing commits - #3729

Open
sergio-teruel wants to merge 8 commits into
OCA:19.0from
Tecnativa:19.0-fwp-base_exception-rollback-and-fixes
Open

sergio-teruel wants to merge 8 commits into
OCA:19.0from
Tecnativa:19.0-fwp-base_exception-rollback-and-fixes

Conversation

@sergio-teruel

Copy link
Copy Markdown
Contributor

Missing commits from 18.0:

  • c481946 — [FIX] base_exception: Rollback transaction if we detect exceptions
  • 0585624 — [REF] base_exception: Handle the exception popup at client level
  • fd9116e — [REF] base_exception: Use a client action to reload smoothly
  • 1e71842 — [TEST] base_exception: Test exception rollbacking
  • afd3d2f — base_exception: no second cursor when installing modules
  • 696561e — [FIX] base_exception: MissingError on records created in the ongoing transaction

grindtildeath and others added 6 commits September 17, 2026 10:38
This aims to solve issues when modules not depending on whatever
implementation of base_exception, override the same function that
triggers the detection of exceptions.

Before this commit, any changes done in such overrides could end
up being committed to the database if the MRO did execute such
function before the function implementing base_exception that avoids
to call super in case an exception is detected. (eg sale.order.
action_confirm in sale_exception)

With this commit, in case there is any newly detected exception,
or a record with exception that is not ignored, or a blocking
exception linked to a record, exception changes will be committed
in DB while a specific Exception type will be raised to rollback
any changes done in the ongoing transaction. Such an exception
will be handled in the UI to refresh the exception_ids field
so that the user knows why the action was not completed.
With the previous change raising an exception to rollback a
transaction, the function `_popup_exceptions` could not be called
anymore while the error was raised.

Instead, we provide now a hook `_must_popup_exception` that can be
redefined by model and will be called when `action_popup_exception`
is called by the webclient, to smoothly refresh the page and
display the popup exception wizard.
Simplify the JS layer by leveraging client actions.

Return a custom client action whenever the BaseExceptionError
is catched on RPC call and handle everything through the call
to action_popup_exceptions:
- In case exception should not pop up, return a soft reload client
action instead of handling the refresh manually in JS
- In case exception should pop up, return the wizard action, but
do a soft reload first to display the exception_ids block before
execution the wizard opening action.
Make test decorator available for import in other modules

Avoid using new env for unrelated tests
detect_exceptions() stores the exceptions in a separate transaction (a new
cursor/connection) so that they are kept when the ongoing transaction is
rolled back. When the registry is not ready yet (module installation or
update), the ongoing transaction holds exclusive locks on the tables it has
just modified (ALTER TABLE ...). The call to
_must_raise_exception_after_detection() made inside that new transaction then
reads the model records, and the query waits for those locks forever: the
only thread able to release them is the one waiting for them.

This happens as soon as demo data confirming a sale order is loaded during a
database initialisation with sale_exception installed (e.g. the sale_stock
demo data), making the whole database initialisation hang.

Use the current cursor in that case, as already done when running tests.
…transaction

detect_exceptions() opens a second, genuinely independent DB connection
(self.env.registry.cursor()) to write exception flags so they survive a
rollback of the ongoing transaction. It then re-derived main_records
through that same second connection (self.with_env(new_env)), which
crashes with MissingError whenever _get_main_records() has to read a
field on records created earlier in the SAME ongoing transaction and not
yet committed (e.g. sale.order.line._get_main_records() reading order_id
right after the line was created by write()).

Typical trigger: adding a product to an already confirmed sale order.
sale_exception.write() re-runs detect_exceptions() on order_line whenever
order_line changes on a confirmed order; the new line only exists in the
ongoing transaction, so the second connection can't see it yet.

Resolve main_records once through the original (main) cursor, which does
see the just-created records, and only rebind that already-resolved
recordset to the new environment for the exception_ids check.
@OCA-git-bot

Copy link
Copy Markdown
Contributor

Hi @hparfr, @sebastienbeau,
some modules you are maintaining are being modified, check this out!

Odoo 19.0 dropped 'decorator' from its core requirements.txt (present in18.0).
base_exception's tests use it directly (via the decorator package, not through odoo_test_helper as in 18.0),
so CI fails with ModuleNotFoundError: No module named 'decorator' when running the forward-ported test suite.
Odoo 19.0 renamed Registry.enter_test_mode(cr)/leave_test_mode() to TransactionCase.registry_enter_test_mode()/registry_leave_test_mode(),
with automatic cleanup registration. test_rollback_main_transaction (forward-ported from 18.0 in an earlier commit) still used the old API,
failing with AttributeError: 'Registry' object has no attribute 'enter_test_mode'.
@sergio-teruel
sergio-teruel marked this pull request as ready for review September 17, 2026 09:33
@sergio-teruel

Copy link
Copy Markdown
Contributor Author


@api.model
def _get_popup_action(self):
return self.env.ref("base_exception.action_exception_rule_confirm")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please adapt this code. You should use self.env["ir.actions.actions"]._for_xml_id().

if field in record._get_readable_fields()
}
action.update(
# TODO: When migrating, use _for_xml_id instead of this

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you adapt the code as commented here: https://github.com/OCA/server-tools/pull/3729/changes#r4036710316 please remove the TODO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants