Tuesday, September 15, 2026
22 changes · saas-19.4
Resolved issues and error corrections
This fixes exports of binary fields so file data is delivered in the expected base64 format again. It helps preserve compatibility with existing export workflows and integrations that rely on this format.
Original PR description
Export base64 data like we used to do. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288195
This fix makes an automated website media test consistently use a safe mock instead of reaching the real external illustration service. It reduces false test failures and helps keep release validation stable without changing customer-facing website behavior.
Original PR description
The `test_media_dialog_undraw` test monkeypatches `HTML_Editor.media_library_search` to avoid calling the real undraw API during the tour. However, the "routing" ormcache may already hold the controller endpoint built with the original (unpatched) method, if it was resolved by an earlier request served by the same worker. Invalidate the "routing" ormcache after patching so the requests are routed to the patched methods. Same change as done in #271536. https://runbot.odoo.com/odoo/error/939933
The spreadsheet command palette now only shows actions that are also available in the regular spreadsheet menu. This prevents users from seeing or selecting inaccessible options, making the spreadsheet experience more consistent and less confusing.
Original PR description
Some items are displayed in the command palette while being hidden in the spreadsheet interface. With this revision, we synchronize the availability of a menu item between the topbar menu and the command palette. Task-6352180 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
The spreadsheet command palette is now consistently available from the topbar across all related spreadsheet actions, not just document views. This fixes an access gap so users can more reliably use the same productivity shortcut wherever they work with spreadsheets.
Original PR description
The command palette was made available as a topbar menu item but it was only exposed in the document action. Task-6352180
This fix prevents an error when a check template uses account filters that return no matching accounts. It helps keep accounting report setup stable by handling empty results gracefully instead of showing a traceback.
Original PR description
When a check template has a domain on account.account that would give no result, it would throw a traceback because min cannot operate on an empty result.
This fixes Nilvera e-invoices so amounts written in words use Turkish consistently, including the currency subunit such as cents. It helps prevent mixed-language invoice notes and supports compliance with Turkish e-invoicing requirements.
Original PR description
### Issue before this commit: When generating a Nilvera e-invoice in a foreign currency (e.g., EUR), the amount written in words inside the <cbc:Note> tag contained a mix of languages. While the…
### Issue before this commit: When generating a Nilvera e-invoice in a foreign currency (e.g., EUR), the amount written in words inside the <cbc:Note> tag contained a mix of languages. While the numbers were correctly translated to Turkish, the currency subunit label was fetched using the customer's language. This resulted in a partially translated string (like "... SIFIR CENTS") instead of the expected fully Turkish text (like "... SIFIR SENT"). ### Steps to reproduce the issue: 1. Download Accounting and l10n_tr_nilvera_einvoice 2. Create an API KEY: https://docs.google.com/document/d/1EUzvTBnSm9-VwIfBsX299MHGXIVys-uijnsJ1fpz7vI/edit?tab=t.0#heading=h.e6i8a29lff5t 3. Go to a turkish client on the Accounting tab and click on 'Verify' for the Nilvera status 4. Go to currencies and activate EUR (be sure there is also the translation for currency subunit) 5. Go to invoices, create one for the Turkish customer you already verified setting the currency as EUR and send it with Nilvera 6. See that current output is <cbc:Note>YALNIZ : BEŞYÜZDÖRT EUR SIFIR CENTS</cbc:Note> (Turkish numbers with English subunit) but the expected output is <cbc:Note>YALNIZ : BEŞYÜZDÖRT EUR SIFIR SENT</cbc:Note> (Fully Turkish text) ### Cause of the issue: The issue occurs because the currency_subunit_label field is not translated but fetched using the language of the customer in the invoice. ### Reason to introduce the fix: To ensure that the amount in words inside the <cbc:Note> tag is completely formatted in Turkish, complying with Nilvera and local e-invoicing requirements, regardless of the customer language. opw-6523794 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288037 Forward-Port-Of: odoo/odoo#287630
This fix limits the payment methods that can be selected in expense settings to only those that are consistent with the company configuration. It helps prevent incorrect setup choices that could lead to confusion or processing issues in employee expenses.
Original PR description
Add domain to company_expense_allowed_payment_method_line_ids field to avoid selecting inconsistent data @Tecnativa TT64416 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287131
This update prevents an error when users drag an image and drop it back in the same place in the HTML editor. It improves editing stability, especially in Chrome, by handling the drop position safely when the page content changes during the action.
Original PR description
Steps to reproduce: - Insert an image as the last child of a paragraph. - Drag and drop it below or after itself. Description of the issue: - A traceback occurs. Cause: - When dropping an image below or after itself `document.caretPositionFromPoint()` computes a drop offset equal to the current node size. - The image is then removed from the DOM before being reinserted. Since it is the last child of its parent, removing it shrinks the parent, making the previously computed offset out of bounds. - Restoring the selection at that stale offset results in a traceback. Solution: - Treat dropping the image at its current position as a no-op and skip the remove/reinsert process, since it would not change the DOM. - Clamp the drop offset to the current node size before restoring the selection preventing out-of-bounds offsets. task-6435091 Forward-Port-Of: odoo/odoo#286613 Forward-Port-Of: odoo/odoo#280612
The appraisal workflow no longer forces users to complete a final assessment field. This prevents appraisals from being blocked when that assessment is not needed, making the process more flexible for HR teams.
Original PR description
Forward-Port-Of: odoo/enterprise#131393
Opening the “Insert in Spreadsheet” dialog no longer shows an unwanted horizontal scrollbar or duplicate scrolling on smaller screens. The dialog styling was separated from spreadsheet template styling, improving the user experience and reducing layout side effects between related spreadsheet features.
Original PR description
Opening "Insert in Spreadsheet" displayed an unwanted horizontal scrollbar in the spreadsheet selector. On small viewports, it could also produce a second scrollbar alongside the scrollable modal. The selector reused the `o-spreadsheet-templates-dialog` class, whose styles belong to `documents_spreadsheet`. This applied template-only max-height and overflow rules to the selector and made `spreadsheet_edition` rely on styles from a dependent module. Give selector dialogs their own class and keep the template-specific styles on the template dialog. Move the shared pager layout to `spreadsheet_edition` under a dedicated class, and update both pager consumers and the dashboard document selector. Task: 6526781 Forward-Port-Of: odoo/enterprise#131398 Forward-Port-Of: odoo/enterprise#130114
This fixes a visual issue on the online shop where wishlist heart buttons could appear out of place for Safari users. Product grids now look consistent across browsers, improving the shopping experience without changing functionality.
Original PR description
The wishlist button on the shop page is misaligned in Safari Steps to reproduce: (in Safari) 1. Install eCommerce 2. Go to the shop 3. The wishlist button (heart icon in the top right corner of each product) is misaligned Issue: The wishlist button (`.o_add_wishlist`) is positioned with `position: absolute` with only top and right offsets set (through the `o-position-absolute` mixin), leaving its width and height on `auto`. https://github.com/odoo/odoo/blob/c4de5361fb207916175332dcf6815c0814ecf09c/addons/website_sale_wishlist/static/src/scss/website_sale_wishlist.options.scss#L62-L65 In other browsers, the button resolves to a 38 x 38px square box but in Safari, it is not a square which misaligns it in the product grid. Solution: Force width and height on `.o_add_wishlist`, so the button resolves to the same box size in every browser. opw-6456552 Forward-Port-Of: odoo/odoo#287940 Forward-Port-Of: odoo/odoo#281935
Salary offers can now be created for contracts that start in the future, even when an employee's current contract ends today. This prevents unnecessary validation errors and helps HR teams prepare upcoming contract changes without delays.
Original PR description
Before this commit, creating a salary offer for a contract starting in the future raised a ValidationError on contract dates if the employee had an active contract ending today. This occurred because the salary simulation fallback logic defaulted to using today's date for the default contract start date, causing the simulation to overlap with the current running contract. This commit uses the target contract version's start date instead of today's date, preventing contract date overlap validation errors during offer generation. Task: 6502960 Forward-Port-Of: odoo/enterprise#129378
Belgian payroll DMFA validation now handles cases where the social security website cannot be reached. Instead of stopping with an error, the report is marked invalid with a clear explanation and the issue is logged for follow-up.
Original PR description
Before this PR, when the _fetch_validation_schema method was called (such as when the compute method for validation_state or error_message on dmfa was triggered), if the server could not reach the social security website, an error would be thrown. This is a problem, for instance, in Matt CI in upgrade which are run without internet access, or in case the social security website was down. To avoid this, we catch the error and instead: - Set the validation_state of the dmfa to 'invalid' - Add an explanatory error_message - Log the same error message in the server logs Task: 6528134
This fixes an issue where Turkish payroll payment reporting could fail if a payslip did not include stamp tax. Payroll teams can now complete MUHSGK V2 payments reliably even when that deduction is not configured.
Original PR description
## Steps to Reproduce: - Install the `l10n_tr_hr_payroll` and `hr_attendance` modules with demo data. - Switch to the company "My Turkish Company". - Settings > Set `Tax Responsible` and `SGK Workspace Registration Number`. - Pay Structures > `Türkiye: Monthly Pay` > remove `Stamp Tax Deduction (STAX)`. - Create and validate any employee's payslip. - Pay the payslip using the `MUHSGK V2` mode. ## Error: `TypeError: bad operand type for abs(): 'NoneType'` ## Cause: When the STAX code is missing from `totals_per_code`, it returns None. And calling `abs()` on this value raises a TypeError. ## Fix: Use `0` as the default value when STAX is missing. Align with the other values retrieved from `totals_per_code`, such as BTNET, CURTAXABLE. sentry-7719230995
When businesses import CII XML vendor invoices, Odoo now carries over the payment reference onto the generated vendor bill. This helps accounting teams keep payment instructions accurate and avoids manual correction after import.
Original PR description
### Issue before this commit: When importing a CII XML invoice containing a PaymentReference, the value is not transferred to the generated vendor bill in Odoo. ### Steps to reproduce the issue: 1. Download Accounting 2. Try to import the invoice in the ticket 3. See that in the tab other info the payment reference is not imported ### Cause of the issue: During a previous refactoring (ffbdf29a816d0ff4136488d26b55b9707fc37fc6), the helper function responsible for extracting the payment reference during the import process was omitted. ### Reason to introduce the fix: Add the missing extraction logic to ensure the payment reference is correctly retrieved from the XML and assigned to the Odoo invoice. opw-6530627 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287216
List view columns can now be resized reliably on tablets and other touch-screen devices. This prevents touch gestures from interrupting the resize action, making list views easier to adjust for mobile and tablet users.
Original PR description
Steps to reproduce ================== - Use a tablet (touch screen) - Open any list view - Try to resize a column by dragging the column header's right edge => The resize doesn't work properly: it gets interrupted an we can only move a few pixels at a time Cause of the issue ================== The resize handle relies on pointerdown/pointermove/pointerup to run and stop the drag, but nothing tells the browser to opt out of its native touch gestures. On a tablet, the drag can get hijacked as a page scroll, which fires pointercancel instead of pointerup. That event was not listened to, leaving the pointermove handler attached and the resize state stuck. Solution ======== - Set touch-action: none on the resize handle so a touch drag isn't interpreted as scrolling - Listen to pointercancel to properly stop the resize when the browser takes over the gesture anyway Forward-Port-Of: odoo/odoo#288046
The project overview now shows the upcoming milestone based on the milestone deadline rather than creation order. This keeps the project list consistent with the milestone list and helps users see the correct next deadline at a glance.
Original PR description
Issue: The project list could display the first created unreached milestone as the next milestone, even when another milestone had an earlier deadline. This made the project overview inconsistent…
Issue: The project list could display the first created unreached milestone as the next milestone, even when another milestone had an earlier deadline. This made the project overview inconsistent with the milestone list. Steps to reproduce: - Create a project with milestones enabled. - Create MS1, then MS2. - Give MS1 a later deadline than MS2. - Open the project list and display the Next Milestone column. Cause: `_compute_next_milestone_id()` aggregated unreached milestones as an `id:recordset` and selected its first element. The ORM orders that aggregate by database ID, so creation order was used instead of the milestone model's deadline order. https://github.com/odoo/odoo/blob/765174be270813442df6c497456fe2864517da0b/addons/project/models/project_project.py#L209-L218 https://github.com/odoo/odoo/blob/765174be270813442df6c497456fe2864517da0b/odoo/models.py#L364-L377 Solution: Retrieve unreached milestones through their normal ordered search before grouping them per project. This preserves batched computation while ensuring that the selected record follows the established milestone order. opw-6496938 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287810 Forward-Port-Of: odoo/odoo#285933
This change fixes an intermittent issue in website editing tests caused by the edit button not being ready after a language switch. It removes an unnecessary language change and waits for the editor to be in the correct mode, making test results more stable without changing user-facing behavior.
Original PR description
In [this commit][1] some steps were added to resolve non-deterministic errors. Just before `...clickOnEditAndWaitEditModeInTranslatedPage(),` three steps were added that switch the language back to…
In [this commit][1] some steps were added to resolve non-deterministic errors. Just before `...clickOnEditAndWaitEditModeInTranslatedPage(),` three steps were added that switch the language back to parseltongue. This is most likely since the function call implies we are on a translated page. The choice for this function was most likely due to a race condition. As the language was switched to English recently, the edit button might not have time to have switched. To recreate the race condition, remove the step added in this commit but leave the rest of the changes. Run the tour and it will hang up on the first step of `...clickOnEditAndWaitEditMode()` because the Edit button is still in "translation" mode. This commit removes the redundant language change and adds an extra step to check the Edit button is in the correct "mode" before continuing. [1]: https://github.com/odoo/odoo/commit/7f7cc9617381b1a2f61af0875e7b60ab0b7ab3a0 task-5951393 Forward-Port-Of: odoo/odoo#288035 Forward-Port-Of: odoo/odoo#286764
The Indian salary configurator now shows only one Gross salary line instead of duplicating it. The Monthly Equivalent total is also adjusted so employees and HR teams see an accurate salary breakdown.
Original PR description
Issue: - The salary configurator displays two 'Gross' lines for Indian payroll structures. - The generic salary resume uses the `wage` code, while the Indian payroll defines a structure-specific…
Issue: - The salary configurator displays two 'Gross' lines for Indian payroll structures. - The generic salary resume uses the `wage` code, while the Indian payroll defines a structure-specific 'Gross' resume using the 'GROSS' payslip rule. Both resumes were included in the salary configurator, resulting in duplicate 'Gross' entries. - The 'Monthly Equivalent' total shown in the configurator was also affected, as it included the generic 'wage' amount on top of the actual payslip values. Cause: - The generic 'wage' resume was still included for the Indian payroll structure alongside the India-specific 'GROSS' payslip resume. - The generic 'wage' resume also counts towards the 'Monthly Equivalent' total shown in the configurator, so removing only the duplicate line left this total incorrect. Fix: - Exclude the generic 'wage' resume from the salary configurator results when the selected structure is the Indian employee payroll structure. - This keeps the India-specific 'Gross' resume based on the 'GROSS' payslip rule while preventing the generic contract wage from being displayed as a duplicate. - Subtract the removed 'wage' amount from the 'Monthly Equivalent' total so it stays correct after the duplicate line is removed. task-6511413 Forward-Port-Of: odoo/enterprise#129518
FedEx shipping labels generated in ZPLII format now download with a standard .zpl file extension instead of being saved as .txt files. This prevents confusion and helps ensure labels can be used directly with compatible label printers.
Original PR description
TL;DR When downloading a `.zplii` shipping label from the chatter on a Delivery Order (using FedEx), the browser automatically adds .txt to the end of the filename, saving it as `.zplii.txt` Step to…
TL;DR
When downloading a `.zplii` shipping label from the chatter on a Delivery Order
(using FedEx), the browser automatically adds .txt to the end of the filename,
saving it as `.zplii.txt`
Step to reproduce:
- install `delivery_fedex_rest` with demo
- open shipping method menu -> Fedex Us -> label format = `zplii` -> save
- create a SO, click on 'Add Shipping",
- select fedex as shipping method -> get rate -> add -> confirm SO
- go to delivery and validate
- notice, in thread, a attachment with ZPLII extension appears
- download (.txt is appended to file)
Issue:
- `fedex_rest_send_shipping` post message with documents with extension as
`fedex_rest_label_file_type` i.e. `ZPLII`
https://github.com/odoo/enterprise/blob/735490d7ba9bdc6d0df7a0bd07c0d4e36d1ed2d4/delivery_fedex_rest/models/delivery_fedex.py#L193-L195
- when the attachment is created for this document , it's mimetype is computed
to be `text/plain` from [guess_mimetype](https://github.com/odoo/odoo/blob/5de4a5f6caee09881e7e147062f9eab9f8916a61/odoo/tools/mimetypes.py#L192) method, as data is plain ASCII code
- moreover, when downloading, [_get_stream_from](https://github.com/odoo/odoo/blob/5de4a5f6caee09881e7e147062f9eab9f8916a61/odoo/addons/base/models/ir_binary.py#L89) tries to guess extension
using [get_extension](https://github.com/odoo/odoo/blob/5de4a5f6caee09881e7e147062f9eab9f8916a61/odoo/tools/mimetypes.py#L210) which return `None` as len('zplii') > 4, [see](https://github.com/odoo/odoo/blob/5de4a5f6caee09881e7e147062f9eab9f8916a61/odoo/tools/mimetypes.py#L221)
- finally, as we got `None`, and mimetype is `text/plain`, `.txt` is appended [here](https://github.com/odoo/odoo/blob/5de4a5f6caee09881e7e147062f9eab9f8916a61/odoo/addons/base/models/ir_binary.py#L149)
Fix:
- we use `zpl` as extension for file instead of `zplii` as there is not
difference between them from printing perspective
- as length of 'zpl' is <=4 , `get_extension` will considered it as valid
opw-6410968
Forward-Port-Of: odoo/enterprise#126620The UAE payroll update process now restores required payroll structure information before updating related salary rules. This prevents scheduled payroll updates from failing if UAE payroll structures or structure types were deleted, keeping payroll maintenance running reliably.
Original PR description
Currently, an error occurs when the Payroll Update Data schedule action is run. **Steps to Reproduce:** - Install the `l10n_ae_hr_payroll` module without demo data. - Create a new company with the…
Currently, an error occurs when the Payroll Update Data schedule action is run. **Steps to Reproduce:** - Install the `l10n_ae_hr_payroll` module without demo data. - Create a new company with the country set to `United Arab Emirates`. - Switch to that company. - Go to `Payroll` > `Configuration` > `salary` > `Structures`. - Delete all salary structures related to the `United Arab Emirates`. - Go to `Scheduled Actions` and run `Payroll: Update Data`. `ValueError: External ID not found in the system: l10n_ae_hr_payroll.uae_employee_payroll_structure.` After this [recent commit], hr_rule_parameter_data and hr_salary_rule_data were added to _get_data_files_to_update. If the user deletes the salary structure and then updates the data files [1], an error is raised because the structure is missing. This commit ensures that the salary structure data is updated before updating the salary rule data. It also ensures that the salary structure type data is updated beforehand, as the structure depends on it and the user can delete the structure type data. [recent commit]: https://github.com/odoo/enterprise/commit/f3316e056da817ca31fecdc04e0f8df000f0f038 [1]- https://github.com/odoo/enterprise/blob/0a0b3a50a81df062ddee5c310ce06aaa4533a8a8/l10n_ae_hr_payroll/models/hr_payslip.py#L98-L105 sentry-7496380516 Forward-Port-Of: odoo/enterprise#130654
A timing issue in an automated rental shop test was fixed so it waits for the calendar to finish updating before choosing dates. This reduces false test failures and helps keep rental checkout validation stable without changing the customer experience.
Original PR description
The shop_buy_rental_stock_product tour can select a day from the previous month's grid before the date picker finishes rendering the next month. This can leave the rental period unchanged and cause the cart price assertion to fail. Wait for an animation frame after clicking "next month" before selecting a day. runbot-240903 Forward-Port-Of: odoo/enterprise#131467 Forward-Port-Of: odoo/enterprise#130822