Thursday, September 17, 2026
17 changes · saas-19.2
Resolved issues and error corrections
Fixes display issues in the website editor color picker and shop comparison bar when Odoo is used in languages such as German. Longer translated labels now fit better, and styling no longer depends on English text, improving consistency for multilingual users.
Original PR description
Steps to reproduce: - Set the user language to German. - Open a color picker with the `Theme` tab in the website editor. - Check the color presets and the reset button. - Open the product comparison bar on the shop page. => Long labels do not fit and some styles are missing. Before this commit, long labels did not fit in the color preset picker. Some CSS selectors also relied on English `title` values, so their styles were not applied in other languages. After this commit, the preset picker adapts to long labels and the CSS selectors use dedicated classes that work in every language. task-6259086 Forward-Port-Of: odoo/odoo#286426
This fix cleans up saved filter values before they are read by the system. It helps prevent avoidable errors when filters contain extra spaces, improving reliability without changing how users work.
Original PR description
task-6578010 Forward-Port-Of: odoo/odoo#288643 Forward-Port-Of: odoo/odoo#288528
This fix updates references to a renamed product unit precision setting so quantities are rounded consistently. It prevents affected POS, Jordanian e-invoicing, and stock package flows from silently using a generic two-decimal fallback.
Original PR description
…al.precision The `decimal.precision` "Product Unit of Measure" was renamed "Product Unit" in 18.1. Some occurences called the old name still exist in the code. This is silently fallbacking on the default 2 decimals from the `precision_get`. See: https://github.com/odoo/odoo/pull/193490 task-none Forward-Port-Of: odoo/odoo#288508
Odoo Studio now correctly removes text that sits next to an element when that element is deleted from a view. This prevents leftover text from appearing unexpectedly after users edit customized screens.
Original PR description
Have an arch like ``` <div> <br /> TEXT <span /> </div> ``` Now remove the block `TEXT <span />` Before this commit, the resulting inheriting arch was just `<xpath expr="//span" position="replace" />` So the `TEXT` was not removed After this commit, the `TEXT` is removed along with the following span opw-6524957 Forward-Port-Of: odoo/enterprise#131717
This fix updates a missed internal reference after a naming change for product unit precision. It helps ensure sales order line quantities in field service planning use the intended decimal accuracy instead of silently falling back to a default value.
Original PR description
The `decimal.precision` "Product Unit of Measure" was renamed "Product Unit" in 18.1. Some occurences called the old name still exist in the code. This is silently fallbacking on the default 2 decimals from the `precision_get`. See: https://github.com/odoo/odoo/pull/193490 task-none Forward-Port-Of: odoo/enterprise#131709
Long-pressing an order line in Point of Sale no longer resets its price back to the product's original price. This helps cashiers keep manual or adjusted prices intact when reviewing an order line, reducing pricing mistakes at checkout.
Original PR description
Long-pressing an order line recomputed its price and reset it to the product's original price. Preserve the existing price when the product is neither configurable nor part of a combo. --- Task: https://www.odoo.com/odoo/project/1737/tasks/6570304 Forward-Port-Of: odoo/odoo#288053
Users can now choose any applicable sales or purchase tax when editing a product, regardless of whether the product is goods or services. This prevents valid tax options from being hidden in the tax search popup and gives businesses more flexibility when configuring products.
Original PR description
With this commit:- - We remove the tax-scope filter from the Search more taxes in the product page's tax fields (Sales taxes and Purchase taxes). - The purpose of doing so is that we should not restrict the user from using service taxes in goods and vice versa. task-6527424 Forward-Port-Of: odoo/odoo#288187
Long bill reference text in the Outstanding credits or Outstanding debits sections is now shortened visually so it stays within the page layout. This keeps Credit Notes and Vendor Bills readable and prevents awkward display issues when references are unusually long.
Original PR description
The "Outstanding credits" or "Outstanding debits" sections of a Credit Note or Vendor Bill will overflow when the "Bill Reference" is too long. We resolve this by applying the text-truncate class.…
The "Outstanding credits" or "Outstanding debits" sections of a Credit Note or Vendor Bill will overflow when the "Bill Reference" is too long. We resolve this by applying the text-truncate class. Steps to Reproduce: 1. Create a new 19.0 db and load demo data. 2. Accounting -> Vendors -> Refunds -> RBILL/2026/09/0001 3. Click the entry in the Outstanding credits section. 4. Enter a long "Bill Reference" value, e.g. asdf asdfasfasdfasdfasdfasdfasdfasdfasdfasdfasdf. 5. Go back to the Credit Note and observe the text overflow. opw-6558982 <img width="1254" height="1162" alt="bill_reference_long" src="https://github.com/user-attachments/assets/8c762b50-65a8-44bf-9a28-bd34887d5928" /> <img width="1620" height="1294" alt="overflow" src="https://github.com/user-attachments/assets/f5c47404-fb7f-4715-8815-cabe5dda3805" /> <img width="1586" height="1159" alt="truncated" src="https://github.com/user-attachments/assets/2a80f656-0a12-4805-9c1d-fd20379655ce" /> Forward-Port-Of: odoo/odoo#288389
When opening quotations or orders from the point of sale with a customer already selected, the customer filter now behaves like a normal search filter. Users can remove it to view all available quotations and orders instead of being stuck seeing only that customer’s records.
Original PR description
When a customer was selected before opening the quotations/orders view, a default partner filter was applied. However, the partner was also added directly to the domain. Therefore, removing the partner filter from the search bar had no effect, as the domain continued to restrict the records to that partner. We now only use the default search filter so that users can remove it and display all available quotations/orders. --- Task: https://www.odoo.com/odoo/project/1737/tasks/6537521 Forward-Port-Of: odoo/odoo#287689
The wording for a French electronic invoicing/reporting setting was corrected after it was accidentally narrowed in meaning. This helps businesses understand that the option also relates to choosing not to send through the public invoicing portal, avoiding confusion during configuration.
Original PR description
When we removed the pilot phase setting from the view, we changed that setting to only mean Enable e-reporting. But that's a mistake. In fact people are also choosing not to send to the PPF, so the previous sentence was still right. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288518
This fix prevents an error from appearing when a website editor clicks a shared Sign document link from a page that has backend editing options. It improves editor stability by ensuring website controls are not triggered on Sign pages that do not support them.
Original PR description
# How to reproduce - Go to Sign > Templates - Upload a PDF & click on Share - Copy the link - Go to a page with a EditInBackend systray item (e.g. a Product or Event page) - In the editor, add the…
# How to reproduce - Go to Sign > Templates - Upload a PDF & click on Share - Copy the link - Go to a page with a EditInBackend systray item (e.g. a Product or Event page) - In the editor, add the copied link to a button or some text - Save - While still in editor mode, click the link # The issue A traceback is shown # Cause The traceback is caused by the call to this function : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/services/website_service.js#L336 In our case, `this.currentWebsite.metadata.mainObject` is undefined, so trying to access `.model` throws. `mainObject` is undefined because the sign link opens an XML file, which does not have any metadata associated to it : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/services/website_service.js#L150-L155 The call to `getUserModelName` is done by the `EditInBackendSystrayItem` component which subscribes to the "CONTENT-UPDATED" event : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/client_actions/website_preview/edit_in_backend.js#L33 However, this method should not be called by the bus because the sign page does not have this systray item. The issue is, the display of the component is managed by the `WebsiteSystrayItem`, based on the `hasEditableRecordInBackend` getter : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/client_actions/website_preview/website_systray_item.js#L10 https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/client_actions/website_preview/website_systray_item.xml#L9 And the re-render of that component that would remove the `EditInBackendSystrayItem` component is triggered by a call to `renderAndAdapt`, which is also subscribed to "CONTENT-UPDATED" : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/components/navbar/navbar.js#L48 So the destroy of the `EditInBackendSystrayItem`, which should remove the listener that calls `getUserModelName` is trigerred AFTER the call to that function is already done opw-6443794 Forward-Port-Of: odoo/odoo#281763
When a website editor clears an embedded code snippet and saves, Odoo now removes the stored embed content instead of restoring the previous code after reload. This prevents outdated embedded content from unexpectedly reappearing and restores the expected empty-snippet message for editors.
Original PR description
Scenario: - drop embedded code snippet - edit it to add a value - edit it to put it empty - save Result: on reload the embed is not removed and the old value is restored In 18.2, setting it empty would work and you would see an info alert: "Your Embed Code snippet doesn't have anything to display. Click on Edit to modify it." Fix: delete the embed field if it is saved empty. opw-5454289 Forward-Port-Of: odoo/odoo#251537
The Norwegian tax report now lists eVAT tax codes in a consistent order. This prevents random test failures and helps ensure the generated report output remains reliable and predictable.
Original PR description
The Norwegian tax report is built from ordered elements, but the summary detail per tax code is appended from a list that is quasi-directly calculated straight from PostgreSQL. The query does not request a specific result order causing indeterminism (it depends on the query plan chosen: hash vs. sort aggregate, parallel workers) when the whole XML tree is compared against a golden copy in tests. An explicit ORDER BY clause is added to the taxes query. The chosen key is the tax_code, because these can be casted for integer natural sort. The produced XML tree can be compared in its entirety without random failures. REF Runbot; https://runbot.odoo.com/odoo/error/939532 Forward-Port-Of: odoo/enterprise#131702 Forward-Port-Of: odoo/enterprise#131307
The tour testing action now correctly loads recorded tours from the database, even when they run automatically. This prevents the Testing button from appearing to do nothing for custom recorded tours, improving reliability for teams validating guided workflows.
Original PR description
Clicking "Testing" on a custom/recorded tour called startTour with mode "auto" and fromDB true, but getTour() only loaded from the database when mode was "manual". For a tour that only exists in the web_tour.tour record (not in the client-side registry), this left `tour` undefined and startTour() silently did nothing. Load from the database whenever fromDB is set, regardless of mode. Task-id: 6575435 Forward-Port-Of: odoo/odoo#288474
Users can now click old file links in HTML fields even if the original attachment was deleted. Instead of showing a client error, Odoo safely handles the missing file so records remain usable.
Original PR description
Clicking a stale /web/content/<id> link in an HTML field crashed the client after the related attachment had been deleted. **Steps to reproduce:** 1. Open any record with an HTML field (e.g. Project…
Clicking a stale /web/content/<id> link in an HTML field crashed the client after the related attachment had been deleted. **Steps to reproduce:** 1. Open any record with an HTML field (e.g. Project > Task description). 2. Upload a file into the HTML field to embed an attachment link. 3. Save the record. 4. Delete the uploaded attachment from Chatter > Files, or from Settings > Technical > Attachments. 5. Reopen the record and click the embedded file link. **Client Error:** `TypeError: Cannot destructure property 'mimetype' of '(intermediate value)' as it is undefined at LinkPopover.loadAsyncLinkPreview` `TypeError: Cannot destructure property 'type' of '(intermediate value)' as it is undefined at LinkPopover.updateDocumentState` When the attachment is missing, ormService.read returns an empty array, so fetchAttachmentMetaData returned undefined instead of entering its catch block. LinkPopover then crashed while destructuring that result in loadAsyncLinkPreview and updateDocumentState. Return a safe fallback metadata object when the attachment cannot be found so both code paths keep working without crashing. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279281
Spreadsheet actions now keep trusted help content intact, so guidance text with intended formatting is shown correctly instead of appearing as escaped plain text. This improves the user experience when opening spreadsheet-related actions without changing business workflows.
Original PR description
Current behavior before PR: - `navigateTo` cleans up the action description using `JSON.parse(JSON.stringify(...))`. - This removes Owl's `markup()` wrapper from the `help` field. - As a result, the trusted HTML is converted to a plain string and gets escaped instead of being rendered. Desired behavior after PR is merged: - Pass the action description directly to doAction. - `_preprocessAction` already provides defensive fallbacks for individual fields, such as `action.domain || [] and action.display_name || action.name || "".` - Therefore, undefined fields or missing keys are handled safely without the need for the JSON round-trip. - This preserves the trusted markup in the help field and renders the HTML correctly. Task: [6428217](https://www.odoo.com/odoo/project/2328/tasks/6428217) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286191
This fixes an issue in Discuss where rapidly clicking delete on an attachment could send duplicate removal requests and trigger an error. The app now tracks attachments already being deleted, preventing unnecessary repeat requests and improving reliability on slow connections.
Original PR description
**Steps to reproduce:** - Open Discuss app - Open any conversation - Setup the browser with throttled connection (e.g. Slow 4G) - Select multiple files to attach but don't send the message - While…
**Steps to reproduce:**
- Open Discuss app
- Open any conversation
- Setup the browser with throttled connection (e.g. Slow 4G)
- Select multiple files to attach but don't send the message
- While some are loading, double click the delete button of one of the loaded attachment preview
- Traceback will appear: `404 Not Found`
**Issue:**
On click the delete button triggers a deletion request on `/mail/attachment/delete`.
Repeatedly clicking the delete button before the first request was completed (and the `AttachmentList` get updated) but after the attachment was deleted, will cause a `404 Not Found` due to the `raise NotFound()` which was added by [1] in `mail_attachment_delete`.
```py
attachment = request.env["ir.attachment"].browse(int(attachment_id)).exists()
if not attachment or not attachment._has_attachments_ownership([access_token]):
request.env.user._bus_send("ir.attachment/delete", {"id": attachment_id})
raise NotFound()
```
**Fix:**
Prevent concurrent deletion requests for the same attachment by keeping track of attachments currently being deleted.
[1] https://github.com/odoo/odoo/commit/50f45dd436b97027cb1461410efeee7057dad4e8#
opw-6499125
Forward-Port-Of: odoo/odoo#288371
Forward-Port-Of: odoo/odoo#285060