Wednesday, September 9, 2026
23 changes · saas-18.3
Enhancements to existing features
Odoo now has a cleaner way to refresh or shut down messaging data in the background, helping avoid stale information and test side effects. This prepares live chat and mail features to recover more reliably if updates are missed for an extended period.
Original PR description
This commit adds `store.destroy()` to cleanly destroy the store, including ongoing reactive observers. This is useful to make sure no side-effect store among HOOT tests This commit adds `store.reset()`, to make the store fresh as at page load. This is in preparation to make store reset in case we miss notifications for a long time. https://github.com/odoo/enterprise/pull/85615
This update improves how messaging data is cleared and rebuilt in the background, helping keep chat and AI assistant interfaces consistent after resets or page changes. It also fixes related Web Studio test coverage to ensure report editing behavior remains stable.
Original PR description
https://github.com/odoo/odoo/pull/210139
Resolved issues and error corrections
The warning shown when users try to edit properties before a required product category or definition is set now explains the real problem instead of showing "undefined". This helps users understand what must be completed first and reduces confusion during product setup.
Original PR description
Versions -------- - saas-18.3+ Steps ----- 1. Create a new product without a category; 2. try to edit properties. Issue ----- You get the following warning notification: > Oops! You cannot edit the Product Category "undefined". > [!note] > If `account_asset` is installed, the warning will remain empty until https://github.com/odoo/enterprise/pull/94583 is merged. Solution -------- The property cannot be edited because the definition record doesn't have a value. By checking if `this.defenitionRecordId` is unset, we can display a clearer warning message that the field has to be defined first. opw-4980006
This fixes an issue where users could not update line descriptions on confirmed purchase orders when the product column was visible. The change makes description editing consistent across purchase order views, reducing confusion and avoiding unnecessary workarounds.
Original PR description
Steps to reproduce the bug: - Create and Confirm a purchase order with any product and a description (name) on the order line - Try to edit the description (name) field Problem: The description field…
Steps to reproduce the bug:
- Create and Confirm a purchase order with any product and a description (name) on the order line
- Try to edit the description (name) field
Problem:
The description field was not editable on a confirmed purchase order when the product_id column was visible, but became editable when product_id was hidden.
The `ProductLabelSectionAndNoteField` widget renders both `product_id` and the description (`name`) in a single cell. When `props.readonly` is true (because `product_id` has `readonly="state in ('purchase', 'to approve', 'done', 'cancel')"`) and the order state is not draft (`isProductClickable` is true), the template rendered the description textarea with a hardcoded `readonly="1"` attribute, making it impossible to edit regardless of the actual intended readonly state for the description.
When `product_id` was column-invisible, the `name` field rendered via its own `section_and_note_text` widget, which correctly used `sectionAndNoteIsReadonly` (blocking only `cancel`, `done`, `posted`) hence the inconsistency.
Solution:
Replace `readonly="1"` with `t-att-readonly="sectionAndNoteIsReadonly"` on the description textarea so its editability follows the same logic as the other cases: blocked only for terminal states (`cancel`, `done`, `posted`), not for `purchase` or `to approve`.
opw-5474986
Forward-Port-Of: odoo/odoo#272102Kitchen orders in setups with fewer than three stages now record completion time based only on preparation time. This prevents inflated timing data when staff complete multiple order lines one by one, improving the accuracy of kitchen performance reporting.
Original PR description
Kitchens with fewer than 3 stages were incorrectly recording both preparation and service time. Completion time should only include preparation time in this case. Steps to reproduce: - Configure the kitchen to have only 2 stages - Create an order with more than 1 order line - Mark the order lines as completed one by one - Observe that the completion time is calculated incorrectly opw-6515078
New company cars created through the Belgian Salary Configurator will no longer have the “Make vehicle available” option selected automatically. This prevents cars ordered for incoming employees from being incorrectly treated as available in Fleet, reducing confusion and manual correction.
Original PR description
Steps to reproduce: - Install the Salary Configurator (Belgium) module - Create a new offer in the recruitment process. - Open the salary configurator and select a company car to order. - Fill in all other necessary details and sign the contract. - Navigate to the fleet module and locate the newly created car for new employee Issue - The "Make vehicle available" checkbox is incorrectly checked by default for the newly created company car. Reason: - The create method contains code that writes values for plan_to_change_bike and plan_to_change_car, which causes the 'Make vehicle Available' to be checked Solution - Remove the code that writes to plan_to_change_bike and plan_to_change_car in the create method to prevent the vehicle from being marked available by default. task-4868865
This fix prevents automated tests from unpredictably changing user session data during login checks. It keeps test runs more stable and reduces false failures, without changing normal customer-facing behavior.
Original PR description
The test harness patches the CryptContext object to spend less time hashing to decrease total test runtime. Because the hash parameters have changed, every first login (per transaction) per user will result in a hash rotation. The session_id is also rotated when the password hash rotates. When multiple requests are sent to the server while a session rotation is underway, the session datastore holds either a valid, or expired, or logged-out user session. This is a source of indeterminism in tests that can be prevented by always returning None value for replacement hash. REF Runbot; https://runbot.odoo.com/odoo/error/242811 REF Runbot; https://runbot.odoo.com/odoo/error/233722 Forward-Port-Of: odoo/odoo#285710
This update addresses a problem in the Spreadsheet area to improve how the spreadsheet interface behaves or appears. It helps provide a smoother and more reliable experience for users working with spreadsheets in Odoo.
Original PR description
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
This update adjusts the Spreadsheet app’s front-end files to support a testing-related fix. It helps improve reliability around spreadsheet behavior without introducing a major user-facing change.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects how spreadsheet pivot tokens are handled, helping spreadsheet views work more reliably. It affects the Spreadsheet app interface and styling, with a limited user-facing impact focused on preventing a specific issue.
Original PR description
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
This fixes a live chat issue where operators could not leave a conversation after the visitor had already left. Ended chats are now properly marked as read, so the interface shows the leave option instead of an unread badge.
Original PR description
**Current behavior before PR:** When an operator accessed a live chat where the visitor had left, the composer was disabled, preventing `markAsRead()` from executing and showing the unread message counter badge instead of the leave action. **Desired behavior after PR is merged:** `markAsRead()` is now called on ended live chat, ensuring that operator can leave the channel. **Task**-4500402 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents accounting reports from being incorrectly nested inside other report sections during upgrades or configuration changes. It helps keep custom financial reports organized correctly and avoids confusing duplicated or nested report structures for users.
Original PR description
Case: - Custom report has sections and is not root - Root report is added as a section to another report. For example here: https://github.com/odoo/enterprise/blob/saas-18.3/account_reports/data/annual_statements.xml#L8 Example before the upgrade to 18.3: ``` yaih@(none):yaih_3038736> SELECT ar.id FROM account_report ar JOIN ir_model_data imd ON imd.res_id = ar.root_report_id where imd.name = 'balance_sheet' +----+ | id | |----| | 26 | | 21 | +----+ SELECT 2 Time: 0.009s yaih@(none):yaih_3038736> SELECT * FROM account_report_section_rel +----------------+---------------+ | main_report_id | sub_report_id | |----------------+---------------| | 26 | 21 | | 26 | 20 | +----------------+---------------+ ```
Point of Sale users can now open the app without running into an access error when an optional installation request component is not installed. This prevents unnecessary disruption for employees who have Point of Sale permissions but do not have administrator settings access.
Original PR description
Fixes https://github.com/odoo/odoo/issues/238503 Avoid access error if `base_install_request` is not installed Example use case: - Install point_of_sale (without having `base_install_request` installed) - Give user Marc Demo Point of Point of Sale permission but NOT Administration > Settings - Go to Point of Sale ``` Access Error You are not allowed to access 'Module' (ir.module.module) records. This operation is allowed for the following groups: - Administration/Settings Contact your administrator to request access if necessary ``` Please @pedrobaeza and @christian-ramos-tecnativa can you review it? @Tecnativa TT57146 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#240587
This update ensures demo Drawer and Flipover products receive the required lot numbering setup when inventory-related demo data is installed. It prevents an error during receipt validation, so users can generate serial or lot numbers for these products without interruption.
Original PR description
Issue before this commit: ========================= When generating a lot number for a Drawer/Flipover and validating the operation, a traceback is raised: "ValueError: Expected singleton:…
Issue before this commit: ========================= When generating a lot number for a Drawer/Flipover and validating the operation, a traceback is raised: "ValueError: Expected singleton: ir.sequence()" Steps to Reproduce: ========================= - Install the "stock" module. - Create a receipt for the drawer product. - Open the detailed operations wizard. - Click on "Generate Serials/Lots". - Enter the first lot/serial number. Validate it. Result: A traceback is raised with: ValueError: Expected singleton: ir.sequence() Cause of the issue: ========================= The 'lot_sequence_id' field is defined in the 'stock' module with a default value. However, defaults are only applied at record creation time. When the drawer is initially created by the product module, the lot_sequence_id field does not exist yet. Later, when the stock module is installed, the existing drawer is configured to be tracked by lot via demo data. Since the drawer already exists, the default value for lot_sequence_id is not applied, leaving the field unset. The lot_sequence_id field is added in this [PR](https://github.com/odoo/odoo/pull/200395), but the issue occurs on [the line](https://github.com/odoo/odoo/blob/saas-18.3/addons/stock/models/stock_move.py#L1026) introduced in [this PR](https://github.com/odoo/odoo/pull/240368). The code attempts to call get_next_char() on lot_sequence_id while it is still unset (False), resulting in the method being called on an empty recordset. As a result, serial/lot number generation fails due to a missing sequence. Same issue for Flipover. With This Commit: ========================= Ensure that the existing drawer product tracked by lot is assigned a default lot_sequence_id when the stock module is installed. This guarantees consistent and correct lot generation for the drawer/Flipover.
This fixes an issue where keyboard shortcuts could apply formatting to parts of a page that are not meant to support rich text editing, even though the toolbar was disabled. It helps keep blog header and footer content consistent and prevents accidental styling changes in restricted fields.
Original PR description
Problem: Selecting text in non-html fields disables toolbar formatting, but pressing CTRL+B still formats the text. Cause: `formatSelection` did not check if the selection was inside a non-html field before applying formats. Solution: Return early in `formatSelection` if the selection is inside a non-html model field element. Steps to reproduce: 1. Go to /blog and open an article. 2. Open editor and select header/footer text. 3. Press CTRL+B. => Selected text becomes bold. opw-6537402 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286675
This fix ensures the alternative mode labels in the AI Copywriter dialog are shown in the user's selected language. It improves consistency for multilingual users and makes the writing assistant easier to use outside English.
Original PR description
Description of the issue/feature this PR addresses: The alternativemodes on the AI Copywriter dialog are not translated Current behavior before PR: <img width="1079" height="250" alt="image" src="https://github.com/user-attachments/assets/fced9432-b557-44de-9b7c-a31547b7a16b" /> Desired behavior after PR is merged: <img width="1078" height="250" alt="image" src="https://github.com/user-attachments/assets/1499836a-924e-425c-b328-27a378eae62a" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230740
A typo in the Helpdesk “Auto Assignment” group name was corrected. This improves clarity for users and administrators when viewing or managing Helpdesk settings.
Original PR description
This commit fixes the typo in the "Auto Assignment" group. task-6542450 Forward-Port-Of: odoo/enterprise#130841
Users can now reliably remove text or background colors even when the color was applied higher up in the content structure, such as in lists, buttons, or table cells. This makes the formatting toolbar behave correctly and reduces frustration when cleaning up styled content.
Original PR description
#### Description of the issue this PR addresses: - Color detection only checked the closest element of the selected text nodes, assuming the color is always applied on their direct parent. - This is…
#### Description of the issue this PR addresses: - Color detection only checked the closest element of the selected text nodes, assuming the color is always applied on their direct parent. - This is not always the case: the color can be applied on a `<font>` wrapping an inline element (e.g. a neutral style `<span>` created inside button links), or on the list item itself when its content is wrapped in a block (e.g. a heading). - As a result, remove format could not remove such colors, and its toolbar button stayed disabled as no color was detected for the selection. #### Desired behavior after PR is merged: - Introduce the `closestColoredElement` util, which returns the element actually applying the color to a node by looking up its ancestors. - The lookup stops on an element resetting the color of its content (`style="color: initial"`), as there is nothing to remove above it. It is also limited to the closest paragraph related element, or to the closest list item (color) or table cell (background color), as those can hold the color of a text nested deeper in them. - Use it for the remove format detection, and to get the `<font>` to clean when removing a color: the closest one is not necessarily the one applying it, e.g. a `<font>` with a background color nested in a `<font>` with a text color. task-6312677 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Demo products used in helpdesk stock and rental flows now receive the needed lot/serial number sequence when their demo data is installed. This prevents an error when users generate and validate serial or lot numbers for products like Cabinet with Doors or Printer.
Original PR description
Issue before this commit: ========================= When generating a lot number for a Cabinet with Doors/Printer and validating the operation, a traceback is raised: "ValueError: Expected singleton:…
Issue before this commit: ========================= When generating a lot number for a Cabinet with Doors/Printer and validating the operation, a traceback is raised: "ValueError: Expected singleton: ir.sequence()" Steps to Reproduce: ========================= - Install the "helpdesk_stock" module. - Create a receipt for the Cabinet with Doors product. - Open the detailed operations wizard. - Click on "Generate Serials/Lots". - Enter the first lot/serial number. Validate it. Result: A traceback is raised with: ValueError: Expected singleton: ir.sequence() Cause of the issue: ========================= The 'lot_sequence_id' field is defined in the 'stock' module with a default value. However, defaults are only applied at record creation time. When the Cabinet with Doors is initially created by the product module, the lot_sequence_id field does not exist yet. Later, when the helpdesk_stock module is installed, the existing Cabinet with Doors is configured to be tracked by lot/serial via demo data. Since the Cabinet with Doors already exists, the default value for lot_sequence_id is not applied, leaving the field unset. The lot_sequence_id field is added in this [PR](https://github.com/odoo/odoo/pull/200395), but the issue occurs on [the line](https://github.com/odoo/odoo/blob/saas-18.3/addons/stock/models/stock_move.py#L1026) introduced in [this PR](https://github.com/odoo/odoo/pull/240368). The code attempts to call get_next_char() on lot_sequence_id while it is still unset (False), resulting in the method being called on an empty recordset. As a result, serial/lot number generation fails due to a missing sequence. Same issue for the printer. With This Commit: ========================= Ensure that the existing Cabinet with Doors/Printer product, tracked by serial/lot is assigned a default lot_sequence_id when the helpdesk_stock module is installed. This guarantees consistent and correct lot generation for the drawer.
The Planning schedule email template now shows the “View Your Planning” button with a default color when viewed in read-only mode. This makes the call-to-action clear in template previews while still allowing company-specific colors to apply when emails are sent.
Original PR description
Steps to reproduce: - Install Planning - Open email templates - Open Planning New Schedule template Issue: - `View Your Planning` button doesnt have any color and doesnt seem like a button. Cause: - Earlier the colors we hard-coded, now they are applied dynamically using button color set on company settings. - As t-attf is evaluated during read-only render we are not able to see the color. Fix: - Set default color of button as Purple to be visible in read-only mode. - Have dynamically added colors override default colors using `!important`. task-5064862
After validating an OTP during GSTR1 submission, the confirmation wizard now closes automatically. This removes an unnecessary manual step and makes the GST filing flow smoother for users.
Original PR description
Steps to Reproduce: 1. Open the GST Return Period page 2. Click on Push to GSTN 3. Re-initiate → Send OTP → Validate OTP Issue: - After OTP validation, the wizard does not close automatically. Root Cause: - The method button_send_gstr1 and action_get_irn_data were returning 'type': 'ir.actions.client' instead of 'type': 'ir.actions.act_window_close'. Fix: - Updated the button_send_gstr1 and action_get_irn_data methods to return 'type': 'ir.actions.act_window_close' to ensure the wizard closes properly after OTP validation.
A product used in a Mexican point-of-sale refund test is now marked as available for POS, so it appears correctly when paid orders are loaded. This keeps the refund discount scenario reliable and prevents false test failures.
Original PR description
Before this commit: * `available_in_pos` was not set on the product in the test, causing it to be missing from the ticket screen when fetching paid orders using `callRelated`. After this commit: * Set `available_in_pos` on the product so it is loaded correctly and appears in the ticket screen when fetching paid orders, fixes test case `test_mx_pos_refund_discount_order`. task-5890998 related pr: https://github.com/odoo/odoo/pull/247127 Forward-Port-Of: odoo/enterprise#128730
This fix makes an internal time off accrual test use fixed dates instead of dates based on the day the test runs. It prevents false test failures when the calculated date falls on a non-working day, improving release reliability without changing employee-facing behavior.
Original PR description
## Before: The test relied on relative dates (today + 2 days) when creating a leave request. The behavior depended on the day it was executed. For example, if the test ran on a Friday, the leave request would be created for Sunday, causing the validation to fail because the employee was not supposed to work on that day. ## After: This uses a static date for both the accrual allocation and creating the leave to avoid unnecessary errors. runbot-945745 Forward-Port-Of: odoo/odoo#282190