Wednesday, June 3, 2026
26 changes · saas-19.2
New functionality added to Odoo
This update enhances the Odoo Enterprise payroll system by allowing for more flexible adjustments to individual payslip lines. This change improves the accuracy and customization of payroll calculations for employees. The update modifies related models and views to support these new editing capabilities.
Resolved issues and error corrections
This update fixes an issue where users couldn't reliably select formatted text within a table cell. The fix simplifies the selection process by directly verifying cell boundaries, ensuring consistent and accurate cell selection across the HTML editor. This enhances the user experience when working with tables.
Original PR description
### Steps to reproduce: - create a table (e.g. /table) - type something in any cell and select that cell. - apply formatting through toolbar (bold, italic, etc.) - now select that single cell through…
### Steps to reproduce: - create a table (e.g. /table) - type something in any cell and select that cell. - apply formatting through toolbar (bold, italic, etc.) - now select that single cell through mouse. - observe that it is not selected ### Description of the issue/feature this PR addresses: - The single-cell selection logic relied on getTargetedNodes(), which collects descendants of the selection’s common ancestor. When selecting text inside inline formatting tag (e.g. `<i>`), the text node became the common ancestor, so the parent `<i>` tag was excluded from selectedNodes. As a result, check ensuring all cell elements were selected failed, preventing from being selected. ### Desired behavior after PR is merged: - Cell selection was simplified using areNodeContentsFullySelected(startTd) directly instead of manually matching targeted descendants. This relies on DOM Range to verify whether the cell boundaries are fully selected. task-6207941 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266208 Forward-Port-Of: odoo/odoo#263742
Features or functions removed from Odoo
This update removes a reference to 'Peppol' from the French Payroll (l10n_fr_pdp) module. This change simplifies the configuration process and aligns with current regulatory requirements for French businesses. It ensures clarity and avoids potential confusion for users.
Original PR description
task-None Forward-Port-Of: odoo/odoo#267650
This update optimizes the styling of the Odoo Enterprise home menu by replacing inefficient CSS selectors with CSS variables. This change improves page loading speed and overall performance, leading to a smoother user experience. The update addresses a performance issue related to hover and active states.
Original PR description
Avoid selectors after `:hover` and `:active`, as they can impact performance. CSS variables are now used instead. Replace hex color values with "0 0 0" RGB syntax to ensure compatibility with CSS variable usage. Forward-Port-Of: odoo/enterprise#119082
This update resolves an issue where clicking on binary data within a list view would also open the associated record. We've implemented a change to prevent this automatic opening, ensuring users only download the desired file content. Unit tests have been added to guarantee this fix.
Original PR description
If a list view contains a field (column) with binary widget, on click it will download the content of the field. This is the intended behavior but at the same time it will, by default, open the record of which it is part, which is strange since the user only wants to download the content. With this PR we make use of .stop on the t-on-click to detach the execution of the function from the opening of the record. We also add unit tests for this. Task: 6260266 Forward-Port-Of: odoo/odoo#267197
This update fixes an issue where timesheet forms weren't loading correctly after refreshing a page. Now, when you view a timesheet entry, the correct, detailed form view is displayed, ensuring accurate data access. This improves the user experience for timesheet management.
Original PR description
…m view * Go to Timesheets > My Timesheets > switch to Grid view. * Hover over a cell with a timesheet entry and click the magnifier (search) icon. * The list opens; click a record to open its form view. * Observe the URL: `/odoo/timesheets/account.analytic.line/<id>`. * Refresh the page (F5). Before this commit, the generic form view was shown instead of the timesheet-specific form view. This occurred because, when reloading a page with a dynamic action and a resId, a generic view layout [false, "form"] was requested instead of the action-defined view. Now, the dynamic action is properly restored on refresh, ensuring the correct specific view is loaded for the form. opw-6133602 Forward-Port-Of: odoo/odoo#266369 Forward-Port-Of: odoo/odoo#265552
This update optimizes how Odoo recalculates styles in large tables, like the Accounting > Balances Sheets. By using a more targeted approach, the system now responds faster during window resizing, scrolling, and sorting, leading to a smoother user experience. This change improves overall performance and responsiveness.
Original PR description
Avoid using the :has() selector and use a specific class on the body instead to replicate the same behavior. This reduces work during the "Recalculate Style" phase (for example when hovering rows in large tables such as the Accounting > Balances Sheets). It lowers recalculation time during window resizes, heavy scrolling, and table sorting by preventing broad selector matches and limiting style checks to elements with the specific class. 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#267602 Forward-Port-Of: odoo/odoo#267170
This update resolves an issue where the Documents app incorrectly displayed a duplicate PDF preview when receiving XML attachments via email. The fix ensures that the preview accurately shows the PDF content, addressing a visual inconsistency. This improvement enhances the user experience when accessing documents from email.
Original PR description
**Steps to reproduce:** - Install documents_account - Set up alias to catch incoming mails - Receive a mail with xml attachement which can be previewed as pdf - Go to Documents app - Click on the…
**Steps to reproduce:** - Install documents_account - Set up alias to catch incoming mails - Receive a mail with xml attachement which can be previewed as pdf - Go to Documents app - Click on the document preview - Preview is split in two iframes, both with the same content (pdf) **Issue:** Due to the `isPdf` patch the attachment can match multiple types for the preview (pdf and text) as both getter return `true`. ``` <iframe t-if="state.file.isPdf" ... <iframe t-if="state.file.isText" ... ``` It also seems that xml received by mail are imported as text, which is why the issue doesn't happen when manually uploading the same xml file. **Fix:** Ensure that if the document is matching `isPdf`, it doesn't trigger the second iframe with `isText`. Also it seems fixed in 19.0 as the text iframe is replaced by this xpath: `<xpath expr="//iframe[@t-if='state.file.isText']" position="replace">` which was added for https://github.com/odoo/enterprise/commit/de614ee5e9a087d49939c65c0118ae6164c7b31b related patch: https://github.com/odoo/enterprise/commit/ffcdd2275c8bf564e15151ccbcaf3965ed968450 opw-6018536 Forward-Port-Of: odoo/enterprise#118041 Forward-Port-Of: odoo/enterprise#112041
This update fixes a bug in the helpdesk rating dashboard. Previously, ratings created late in the day weren't accurately reflected in searches. The change now uses the current date and time for searching, ensuring all recent ratings are included in the dashboard view.
Original PR description
Before this commit, the ratings created the current date at 23h will not been taken into account in helpdesk rating dashboard. This commit uses datetime.now() instead of date.today() to search the ratings in the last 7 seven days. runbot-error-230905 Forward-Port-Of: odoo/enterprise#119035
This update resolves a situation where users would receive warnings related to the Italian EDI (SdI) functionality even when it wasn't applicable. Now, the system only displays these warnings when the company is actually configured for Italian EDI processing, ensuring a cleaner user experience.
Original PR description
We shouldn't show warnings for `l10n_it_edi` if it's not possible to use it, even if the partner has its preferred EDI method set as `it_edi_xml`. Ticket [link](https://www.odoo.com/odoo/project.task/5985570) opw-5985570 Forward-Port-Of: odoo/odoo#267019
This update resolves a visual issue in the Gantt holiday view, specifically a problematic background color in dark mode. It also corrects a previous issue where the selection of holidays was incorrectly counting records instead of the number of selected cells, ensuring accurate holiday management.
Original PR description
- changed selected value in the view to be number of selected cells instead of number of selected records - fixed a visual bug in dark mode where the create popup has ugly background task-id: 6124765
This update corrects a recent change that unintentionally removed a styling class from all dynamic website snippets. The previous fix, intended for mono-record snippets, was too broad. This commit restores the correct styling for all dynamic snippets, ensuring consistent layout and appearance on the website.
Original PR description
Before [1], the `s_dynamic_snippet_row` class was added to all dynamic snippets using the `website.s_dynamic_snippet.grid` template and defining `columnClasses` values. In [1], a fix was introduced to prevent adding this class on mono-record snippets, as it was breaking the layout when used inside small containers (`o_container_small`). However, the condition introduced by that fix is too broad and currently removes the class from all dynamic snippets. This commit fixes the condition so that `s_dynamic_snippet_row` is only excluded from mono-record snippets, restoring the intended layout for other dynamic snippets. [1]: https://github.com/odoo/odoo/commit/fe2279f760adc6a53ba2242961f3873a5d3215dd Forward-Port-Of: odoo/odoo#265362 Forward-Port-Of: odoo/odoo#264407
This update fixes a limitation in how analytics data is managed for assets. It now allows users to simultaneously edit multiple analytics distribution values within the asset form, mirroring the functionality available for journal items. This streamlines the process of updating and analyzing asset performance data.
Original PR description
This commit fixes the multi-edit of analytics distribution field in assets form view. The multi-edit option was added to the analytics distribution widget, same as in the journal items. task-6218188 Forward-Port-Of: odoo/enterprise#119054 Forward-Port-Of: odoo/enterprise#118042
This update fixes an issue where multiple lines of text were being converted into separate code or quote blocks instead of a single block. The fix ensures that selecting multiple lines and changing the block type results in a unified code or quote block, improving the editor's functionality and consistency.
Original PR description
Steps to reproduce: - Write multiple lines of text. - Select all lines. - Change block type from Normal to Code (or Quote) via the toolbar. Description of the issue: - Notice that each line is now a separate code block (or quote). Cause: - The `setBlock` method currently converts each selected block individually into the target block type, creating multiple blocks when multiple lines are selected. Solution: - For code and quote blocks, `setBlock` now converts only the first selected block into the target type and merges the content of the other selected blocks into it, ensuring a single code/quote block. task-6068930 Forward-Port-Of: odoo/odoo#258331
This update resolves a technical error that occurred when PL companies attempted to pay non-VAT PL suppliers with invoices exceeding 15,000 PLN. The fix prevents unnecessary verification processes, ensuring smoother payment processing for these suppliers. This improves the reliability of the bank verification system.
Original PR description
[FIX] l10n_pl_bank_verification: PL Supplier no VAT When a PL supplier has no VAT and a PL company tries to pay him a bill above 15.000 PLN, there is a traceback. The reason is that there was no check for partner with no VAT, a verification was created every time the field was compute. Forward-Port-Of: odoo/odoo#266878
This update strengthens Odoo.com's subscription verification process by adding a check for duplicated SAAS databases that have been neutralized. Previously, test databases could incorrectly pass subscription checks, leading to potential issues. This change ensures accurate subscription validation for all Odoo.com users.
Original PR description
Odoo.com does not create a distinction between a production and duplicated SAAS database. This allows test databases to pass the check for subscription. This commit adds an additional check for duplicated SAAS databases with a neutralised status. task-6249752 Forward-Port-Of: odoo/enterprise#118281
This update corrects a formatting problem in invoices generated when 'Hide composition' is enabled. Previously, columns after the description were misaligned, causing a visually incorrect invoice PDF. This fix ensures invoices are displayed correctly for German companies using the l10n_din5008 module.
Original PR description
| Before | After | |--------|--------| | <img width="1573" height="830" alt="image" src="https://github.com/user-attachments/assets/1960b51b-5c3e-4560-bd09-a20adfe2b381" /> | <img width="1573" height="830" alt="image" src="https://github.com/user-attachments/assets/565d0238-a295-44b7-bdaa-e7c6dd1200cf" /> | Steps to reproduce ================== - Install l10n_din5008,l10n_de - Use a german company - Go to settings - Enable "Show Position Column in Reports" - Go to Invoicing > Sales > New - Add a new section - Click on the three dots - Check "Hide composition" - Add a new line with a product - Confirm the Journal Entry - Print the Invoice PDF => Every column after the description is offset by one opw-5427590 Forward-Port-Of: odoo/odoo#261527
This update ensures that file uploads initiated through the link popover are immediately canceled when the user discards the popover. Previously, uploads continued in the background even after the discard button was pressed, leading to potential data inconsistencies. This change improves the user experience by preventing unexpected uploads.
Original PR description
**Current behavior before PR:** Steps to reproduce the issue: - Go to Todo, In the network tab switch to "Slow 4G" so that file upload can take few seconds to upload. - Upload a file using link popover. - While the file upload is in progress, hit the discard button of the link popover. - Notice that the upload continues in the background and when it completes successfully, link is inserted. **Desired behavior after PR is merged:** Discarding the link popover during file upload should cancel the upload request and prevent inserting the link. task-6199113 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267611 Forward-Port-Of: odoo/odoo#263463
This update fixes an issue where the project template dropdown in demo mode had a cluttered appearance, making it difficult to read. The fix removed a styling element that caused text to overlap, ensuring a clean and consistent display for all users.
Original PR description
Steps to reproduce: == Login as demo/onboarding user Open Project app Click on New Observe the template dropdown list Issue: == The template dropdown items are rendered with collapsed row height and poor vertical spacing in demo mode, making the list hard to read. Cause: == The template dropdown items utilized the `pe-0` utility class, which removed the padding at the end of the element. For non-admin users this caused the template name to touch the right edge of the container. Fix: == Removed the `pe-0` from the `DropdownItem` to restore standard right-side padding, and ensure consistent and readable row heights for both Admin and Demo users. task-5338191 Forward-Port-Of: odoo/enterprise#104440
A recent test within the HR Holidays module failed due to an error in how it checked for recordsets with multiple records. This commit corrected the code to avoid this issue, preventing test failures when other modules are installed. This ensures the HR Holidays tests run reliably.
Original PR description
Before this commit, the line https://github.com/odoo/odoo/blob/saas-19.1/addons/hr_holidays/tests/test_holidays_mail.py#L69 used `.id` on a many to many recordset which failed when the recordset had multiple records. This test led to an error when installing other modules with demo data like `test_l10n_be_hr_payroll_account` and the test was run with demo data. This commit uses the `in` operator instead of `==` and avoids `employee_ids.id` to avoid the error. Runbot error: https://runbot.odoo.com/odoo/error/241106 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266677
This update fixes an issue where the cursor position was incorrect after moving content within the HTML editor. Now, when moving a table or paragraph, the cursor automatically adjusts to the beginning of the moved item, preserving the user's selection if it was within the moved content.
Original PR description
#### Description of the issue/feature this PR addresses: - MoveNode restores the cursor at the container end position - After moving a table, the cursor ends outside the table body #### Desired behavior after PR is merged: - Preserve the selection if it was inside the moved node - Otherwise place the cursor at the start of the moved node #### Steps to reproduce: - Create a table in the editor - Move the table using Movenode - Drop the table and check the cursor position - The cursor ends outside the moved table body - Select some text in a paragraph - Move that paragraph using Movenode - The selection is placed at the end of the moved node task-6215743 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267549 Forward-Port-Of: odoo/odoo#264264
This update corrects a flaw in how Odoo tracks device status (supported/unsupported). Previously, changes weren't consistently reflected in the database when a device switched between states. Now, device status changes are tracked separately, ensuring accurate database updates and preventing issues with device recognition.
Original PR description
When a device is marked unsupported (e.g. FDM after power outage) and becomes supported with the same identifier (e.g. FDM after the client restarts it after the power outage), the changed was not taken into account because we used to track changes in a set of supported + unsupported. We now track changes in supported and unsupported separately to make sure the db is informed of the changes.
This update resolves an issue where users without employee access rights couldn't search for timesheet versions. The change removes a restriction on accessing version fields, ensuring broader search functionality while maintaining security through a previously implemented bypass mechanism. This improves usability for all users.
Original PR description
Issue: ---------------------------------------- When searching for a field from `hr.version` without any rights on Employees, we get an access error. Steps to reproduce:…
Issue: ---------------------------------------- When searching for a field from `hr.version` without any rights on Employees, we get an access error. Steps to reproduce: ---------------------------------------- - Timesheet > To Validate > All timesheet - Filter on Employee > Department (is set for example) - An error pops up Cause: ---------------------------------------- The field `department_id` of `hr.employee` belongs to `hr.version` and is accessible through the `_inherits` and the field `version_id`. When doing the search above, during the optimization of the domain, we end up trying to read `department_id` on `hr.employee.version_id`. But the field `hr.employee.version_id` is not accessible to users without Employee access rights. They only have rights on the field `hr.employee.current_version_id`. This occurs from version saas-19.1 because the access check was added in this version. ([commit](https://github.com/odoo/odoo/commit/aa58663a271e24a1fcb3f59e6bddfac50054703c)) Solution: ---------------------------------------- We remove the group restriction on `version_id`. The group restrictions are done with the fields of `hr.version`. As `version_id` is only a computed field from `current_version_id` which has `bypass_search_access=True`, this should not expose any field that wasn't already. `bypass_search_access=True` was added on `current_version_id` for the same reason. ([src](https://github.com/odoo/odoo/commit/94bb4a29189400d6bd0c2ca97eba271601262e1b)) opw-6149198 opw-6251866 Forward-Port-Of: odoo/odoo#264953
This update fixes an issue where the duration of calendar events created via drag-and-drop wasn't accurately reflected in the full event form. Previously, the duration was stuck with the initial drag value. Now, the full form correctly displays the updated duration based on the user's final time selection, ensuring accurate event scheduling.
Original PR description
When creating a calendar event by dragging on the calendar view, modifying the end time in the quick-create popover, and then clicking "More Options", the duration shown in the full form is the…
When creating a calendar event by dragging on the calendar view, modifying the end time in the quick-create popover, and then clicking "More Options", the duration shown in the full form is the original drag value instead of the value implied by the user's updated stop. calendar's makeContextDefaults seeds default_start, default_stop, default_duration, and default_allday from the drag extent. In the quick-create popover, changing stop triggers _compute_duration on that record so its duration becomes correct. On "More Options", goToFullEvent extracts a whitelist of fields from the quick-create record as default_X and merges them with the original drag context. https://github.com/odoo/odoo/blob/c82341c503ac/addons/calendar/static/src/views/calendar_form/calendar_quick_create.js#L9-L19 duration is missing from that whitelist, so the merged context still carries the stale default_duration from the drag. In the full form, that default is applied to the duration field and _compute_duration does not run because a default was provided for a stored, writable field. Adding duration to the whitelist forwards the quick-create's recomputed value as default_duration so the full form opens with the correct duration. Steps to reproduce: 1. Open Calendar, drag to create a 2-hour event (e.g. 10:00-12:00) 2. In the quick-create popover, change the end time to 14:00 3. Click "More Options" 4. Check the Duration field in the full form => Duration shows the original drag value (02:00) instead of 04:00 opw-6087449 Forward-Port-Of: odoo/odoo#257294
This update fixes a previous limitation where channel owners without system admin privileges couldn't promote members to admin roles. The change ensures that channel owners can now correctly assign admin access, improving channel management capabilities. This resolves a usability issue for channel administrators.
Original PR description
`canSetAdmin` was checking the target member role instead of the current user's role. Because of that, a channel owner who was not a system admin could not promote another member to admin. task-6250058 Forward-Port-Of: odoo/odoo#266615
This update fixes a technical issue in Odoo related to Python 3.14's garbage collection. Specifically, it prevented a runtime error that occurred when copying data structures using an `OrderedSet`. The change utilizes a more reliable copying method to avoid conflicts with the garbage collector, ensuring data integrity.
Original PR description
In Python 3.14, iterating over weak references (like `transaction.envs`) can trigger a `RuntimeError: dictionary changed size during iteration`. This happens mostly because the Garbage Collector can remove a weakref while `OrderedSet.copy()` is rebuilding the set via `dict.fromkeys()`. Instead of re-initializing the set by iterating over its elements, we now directly use the dictionary's native `.copy()` method. This atomic operation prevents the GC from modifying the size of the underlying `_map` during the copy. Forward-Port-Of: odoo/odoo#267947