Friday, September 25, 2026
10 changes · saas-19.1
Resolved issues and error corrections
This fixes an issue where email links copied or pasted into the HTML editor could become invalid or appear as plain text instead of clickable links. Users can now paste email addresses and mail links more reliably when editing content.
Original PR description
**Current behavior before PR:** **Issue 1:** Steps to reproduce the issue: - Create a mail link in editor. - Copy link via link popover. - Paste it anywhere in editor. - Click on it to open popover. Notice that newly created link is not a correct mail link. **Issue 2:** Steps to reproduce the issue: - Copy a mail URL from google docs or from some other website. - Paste the copied link in editor. Notice that URL is pasted as plain text instead of link. This happens because when a link is copied with HTML content, `handlePasteText` is called after `handlePasteHtml`, and it ends up being pasted as html content. **Desired behavior after PR is merged:** This PR aims to ensure that mail URLs are being pasted correctly in editor. task-6462998 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289981 Forward-Port-Of: odoo/odoo#282954
This fix ensures an automated employee event registration test opens the correct starting menu in Community databases. It prevents false test failures, helping keep employee skills and event registration features more reliably validated.
Original PR description
**Trigger:** Running `test_onsite_employee_registration` in a community database starts in Discuss instead of enterprise's usual home menu which crashes the test on the first step. This commit adds the `showAppsMenuItems` util to the test. To ensure the test starts in the correct view. runbot-946289 Forward-Port-Of: odoo/odoo#289486
Indian e-Way Bill generation now accounts for global discounts applied to invoices or transactions. This helps ensure e-Way Bill values match discounted totals, reducing compliance errors and manual corrections.
Original PR description
Before this commit- We didn't consider, global discount for ewaybill After this commit- We consider the global discount for ewaybill opw-6592878 task-[6596257](https://www.odoo.com/odoo/project/967/tasks/6596257) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#290217
This fixes an issue where archived bills of materials could be missed when their linked product was also archived. Users can now reliably find archived manufacturing records by product name, improving accuracy when reviewing or managing inactive products.
Original PR description
When searching for an archived bom (filer archived activated), if the main product is also archived, the search on the produt will not find the bom. Steps to reproduce: ------------------- * Create…
When searching for an archived bom (filer archived activated), if the main product is also archived, the search on the produt will not find the bom.
Steps to reproduce:
-------------------
* Create product AA
* Create a bom for product AA
* Archive product AA
* Products > bom
* Search for "Archived" and Product: "AA" -> It will not find the bom
Observation:
-------------
When doing the search, it will start a web_search_read ['&', ('active', '=', False), ('product_tmpl_id', 'ilike', 'AA')].
While in _search it will decide if we filter active elements: https://github.com/odoo/odoo/blob/60b5b99d569dbe183ef9c980217ccfe9bf243756/odoo/orm/models.py#L5363-L5369 In the first level since "active = False" is in the domain (for the bom) it will not add the filter.
The _search will optimize the domain query level by level by calling optimize_full.
First the outher layer :
optimize_full (Domain '[]')> _optimize (DomainNary '&')> _optimize_step (DomainNary '&')
Then the children [1: (active bom), 2: (product template display name)]:
_optimize>optimize_step> ...
While optimizing the second child the domain condition is: [('product_tmpl_id', 'any', [('display_name', 'ilike', 'AA')])]
Since it's a any operation, in optimize_step, it will use the _optimize_any_domain_at_level:
https://github.com/odoo/odoo/blob/16aaaafd7d314c04f39b1f633af3b5e15b46d78b/odoo/orm/domains.py#L970-L972
After doing some checks it will continue to optimize per level with the related comodel:
https://github.com/odoo/odoo/blob/60b5b99d569dbe183ef9c980217ccfe9bf243756/odoo/orm/domains.py#L1389-L1393
Since it's an "any" operator it need to respect the following guidelines : https://github.com/odoo/odoo/blob/60b5b99d569dbe183ef9c980217ccfe9bf243756/odoo/orm/domains.py#L98-L101
this is no done in `_optimize_any_domain_at_level` since it resolves a relational field's 'any' domain by looking up a fresh comodel recordset without adjusting its context.
Which means that for the following level, on the product template, the active_name is not on the domain anymore and the context was not passed corretly, so _search will automaticly add the filter ("active = True").
opw-6514762
Forward-Port-Of: odoo/odoo#285942This fixes a mail composer issue where the mention suggestion list could reopen after a user dismissed it, preventing the next Escape key press from discarding a reply. The change makes message composition more predictable, especially under slower or heavily loaded server conditions.
Original PR description
Before this commit, the composer suggestion list comes back on its own after Escape closed it, as soon as the server answers the mention search. The re-opened list takes the next Escape, and the…
Before this commit, the composer suggestion list comes back on its own after Escape closed it, as soon as the server answers the mention search. The re-opened list takes the next Escape, and the reply is never discarded. The test "reply: discard on pressing escape" fails that way on runbot: ``` Failed to find 0 of ".o-mail-Composer" (Timeout of 10 seconds). Found 1 instead. ``` This happens because NavigableList opens on every new set of options: the list first opens on the partners the store already holds, and the answer brings the ones it does not. The fetch is debounced by 250ms, so it lands between the two Escapes only on a loaded machine. This commit fixes the issue by ignoring the fetched suggestions once the user closes the list, until the search changes. Note that the test now flushes the debounced fetch right after Escape, so the race happens on every run. https://runbot.odoo.com/odoo/error/947267 Forward-Port-Of: odoo/odoo#290363 Forward-Port-Of: odoo/odoo#290163
This fixes a company-switching issue that could allow two portal users to become linked to the same merged contact. The contact merge process now checks all linked users across companies before allowing the merge, helping preserve correct user-contact relationships.
Original PR description
Switching companies can let a contact merge bypass the check that prevents multiple users from ending up linked to the same contact. ### Steps to reproduce 1. As a user with Contact Creation rights…
Switching companies can let a contact merge bypass the check that prevents multiple users from ending up linked to the same contact. ### Steps to reproduce 1. As a user with Contact Creation rights and access to companies A and B, select company A. 2. Create two contacts with no company set and grant each portal access. 3. Select only company B. 4. Merge the contacts. The merge succeeds and links both portal users to the surviving contact. With company A selected, the same merge is correctly rejected. ### Cause The wizard checks that the contacts have at most one linked user in total, including archived users. However, it reads `user_ids` with the acting user's permissions. Company record rules hide both portal users when only B is selected, so the check finds none. The subsequent SQL update still moves both users' contact links to the surviving contact. ### Fix Use `sudo()` only for this check, since it must count every user whose link the merge would move. Retain `active_test=False` to include archived users. Add a regression test covering both company selections. opw-6586945 Forward-Port-Of: odoo/odoo#290418 Forward-Port-Of: odoo/odoo#290296
Copied images in the website editor now stay linked to the correct page or content record instead of retaining a reference to the original source. This prevents mismatches that could otherwise leave edited content and its images out of sync until a later save.
Original PR description
When an attachment tied to one record was copied while editing content linked to a different one, the duplicate could keep referencing the original model instead of the new target, leaving the two out of sync until the next save. opw-6560233 Forward-Port-Of: odoo/odoo#289842 Forward-Port-Of: odoo/odoo#287784
This fix makes an automated email template test wait for the page to be fully ready instead of relying on a short timer. It reduces random test failures in the Mail app, helping keep releases and quality checks more stable without changing end-user behavior.
Original PR description
Before this commit, mail_template_dynamic_placeholder_tour could fail when the server answers the onchange of "Applies to" slowly: Tour mail_template_dynamic_placeholder_tour failed at step Check if…
Before this commit, mail_template_dynamic_placeholder_tour could fail when the server answers the onchange of "Applies to" slowly:
Tour mail_template_dynamic_placeholder_tour failed at step Check if
the dynamic placeholder popover is opened
(trigger: div.o_model_field_selector_popover)
This happens because the tour waits a fixed 200ms after picking "Contact" before typing "#" in the subject. The popover needs the model, and the record only holds the model once the onchange answers. On runbot the answer came after 230ms, so "#" showed the "select a model" notification instead of the popover.
This commit fixes the issue by waiting for the internal link button of the many2one, which only renders once the record holds the model.
Note that this step relies on "[FIX] web: cancel the pending search on autocomplete select": without it, a search still pending on the picked value marks the input as edited, which hides that button.
https://runbot.odoo.com/odoo/error/947209
Ref commit: https://github.com/odoo/odoo/pull/287888
Forward-Port-Of: odoo/odoo#290364
Forward-Port-Of: odoo/odoo#290185Time Off approvers can now access the Time Off smart button for employees they are responsible for, even if they do not have broader Time Off permissions. This lets managers handle assigned employee requests as intended and avoids blocking normal approval workflows.
Original PR description
Issue: A user without any rights on Time Off should still be able to manage the requests of the users he's manager of. However, the computation for `show_leaves` only considers Time Off Officers/Admins and the employee themselves, while it should also consider the employee's Time Off approver. Fix: Include the employee's Time Off approver when computing `show_leaves`, allowing them to access the employee's Time Off smart button. Reproduction Steps: 1. Set a user (e.g. Marc Demo) to "No" for Time Off. Note: If reproducing in v19, Administrator rights on Employees are also needed to access the private employee form view where the issue occurs. 2. Set that user as another employee's Time Off approver. 3. Log in as that user and open the employee's form view. 4. Observe that the Time Off smart button is not visible. Related Tickets: opw-6445714 Forward-Port-Of: odoo/odoo#290047 Forward-Port-Of: odoo/odoo#281589
This fix prevents Ecuadorian electronic invoices from failing when the company partner has a non-Ecuadorian or non-numeric VAT number. The system now avoids generating an Ecuador authorization number unless the company identification is a valid RUC, improving invoice confirmation reliability.
Original PR description
When the VAT of an Ecuadorian company's partner contains characters other than decimal digits, confirming an invoice raises a traceback. Steps to reproduce the error: - Install ``l10n_ec_edi`` module…
When the VAT of an Ecuadorian company's partner contains characters other than decimal digits, confirming an invoice raises a traceback. Steps to reproduce the error: - Install ``l10n_ec_edi`` module and switch to EC Company - Open the partner of EC Company > Set a VAT containing non-digit characters - Create a new invoice > fill the required fields > Confirm Traceback: ```py ValueError: invalid literal for int() with base 10: 'E' ``` During invoice confirmation, ``_l10n_ec_set_authorization_number()`` method is called to generate the authorization number at [1], It builds the ``key_value`` using the vat of company's partner at [2]. The generated ``key_value`` is then passed to ``_l10n_ec_get_check_digit`` method, which converts each character of ``key_value`` to an integer using ``int()`` at below line. https://github.com/odoo/enterprise/blob/799e9e94efcc338a8f3a6b7ab85cf77f9898f005/l10n_ec_edi/models/account_move.py#L830 When the VAT contains a character that cannot be converted to an integer, It will raises the above traceback. To build the ``key_value``, the company's partner vat should be RUC consisting of 13 digits. Ref: https://www.sri.gob.ec/o/sri-portlet-biblioteca-alfresco-internet/descargar/fb95cafc-a8ca-4a4c-afb6-12c4153165f0/FICHA%2520TECNICA%2520COMPROBANTES%2520ELECTR%25C3%2593NICOS%2520ESQUEMA%2520OFFLINE.pdf Solution: If the identification type of the company's partner is not RUC, return an empty string. [1]: https://github.com/odoo/enterprise/blob/799e9e94efcc338a8f3a6b7ab85cf77f9898f005/l10n_ec_edi/models/account_move.py#L806 [2]: https://github.com/odoo/enterprise/blob/799e9e94efcc338a8f3a6b7ab85cf77f9898f005/l10n_ec_edi/models/account_move.py#L825-L826 sentry-7642961403 Related Community PR: https://github.com/odoo/odoo/pull/280047 Forward-Port-Of: odoo/enterprise#132478 Forward-Port-Of: odoo/enterprise#126519