Thursday, July 30, 2026
15 changes · 19.0
Resolved issues and error corrections
The mail composer now respects when a user closes the suggestion menu with Escape. This prevents the menu from reopening due to unrelated background updates, so the next Escape key press can perform the expected composer action such as discarding a reply.
Original PR description
Before this commit, the composer suggestion list could re-open right after the user closed it with Escape, and the next press of Escape would then close the list again instead of being handled by the composer (e.g. discarding a reply). This happened because NavigableList was re-opened on every patch: the useEffect opening the list had `[this.props]` as dependency, and props are a new object on every render. Any unrelated re-render of the composer (e.g. triggered by a late store update) would therefore re-open the list, which would then steal the next Escape from the composer. Fix by narrowing the dependency to the content of the options, so the list only opens on mount and when a new set of options arrives. https://runbot.odoo.com/odoo/error/944571
Fixes an issue where deleting a message could fail for users who had never opened or read messages in that channel. This keeps mail discussions more reliable and prevents disruption when cleaning up messages.
Original PR description
The mail.message/delete bus handler accessed selfMember?.seen_message_id.id with optional chaining only on selfMember, not on seen_message_id. When a member has never seen any message in a channel (seen_message_id is False), accessing .id threw 'TypeError: can't access property id, selfMember.seen_message_id is undefined', breaking message deletion for that user (e.g. deleting a message in a channel the user never opened. Add optional chaining on seen_message_id so the unread counter is simply not decremented when no message has been seen yet. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278073 Forward-Port-Of: odoo/odoo#277417
This fixes an issue where selecting image padding in Studio reports could close the menu before the choice was applied. Users can now adjust image spacing in reports without needing repeat attempts or workarounds.
Original PR description
Problem: Clicking an image padding option in Studio reports closes the dropdown, but the selected option is not applied. Cause: When editing inside an `iframe`, `unFocusEditable` is triggered on `focusin`, which runs `selection_leave_handlers` and closes the dropdown before the `click` event can propagate. Solution: Add `data-prevent-closing-overlay="true"` to the image padding dropdown, as done for other dropdowns, so it remains open until the click event is handled. Steps to reproduce: - Open a new report. - Add an image. - Select the image. - Open the padding dropdown. - Click a padding option. - Observe that the dropdown closes but the padding is not applied. task-6368964 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276448
Clicking a heading in a table of contents no longer causes an error when the editor area cannot scroll. This keeps navigation and highlighting working reliably in To-Do content and other editor views.
Original PR description
**Current behavior before PR:** Steps to reproduce the issue: - Go to a To-Do. - Insert a heading, write something. - Insert a table of content. - Make sure that editable is not scrollable. Clicking on heading label inside toc leads to traceback. The issue occurs after merging commit [1]. When editable is not scrollable then `closestScrollableY` returns null which leads to traceback. **Desired behavior after PR:** If editable is not scrollable then clicking on heading inside toc should hightlight the corresponding heading without traceback. [1]: https://github.com/odoo/odoo/commit/f5cf8565e7d09edd3a29fd95537381fb70d75785 task-6405894 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277657
The website editor now shows the correct preview when changing heading colors in theme color presets. This helps users confidently customize website themes because the preview reflects the selected colors accurately.
Original PR description
Steps to reproduce: - Go to Edit mode - Go to the Theme tab - Open a color preset to customize it - Change the "Headings" color => The color of "Title" did not change in the preview By changing the tag from "h3" to "h1", the color in the preview is now correctly updated in the theme tab. "fs-4" is added to keep the previous size. task-6299680 Forward-Port-Of: odoo/odoo#278056
This fixes an intermittent failure in an automated mail test by waiting until the needed contact option is ready before selecting it. The change helps keep validation runs stable and reduces false failures during development and release checks.
Original PR description
**Issue:** `test_mail_template_dynamic_placeholder_tour` tour is failing sometimes with the following error: `Tour mail_template_dynamic_field_tour → Step Click on contact (trigger: div[name="model_id"] .ui-autocomplete). TypeError: Cannot read properties of undefined (reading 'click')` **Cause:** It happens that the element is not loaded yet after the delay and clicking on an undefined element triggers the error. **Solution:** Make sure to only click on the element when it's ready. runbot-223306 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277954
This fix ensures navigation-related cleanup always happens, even when a screen is prepared but never shown. It helps prevent small memory leaks that could gradually affect browser performance during cancelled page rendering.
Original PR description
The navigator class, which adds event handlers, is instanciated on the setup of components using the useNavigation hook. However, before this commit, it was destroyed when the components were unmounted. It may happen that components are instanciated (setup is executed) but never mounted in the DOM, when the current rendering is cancelled. When this happened, the navigator cleanup wasn't executed, resulting in a small memory leak. This commit fixes the issue by using onWillDestroy instead. 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 fixes how Peppol error messages are selected so the system uses the supported method in current and future Odoo versions. It helps avoid failures or confusing messages when handling Peppol-related account documents.
Original PR description
The fw-ports of https://github.com/odoo/odoo/pull/269465 incorrectly use _get_peppol_error_message, which is depreciated from 19.0 and even removed in subsequent versions (at least 19.4 and master). It now uses the correct get_peppol_error_message static method.
Fixes an issue where adding a slide to a website carousel in edit mode could trigger an error and interrupt the editing experience. The editor now reuses the correct carousel component inside the page preview, making carousel edits more stable.
Original PR description
Steps to reproduce: - Edit a page. - Drop a carousel snippet like s_quotes_carousel - Click "Add Slide" with the browser console open(for concrete race condition) => Traceback: TypeError: Cannot read properties of null (reading 'classList') Cause: `slide()` used the editor window's `Carousel` instead of the iframe's. This created a second Carousel instance for the same element. Both instances updated the indicators at the same time, causing one to remove the active indicator before the other tried to use it, leading to the traceback. Fix: Use `this.window.Carousel` so the iframe's existing Carousel instance is reused instead of creating a second one. task-6084484 Forward-Port-Of: odoo/odoo#275903
Swiss employee payslips now show the contract withdrawal date instead of a related version end date. This prevents incorrect departure information when the two dates differ, improving payroll document accuracy.
Original PR description
The Withdrawal Date in the payslip of CH employees was printing the date_end relative to the version related to the payslip. Instead, it should print the end of the contract of that version, since they can be different. The end date of the contract is in l10n_ch_withdrawal. Task: 6398291 Forward-Port-Of: odoo/enterprise#124848
This fix prevents Swiss BVG-LPP pension fund numbers from being included in status check requests. It helps ensure payroll declaration status queries use the expected information and avoid errors with Swiss payroll processing.
Original PR description
Forward-Port-Of: odoo/enterprise#126040
Studio report editing now keeps a paragraph in place when its last character is deleted. This prevents unintended layout changes and makes report editing more predictable for users.
Original PR description
Problem: In Studio reports, deleting the last character of a paragraph removes the entire paragraph. Cause: `cleanEmptyStructuralContainers` removes the empty paragraph because it is considered empty. Solution: Disable `cleanEmptyStructuralContainers` for reports same as website builder. Steps to reproduce: - Create a new report. - Add multiple paragraphs. - Leave one paragraph with a single character. - Delete the character. - Observe that the paragraph is removed. task-6368965 Forward-Port-Of: odoo/enterprise#124834
The Timesheets overtime indicator now keeps the selected unit, such as days, even when users switch to another language. This prevents employees and managers from seeing misleading remaining-time values caused by translated unit names.
Original PR description
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet…
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet in the past week for this employee (e.g. 8 hours). 4. Observe the overtime indicator for the employee (it shows 32 hrs) (Click the left arrow to display it). 5. Change the timesheet encoding unit to "Days / Half-Days". 6. Return to Timesheets and observe the overtime indicator (it now correctly shows 4 days). 7. Install a language other than English (e.g. French). 8. Return to Timesheets and observe the overtime indicator again. Issue: -------- The remaining time value changes unexpectedly and displays 32 hours instead of 4 days. Cause: --------- In `get_timesheet_and_working_hours_for_employees`, the code determines whether the timesheet UoM is expressed in days by comparing the UoM name with the string `"days"`. Since UoM names are translatable, this comparison becomes invalid when the user language changes (e.g. `"jours"` in French), causing the logic to skip the day conversion and return values in hours instead. https://github.com/odoo/enterprise/blob/c48290e90fdeadf4f9ca8c44b035e601e7ed380a/timesheet_grid/models/hr_employee.py#L165-L169 Solution: ----------- Compare the timesheet UoM record with the day UoM record directly instead of relying on translated string values. see commit: https://github.com/odoo/enterprise/commit/5fbf194c5056566453a124812fd2614edfe19a82 opw-6279133 Forward-Port-Of: odoo/enterprise#125909 Forward-Port-Of: odoo/enterprise#120595
This fixes an issue where clicking analytic plan amounts in the trial balance could fail because the action data was in the wrong format. Users can now drill into the related analytic entries as expected, reducing disruption when reviewing financial reports.
Original PR description
To reproduce (in master, didn't test the earliest but it's not in 17.0):
- Open the trial balance
- Set the Analytic Plans to one plan
- Click on a cell inside the columns of the plan
Using odoo shell in 17.0:
```
>>> from odoo.addons.web.controllers.utils import clean_action
>>> action = clean_action(self.env.ref('analytic.account_analytic_line_action_entries')._get_action_dict(), env=self.env)
>>> type(action['context'])
<class 'str'>
```Belgian Blackbox POS configurations can no longer have their POS ID changed while a sales session is open. This prevents inconsistent compliance settings during active operations and aligns the POS ID behavior with existing Blackbox restrictions.
Original PR description
Just like the Blackbox cannot be changed on a POS config with an open session, the POS ID should not be changeable either.