Thursday, September 17, 2026
20 changes · saas-19.4
Resolved issues and error corrections
The Time Off approval settings have been renamed so they match the actual approver roles shown on employee records. This reduces confusion by making it clear when the HR Responsible, rather than the Time Off approver, will be notified for approval.
Original PR description
## Issue Currently, the different options for the approval of a time off (allocation) request are the following: 1. None needed 2. By Time Off Officer 3. By Employee's Approver 4. By Employee's…
## Issue
Currently, the different options for the approval of a time off (allocation) request are the following:
1. None needed
2. By Time Off Officer
3. By Employee's Approver
4. By Employee's Approver and Time Off Officer
On the Employee's view form, in the Settings tab, the approvers are named:
1. HR Responsible
2. Time Off
The *By Time Off Officer* option does not notify the *Time Off* approver, but the *HR Responsible*, which is not clear for the users. It would be clearer to use a similar naming convention for both the Approvers on the Employee's form and the options for the approval of the time off (allocation) requests.
<img width="1878" height="592" alt="6535827" src="https://github.com/user-attachments/assets/bc7ad9bb-6b53-4553-8fc8-fb305e7c0b28" />
## Steps to reproduce
1. Install *Time Off* (`hr_holidays`)
2. For an Employee E, set an HR Responsible and a (different) Time Off approvers
3. Create a Time Off request for the Employee E
- Ensure that the selected Time Off Type has its approval method set to "By Time Off Officer"
4. **The user notified off the time off request is the HR Responsible, which is unexpected, considering that we expect an approval from the "Time Off Officer".**
## Justification
In the `_get_responsible_for_approval` method, when using the "By Time Off Officer" option (`'hr'`), it is clearly the `hr_responsible_id` (HR Responsible) who is selected as "responsible" for the approval.
https://github.com/odoo/odoo/blob/dbed91769c48768f58b6a66bff0ed6d90394de38/addons/hr_holidays/models/hr_leave.py#L1557-L1559
The exact same logic is applied for the allocation requests [here](https://github.com/odoo/odoo/blob/dbed91769c48768f58b6a66bff0ed6d90394de38/addons/hr_holidays/models/hr_leave_allocation.py#L1070-L1072).
## Targeted version
We are targeting version 19.2, as it is the version from which the `responsible_ids` field (which was clearly specifying who had to be notified for the approval of a time off request) was removed (see https://github.com/odoo/odoo/commit/d37cf89a6ff134988b4a7c001a97973cd95a2ea8).
If deemed interesting, the same modification can be backported to previous versions too.
opw-6535827
Forward-Port-Of: odoo/odoo#288036
Forward-Port-Of: odoo/odoo#287686This fixes an issue in the HTML editor where clicking at the end of text inside a button incorrectly moved the cursor outside the button. Users can now place the cursor where intended when editing button labels, making content editing more predictable.
Original PR description
Problem: When trying to place the caret at the end of a button's content with the mouse, the caret always moves outside of the button instead of staying inside it. Cause: This happens because of the previous commit https://github.com/odoo-dev/odoo/commit/c8e93dbc806b5ea511cce695afbc9e81e30a1ca9 (which aimed to fix placing the caret after a link when at the end of a paragraph in the editable), which was not fixing the issue properly. Solution: Check if the click happens at the end of a link and the caret will move inside the link then manually place the selection after the link. Steps to reproduce: - Add a button with one character. - Try to put selection after that character. - Selection always jumps after the button. opw-6499237 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288521 Forward-Port-Of: odoo/odoo#284197
This fix trims unnecessary spaces before reading saved filter settings, preventing certain filters from failing when they contain leading or trailing whitespace. It helps keep user-defined filters working reliably without requiring manual cleanup.
Original PR description
task-6578010 Forward-Port-Of: odoo/odoo#288643 Forward-Port-Of: odoo/odoo#288528
Debit notes created from credit notes or vendor credit notes now show the correct smart button label. This makes the origin of each debit note clearer and avoids blank labels in the accounting interface.
Original PR description
Issue: - The smart button was displayed without a label when a debit note was created from a credit note or vendor credit note. Fix: - Display 'Credit Note' or 'Refund' as the smart button label based on the source document. Impact: - Smart buttons now display the correct label for each debit note origin. task-6578525
Fixed an issue where long-pressing an order line in Point of Sale could reset a manually adjusted price back to the product's original price. This helps cashiers preserve intended discounts or price changes and prevents checkout errors.
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
This fixes the wording of a French e-reporting configuration option that had been changed incorrectly. The text now more accurately reflects that users may choose not to send data to the public portal, helping avoid confusion during setup.
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
Product tax search now shows both goods and service taxes when users choose sales or purchase taxes. This prevents valid tax options from being hidden, giving 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
This fix prevents users from triggering repeated deletion requests for the same draft message attachment in Discuss. It avoids confusing error pages when users double-click delete during slow network conditions, improving reliability while composing messages.
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#285060Long 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 easier to read and prevents 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
This fixes an intermittent automated test failure in accounting reports by ensuring the report is fully loaded before navigating through breadcrumbs. It improves confidence in release validation without changing day-to-day user functionality.
Original PR description
The issue appeared 1 every 3 run, the reason was because it didn't wait the report to be opened and clicked on the breadcrumb. So it clicked the breadcrumb of the return and not the one of the report. The fix is to add a step in between checking the report is loaded. Runbot error: https://runbot.odoo.com/odoo/error/944180 Forward-Port-Of: odoo/enterprise#130807
Point of Sale users can now remove the preselected customer filter when viewing quotations or orders. This lets them see all available quotations and orders instead of being stuck with results for the customer selected beforehand.
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
This fixes a website editor issue where clearing an embedded code snippet could bring back the previous content after reloading the page. Empty embeds are now saved as empty and show the intended placeholder message, helping website editors avoid accidentally publishing outdated embedded content.
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
This fix prevents an error from appearing when a user clicks a shared Sign document link while editing certain website pages. It keeps the website editor stable by ensuring backend edit controls are not triggered for 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
This fix prevents an automated point-of-sale test from moving ahead too quickly after a receipt printing error. It makes the test results more stable in slower or heavily loaded environments, reducing false failures without changing everyday user behavior.
Original PR description
The fast-payment tours with automatic receipt printing configure an unreachable printer to exercise the printing-failure path. Once the failed print settles, FeedbackScreen arms a 1500ms timer that auto-navigates to the next order (iface_print_auto). The tour needs to detect the resulting error dialog, confirm it, then click the validation button, all before that timer fires. On a fast machine this comfortably fits, but on a loaded CI runner the sequence can take longer than 1500ms, so the auto-navigation happens first, unmounting the feedback screen before the tour can click ".button.validation" and causing a step timeout that could not be reproduced locally. Click on the feedback screen background right after confirming the dialog to call stopAutomaticSkip() and cancel the pending timer, removing the race entirely. This mirrors the pattern already used in test_automatic_receipt_printing. runbot-946191 Forward-Port-Of: odoo/odoo#288593 Forward-Port-Of: odoo/odoo#284690
Tax return submission no longer creates a second PDF attachment when one was already generated during validation. This keeps records cleaner and avoids duplicate documents for users handling tax returns.
Original PR description
When validating a tax return, the pdf is [generated](https://github.com/odoo/enterprise/blob/43d90902284fd55fcd4db2e2e824a1d3aa211db8/account_reports/models/account_return.py#L1386). When submitting it, it is generated once again, resulting in 2 attachments. Let's only keep the one at validate and skip creating when submitting. [task-6413368](https://www.odoo.com/odoo/project/967/tasks/6413368)
The Norwegian tax report now lists tax code details in a consistent order every time it is generated. This prevents random test failures and helps ensure the report output remains predictable and reliable.
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
Spreadsheet action help content now keeps its trusted formatting when users open linked actions. This prevents intended HTML help messages from appearing as escaped plain text, improving clarity 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
The map view now respects the record limit configured on an action when no specific map limit is set. This makes map behavior consistent with other views like list and kanban, helping users see the expected number of records.
Original PR description
Backport of odoo/enterprise#130336 The map view only considered the `limit` set in the arch, ignoring the one coming from the action (`ir.actions.act_window.limit`), unlike other views (list, kanban) which fall back to it. task-6531776 Forward-Port-Of: odoo/enterprise#131719 Forward-Port-Of: odoo/enterprise#131423
Asset depreciation models are now named by the time it takes to fully depreciate an asset, such as "36 Month", instead of by percentage rate. This makes model names easier to understand and avoids incorrect plural wording in translated languages.
Original PR description
This commit does 2 things: 1. Rate-based models were named after their rate, e.g. "2.78% per Month". Now they are named after the duration it takes to fully depreciate the asset. For example "2.78% per Month" now reads "36 Month". A helper function was added to handle the rounding of the method number. 2. Also the plural 's' that was appended to the duration was removed. It was added onto the end of the translated period label, so it produced broken names in every language other than English. task-6498452 Forward-Port-Of: odoo/enterprise#129366
HTML fields no longer crash when a user clicks an embedded file link whose attachment was deleted. Instead, the editor handles the missing file safely, keeping records usable and avoiding a disruptive client error.
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