Monday, May 25, 2026
5 changes · saas-18.4
Resolved issues and error corrections
Malaysian POS invoices with invoice numbers that include a fiscal year range can now be sent to MyInvois without triggering an error. This prevents disruption for businesses using year-range numbering formats for compliant e-invoicing submissions.
Original PR description
Currently, an error is produced when sending invoices to MyInvois if the invoice number uses a year-range sequence. **Steps to Reproduce:(v-19.0)** 1. Install the `accountant` and `l10n_my_edi`…
Currently, an error is produced when sending invoices to MyInvois if the invoice number uses a year-range sequence. **Steps to Reproduce:(v-19.0)** 1. Install the `accountant` and `l10n_my_edi` modules (with demo data). 2. Switch to "MY Company"(Malaysian company). 3. Enable "_Quick Encoding_" for Customer Invoices in Settings. 4. Create a customer invoice with customer "_MY Company_", set a Malaysian classification code and taxes on the invoice line, and confirm the invoice. 5. Set the invoice back to Draft and modify the invoice number with a year-range sequence (e.g., INV/2025-2026/00001), then confirm it again. 6. Open the invoice list view and click **"Send to MyInvois"**. **Error:** `ValueError: not enough values to unpack (expected 4, got 2)` The `_get_sequence_date_range()` method on `myinvois.document` overrides the method from `sequence.mixin` and returns only two values from `date_utils.get_fiscal_year()`. However, it expects the method to return four values at [1]. [1] - https://github.com/odoo/odoo/blob/57b6b8d63b038ede32dfcc833c30e93d0cf4166c/addons/account/models/sequence_mixin.py#L146 Ref: https://github.com/odoo/odoo/blob/1ce06257f877711bd5de5487364909d72b476318/addons/account/models/account_move.py#L4263 sentry-7320998540 Forward-Port-Of: odoo/odoo#253237
This fixes how the HTML editor records grouped content changes so undo and redo actions can replay them in the right order. It helps prevent content from being restored or reapplied incorrectly after editing complex text or layout changes.
Original PR description
This is a backport of [commit](bf86b89f7cdab0ae378a1d897bfef625ccb4cb38). #### Description of the issue: A "childList" mutation record with multiple added or removed nodes is transformed and stored…
This is a backport of [commit](bf86b89f7cdab0ae378a1d897bfef625ccb4cb38).
#### Description of the issue:
A "childList" mutation record with multiple added or removed nodes is transformed and stored as a sequence of individual "add" or "remove" mutations.
Before this commit, each of the resulting "remove" mutations would contain the same previousSibling/nextSibling pair of the original record. The same happened for "add" mutations (in the form of the equivalent operation, e.g. "append", "after", etc).
This was incorrect, as the previousSibling/nextSibling pair of the original record would not be the same for each added/removed node. Inserting nodes A and B between nodes P and N (previous and next siblings) is NOT equivalent to
[
insert A between P and N,
insert B between P and N // wrong,
]
The second resulting mutation does not make sense, as there's already a node A between P and N at this point, so it is ambiguous whether the insertion should should be done between P and A, or between A and N. So the correct equivalence, when converting a batch insertion of nodes A and B between P and N into a sequence of individual insertions, would be:
[
insert A between P and N,
insert B between A and N // correct
]
Similarly, when removing nodes A and B, having N an P as their outer siblings, the correct sequence of mutations would be: [
remove A between P and B, // A's nextSibling is B at this point
remove B between P and N
]
This incorrect information about siblings in stored mutations would lead, in some cases, to incorrect results when later applying or reverting mutations, as demonstrated by the test added by this commit.
Moreover, a mutation record having both added and removed nodes, when transformed into a sequence of individual mutations, should first contain the "remove" mutations, and then the "add" mutations, as the latter assumes that the original previous and next siblings, as references for inserting point, are siblings between each other, which is only true after the "remove" mutations took place.
task-4678910, 6205143
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#263505This fixes a server error that could appear when a user continued browsing in another tab after their session was invalidated, such as after a password change. Users are now redirected appropriately instead of seeing a 500 error, improving reliability during login/session transitions.
Original PR description
1. Apply the below diff. 2. Login using the same account in two independent tabs (e.g. one regular tab, and a private one). 3. In the first tab, change the account password. 4. In the second tab, go…
1. Apply the below diff.
2. Login using the same account in two independent tabs (e.g. one regular tab, and a private one).
3. In the first tab, change the account password.
4. In the second tab, go to `/web/binary/upload_attachment` (any `type='http', auth='user'` controller would do) => 500 error.
> AttributeError: 'HttpDispatcher' object has no attribute 'env'
```
diff --git a/odoo/http.py b/odoo/http.py
index b0fd6197aea8..1ea817ec85cd 100644
--- a/odoo/http.py
+++ b/odoo/http.py
@@ -2309,7 +2309,7 @@ class HttpDispatcher(Dispatcher):
"""
if isinstance(exc, SessionExpiredException):
session = self.request.session
- was_connected = session.uid is not None
+ was_connected = True
session.logout(keep_db=True)
response = self.request.redirect_query('/web/login', {'redirect': self.request.httprequest.full_path})
if was_connected:
```
It is necessary to apply the diff because most places that raise `SessionExpiredException` also pro-actively `logout()`, i.e. they reset `session.uid` and when the exception reaches handle-error `was_connected` is always `False`. For the bug to occur, we need a way to be in the `was_connected == True` case but we found no way in standard Odoo (this also explains how this bug is still present, 2 years later). The diff is the easiest way we found to reproduce it.
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#265952This update resolves a bug impacting how customer account refunds are processed. Previously, refunds caused issues with order settlement, particularly when new orders were created after a refund. The fix restores the original settlement behavior, ensuring accurate order processing and preventing errors in later versions of Odoo.
Original PR description
Refunding a customer account order was introduced by this commit: https://github.com/odoo/enterprise/commit/5a1af0db647563cffcb796a257ad01c0d0c9af91 The goal was to show both the original order and…
Refunding a customer account order was introduced by this commit: https://github.com/odoo/enterprise/commit/5a1af0db647563cffcb796a257ad01c0d0c9af91 The goal was to show both the original order and its refund in the settlement list and allow settling them together. This works in 18.2 where the feature was introduced, but it causes issues in later versions. The main issues are: - Refunded order still appears after the full order is refunded and a new order was created and paid by customer account. - When two orders exist and the larger one is settled first, the second order cannot be settled correctly. How to reproduce: - Create OrderA with AmountA - Create OrderB with AmountB < AmountA - Settle OrderA - Try to settle OrderB: it cannot be found - Settling by amount shows incorrect values due to negative customer_due_total for settlement orders. The fix: Restore the original settlement behavior and handle customer account refunds the same way as settlement orders. opw-6192248 Forward-Port-Of: odoo/enterprise#117520
This update resolves an issue where the 'Info & Tags' chatter wasn't visible on the mobile Documents app's kanban view. The fix adjusts CSS styling to ensure the chatter element is always accessible and scrollable, improving usability on mobile devices. This ensures users can easily access important document information.
Original PR description
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not…
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not displayed but the button is still enabled - Switching to the list view properly shows it **Issue:** We have two conflicting css styling on mobile: - `overflow-hidden` was added for mobile to avoid multiple scroll bars - `min-height: 100%` which is due to the default `o_kanban_ungrouped` in the controller css This means that the element is present at the bottom of the page, but we can't get to it manually. When re-enabling the action we are properly moved to the existing chatter (but we can't go back to the top). Also the documents panel should have a single scrollbar to display all the records, but we still need a way to scroll the messages of the chatter. **Fix:** Set `min-height: 0;` for documents kanban to ensure the chatter is still visible and accessible on mobile by default. This makes the chatter take the full available height when displayed. original overflow fix: https://github.com/odoo/enterprise/commit/945b9e2b1c6752bd905695aa40b0babcf38c50cd opw-6061993 Forward-Port-Of: odoo/enterprise#113168