Thursday, August 27, 2026
25 changes · saas-19.4
Resolved issues and error corrections
Website page caching now handles expired cached pages consistently before storing them again. This helps prevent rare website errors that could occur when an expired page cache was refreshed incorrectly.
Original PR description
**Problem:** Normally, the cached response for an HTTP request will be 'flattened', meaning the QWEB template is force-rendered and stored as `response.response[0]`. However, when the cached response is too old, a new cache value is set which is not flattened. This is inconsistent with the value normally returned by `_get_response_cached()` which will cause a traceback when accessing `response.response[0]`. This issue is rarely reproducible because `flatten()` is usually called on the response later (outside `_get_response()`), and because the returned response points to the same object as in the cache, the cache gets flattened as well. **Solution:** When the cached response is too old, flatten the new response before caching it. opw-6382359 Forward-Port-Of: odoo/odoo#283861 Forward-Port-Of: odoo/odoo#277590
This fix improves how AI-related attachments are checked before cleanup by limiting access checks to the specific files involved. This helps avoid unnecessary broad searches, reducing the risk of delays or errors when access rules are applied.
Original PR description
When marking attachments, check access only to given ids explicitly instead of searching for all records. Given access rules, the search without a sudo would try to find all attachments and filter them. https://github.com/odoo/odoo/pull/284394 task-6488506 Forward-Port-Of: odoo/enterprise#129120
This fix separates tests for product loading limits from tests for product ordering in Point of Sale and stock-related Point of Sale features. It helps ensure automated checks remain reliable when stock features are installed, reducing false test failures without changing user-facing behavior.
Original PR description
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching…
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching code: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L190 This allowed us to completely override (not extend) the ordering of the loaded products in our new pos_stock module: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/pos_stock/models/product_template.py#L42-L65 Notice the difference in point_of_sale: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L403-L416 This was causing problems with our existing test for this feature in point_of_sale because we were explicitly examining the ordering of the products; obviously this ordering would be different when pos_stock is installed alongside point_of_sale. Thus, we must decouple our original test for this feature so that ordering can be examined independently in each module's tests. ## Now: We have one test in point_of_sale that just makes sure our limited products loading feature actually caps the number of products loaded. This test will work correctly whether or not pos_stock is installed. In addition, we have one more test in point_of_sale and pos_stock that explicitly examines the ordering of the products in these limiting conditions when both modules are installed. The point_of_sale test will be skipped when pos_stock is installed because the latter module defines conflicting ordering. runbot-243064 Forward-Port-Of: odoo/odoo#283621
This fixes an issue where unsaved translation text could disappear when a user dragged the translation dialog. Users can now reposition the dialog without losing changes they have just typed, reducing frustration and rework.
Original PR description
Step to reproduce: - have atleast two language and install sale - open any product, hover over product, and click on Translation button - Enter a value for one of language - drag the dialog Observation: - we lose the data, we just entered and fallback to original data Cause: - Inputs used `t-att-value="term.value"`, bound to original data. Since this content is passed to Dialog via slot, it is rendered/patched as part of Dialog's render cycle, - Dragging updates Dialog's state, triggering a patch that re-evaluated the slotted template and reset input values (which comes from `term.value`) Fix: - bind value to `updatedTerms[term.id] ?? term.value` so edits survive patches triggered by the parent Dialog opw-6431521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283514
The tour JavaScript exporter was corrected so generated tour files no longer include a URL field that had already been removed from tour definitions. This keeps exported files consistent with the current format and avoids confusion or unnecessary maintenance work.
Original PR description
The url was removed from all js file tours[1], but the exporter to JS still add it to the created JS file. This commit removes that part from the exporter. [1]: https://github.com/odoo/odoo/commit/53410a93685880b817d2b6b0ffeb7a28c254ac17 Forward-Port-Of: odoo/odoo#284427
Users auditing accounting reports can now open related journal items in all available views, not just the list view. This makes it easier to analyze report figures using formats like pivot, graph, or kanban, improving flexibility during financial review.
Original PR description
Problem: When auditing reports, the audit cell action was only showing the journal items in the list view, and not enabling other view modes (pivot, graph, kanban). Steps to reproduce: 1. Go to Accounting > Reporting > Balance Sheet 2. Click on any cell with a number in the report 3. Notice how the journal items are only shown in the list view, and you cannot switch to other view modes. Cause: The action was hardcoded to only show the list view. opw-6403704 Forward-Port-Of: odoo/enterprise#129214 Forward-Port-Of: odoo/enterprise#128563
The Point of Sale dashboard now keeps the small graph area aligned at the bottom of each card, even when cards show different amounts of information. This makes the dashboard easier to scan and gives users a more consistent visual layout.
Original PR description
In the POS config dashboard kanban view, cards could display a variable number of data lines (e.g. session dates, opening, sold, ongoing amounts, or closing date). Because the graph was placed right below the text content without vertical pushing, graphs across cards in the same row ended up vertically misaligned. Fix this by adding `d-flex flex-column` to the card template and `mt-auto` to the graph container wrapper so that graphs are always pushed to the bottom of the card, ensuring consistent alignment regardless of the number of displayed lines. task-id: 6424698 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279040
Sales order lines without a selected product now display their line name correctly in the mobile view. This prevents blank or confusing entries and makes mobile order review clearer for users.
Original PR description
Since d069ce5, users can create sale order lines without a product. Adapt the mobile view accordingly by displaying the line's name without a product image when the line has no product. Before | After -- | -- <img width="413" height="832" alt="image" src="https://github.com/user-attachments/assets/dfc7638d-c101-4fe2-b5b4-504da57ee993" /> | <img width="382" height="817" alt="image" src="https://github.com/user-attachments/assets/0a73dee9-6dfc-4a0f-89cc-b0c84e1672b5" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Message search in conversations now shows a loading spinner while results are still being fetched. This helps users understand that the search is still in progress, especially when results take longer or update progressively.
Original PR description
Before this commit, when searching messages in a conversation, the search message panel had no UI visual when the search is ongoing. This is a problem because the search can be slow and show intermediate search results from a less specific search. This commit mitigates the issue by replacing the oi-search icon into a spinner when messages search is ongoing. That way, when this is slow or showing intermediate results, there's something on the UI that hints that the search hasn't finished. Before <img width="405" height="95" alt="Screenshot 2026-08-06 at 18 02 24" src="https://github.com/user-attachments/assets/db67b5b8-9563-433a-8367-beb2cac19f26" /> After <img width="404" height="126" alt="Screenshot 2026-08-06 at 18 02 40" src="https://github.com/user-attachments/assets/dc10366a-2102-4fd5-89c9-5b8a9e35b6b5" /> Forward-Port-Of: odoo/odoo#281003
This fix prevents Belgian payroll time off allocation from failing when an employee has no working schedule configured. It adds a safeguard and tests so paid time off calculations remain reliable in more employee setup scenarios.
Original PR description
. Add check for the resource calendar before calling _get_days_per_week_for_period() method . Add corresponding tests task-6479161
The editor now ensures table merge and unmerge actions only affect cells in the table being edited. This prevents users from accidentally changing a different table when multiple tables are present in the same document.
Original PR description
Steps to reproduce: - Insert two tables in the editor. - Merge cells in the first table. - Select the merged cell in the first table. - Open the table menu for the second table. - Observe that the…
Steps to reproduce: - Insert two tables in the editor. - Merge cells in the first table. - Select the merged cell in the first table. - Open the table menu for the second table. - Observe that the "Unmerge Cells" option is available even though the second table has no merged cells. - Click "Unmerge Cells". - The merged cell in the first table is unexpectedly unmerged. Description of the issue: - The "Unmerge Cells" option is shown for the second table when a merged cell from the first table is selected. - Clicking the option unmerges the selected cell from the first table. Cause: - In `getSelectedCellsMergeInfo`, `canUnmerge` was determined using `td.rowSpan > 1 || td.colSpan > 1` without checking whether the cell belonged to the target table. Solution: - Verify that the selected cells (`td`, `firstCell`, and `lastCell`) belong to the `targetTable` before allowing merge or unmerge operations. - Prevent merge and unmerge operations from being applied to cells in a different table. task-6475293 Forward-Port-Of: odoo/odoo#283222
Point of Sale receipts now show general customer notes that are added to an order but not tied to a specific product line. This restores expected receipt behavior so staff and customers can see important order-level notes after payment.
Original PR description
## Steps to reproduce: - Go to the pos, click a product - Click the product again to unselect the line - Go to the 3 dots -> customer note - Enter a customer note, pay for the order - Try and print the receipt -> The customer note is not displayed ## Why the fix: Since the receipt REF, the general customer note was not displayed on the ticket anymore, but in was in earlier versions. When making a customer note without a selected line, we make a general one, which is not attached to a product line, so it was never displayed. We now display the general customer note if it exists, after having displayed all lines, as we did before 19.2. opw-6483621 Forward-Port-Of: odoo/odoo#284456
This fixes how Odoo identifies message attachments that are not embedded directly in the message body. It helps ensure users see the correct separate attachments in mail messages, reducing the chance of missing or misclassified files.
Original PR description
Before this commit, `extra_body_attachment_ids` is declared with `fields.Attr("ir.attachment", { compute() })`, while its compute returns the records of `attachment_ids` that the body does not inline. The model name is therefore the default of an attr field, and only a read inside an update cycle answers that string, as the compute runs on the first read outside one. No reader of the field does that today.
This commit declares the field as the `fields.Many("ir.attachment")` its compute returns, so that the declaration matches the value before the first compute as well as after.
Note that the added test asserts that a message inlining one of its two images lists only the other one, which nothing covered so far. It passes without this change.
Forward-Port-Of: odoo/odoo#284628
Forward-Port-Of: odoo/odoo#284445Invoice scanning now compares bank account numbers in the same cleaned format used by OCR. This helps the system correctly identify partner IBANs even when saved with spaces, dots, or dashes, reducing missed matches during invoice processing.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#128264 Forward-Port-Of: odoo/enterprise#127775
The meeting access test now closes the camera permission prompt before entering a guest name. This prevents a timing issue where the prompt could block the name field and cause automated checks to fail, helping keep meeting entry flows stable.
Original PR description
Before this commit, discuss.meeting_view_public_tour failed on runbot at the step typing the guest name: "It is not allowed to do action on an element that's below a modal." This happens because the welcome page opens the camera permission dialog as soon as navigator.permissions.query answers "prompt", and that answer comes at no fixed moment. The tour types the name first and closes the dialog only on the next step, so a dialog already open covers the input. This commit closes the dialog before typing the name. https://runbot.odoo.com/odoo/error/946301 Forward-Port-Of: odoo/odoo#284491
The salary offer signing page now avoids showing an oversized empty placeholder when no benefits are available. It also removes duplicate action buttons, making the review and signing experience clearer for applicants.
Original PR description
This commit fixes the issue of showing a big placeholder in the signing offer page when there was no benefits available, and also fix the duplicated buttons of "Review & Sign" and "Feedback" on the same page. taskid-6486370 Forward-Port-Of: odoo/enterprise#129008
This fix makes an automated website test wait until the selected page is fully ready before trying to delete it. This reduces random test failures, helping keep website updates more stable without changing user-facing behavior.
Original PR description
Fix the random tour failure by making sure the record is selected before trying to delete it. runbot-944542 Forward-Port-Of: odoo/odoo#280644
Very short assistant events are now fully ignored, including any project or task changes they might have carried. This prevents tiny time entries from accidentally changing the project or task used for future timesheet suggestions.
Original PR description
Before this Commit, small events (<60s) would be ignored but could still set or change the project and task of future events. After this Commit, if an event is small enough to be ignored by the assistant, it is also unable to change the current project or task of the user. For this commit to work correctly, it is expected that each event objects from the assistant has a duration value. task-[6486183](https://www.odoo.com/odoo/project/4105/tasks/6486183) Forward-Port-Of: odoo/enterprise#128700
Users can now update rental start or end dates on sale orders even if they do not have direct access to planning schedules. This avoids unnecessary errors and keeps the related planning slots aligned with the sale order changes.
Original PR description
This commit prevents a potential access error, if a user changes the rental start date and/or end date of a sale order without the access rights to the 'planning.slot' model. In this case, we want the write to be executed and changes repercuted to the associated slots. Forward-Port-Of: odoo/enterprise#128778 Forward-Port-Of: odoo/enterprise#128365
This change makes an automated test for German POS certification wait properly for order syncing before checking table status. It helps prevent random test failures, improving reliability for future updates without changing user-facing behavior.
Original PR description
Sometimes, `test_fiskaly_basic_order` test fails with the following error: ``` AssertionError: FAILED: [55/68] Tour FiskalyTour -> Step body:has(.pos-leftheader .badge:contains(5)). Element (body:has(.pos-leftheader .badge:contains(5))) has not been found. ``` `FloorScreen.clickTable()` clicks on the table and waits for a badge to appear. The badge is rendered once the table order is synced to the server. If the order is still syncing when the click on the table lands, the badge will not be present and triggers the failure. runbot-940256 Forward-Port-Of: odoo/enterprise#128998
Installing eCommerce no longer fails if a user previously deleted default product attributes such as Brand. The change lets setup safely skip missing default records, improving reliability for businesses customizing their product setup.
Original PR description
Steps to produce: --- - Install sales module. - From settings, enable variants. - Go to Sales > Products > Attributes. - Delete one of the attributes created by default (such as the "Brand"…
Steps to produce: --- - Install sales module. - From settings, enable variants. - Go to Sales > Products > Attributes. - Delete one of the attributes created by default (such as the "Brand" attribute). - Try to install the eCommerce module. Traceback: --- - `Exception: Cannot update missing record 'product.pa_brand'` Root cause: --- - The `website_sale` module attempts to append the `external_identifier` field to the default demo attributes originally created by the `product` module. If a user deletes these attributes prior to installing `website_sale`, Odoo's XML parser encounters a missing foreign record. Solution: --- - Wrapped the records in `<odoo noupdate="1">` and added `forcecreate="0"` to each `<record>`. Combining `forcecreate="0"` and `noupdate="1"` safely instructs the XML parser to gracefully skip these specific records during installation or upgrades if they are missing, preventing the traceback while still applying the external identifiers if the attributes exist. opw-6480506 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now delete multiple email templates at once without an error in Field Service Planning. This prevents an administrative task from failing when selected templates include more than one item, while still protecting the customer rating template setting.
Original PR description
Steps to reproduce: - 1. Install `planning_field_service`. 2. Open Settings > Technical > Email Templates. 3. Select two templates and delete them. Issue: - The deletion crashes with `ValueError: Expected singleton: mail.template(290, 212)`, and several templates can no longer be deleted at once. Cause: - `_unlink_customer_ratings_mail_template` guards the template configured for intervention customer ratings, but it reads `self.id`. An `@api.ondelete` hook is called once with the whole recordset being unlinked, so it raises as soon as more than one template is deleted. Fix: - Look up the configured template id in `self.ids` instead. task-6488394 Forward-Port-Of: odoo/enterprise#128905
This update simplifies a visual styling rule in the enterprise messaging area that was unnecessarily expensive to process. Users should see the same experience while the page styling is handled more efficiently.
Original PR description
This PR cleans up a complex selector that is quite costly without providing any striking visual value. task-6481656 Forward-Port-Of: odoo/enterprise#128906
Users can now open links included in spreadsheet cell comments with a normal click, as expected. This fixes a small but visible usability issue that previously made shared links in comments harder to access.
Original PR description
Current behavior before PR: - Clicking a link in a cell comment did not work. A left click was blocked, while Ctrl+click (or Cmd+click) opened the link in a new tab. - This was caused by `t-on-click.prevent` on the comment thread and popover. It was originally added because the scroller service used the URL hash to scroll to anchors, which was removed in https://github.com/odoo/odoo/commit/711e9c9f24818714129f55283e2df64503d93605 Desired behavior after PR is merged: - `t-on-click.prevent` is removed and links in cell comments can be opened normally with both left click and Ctrl+click (Cmd+click on macOS). Task: [6448651](https://www.odoo.com/odoo/project/2328/tasks/6448651) Forward-Port-Of: odoo/enterprise#129188 Forward-Port-Of: odoo/enterprise#127473
The Japanese localization now uses accurate fiscal position names, correcting an incorrect translation for domestic partners. It also fixes an English spelling mistake and simplifies the wording, reducing confusion for users setting up Japanese accounting rules.
Original PR description
Japanese translation "海外取引先" for domestic was clearly wrong.
Also fixed the misspelling ("Oversea" -> "Overseas") and removed the unnecessary "Customer" context from the name.
@qrtl
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#284608