Thursday, June 5, 2025
29 changes · 18.0
Enhancements to existing features
This update strengthens Odoo’s internal unit testing framework and mock test environment, making automated tests more accurate and easier to maintain. The changes are limited to test code, reducing risk while helping developers catch issues more reliably across several apps.
Original PR description
## Pull Request HOOT (PRHOOT) 32 This pull requests brings various improvements and fixes to Hoot and the Odoo unit test ecosystem. See the different commit messages for more details. Note: these changes are made in stable to avoid having to support multiple versions of the HOOT API. As such, these changes are intended to be strictly limited to unit tests as to not put the rest of the code base at risk. Enterprise: https://github.com/odoo/enterprise/pull/85562 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale receipts for UrbanPiper orders now show the provider's order ID in the receipt header. This makes it easier for staff and customers to match Odoo receipts with external delivery platform orders.
Original PR description
In this commit: ========== - We will display the provider's order ID in the order receipt header. Before this commit: ----------  After this commit: ----------  task-4840924
Resolved issues and error corrections
This fixes an issue in the Mail module where replacing an item in a linked list could leave the old item connected and fail to connect the new one correctly. The change helps keep message-related data relationships accurate and prevents follow-up inconsistencies after edits.
Original PR description
Before this commit, when a Many field has a One inverse, assigning on the many field in a specific index lead to a crash. The crash was fixed by https://github.com/odoo/odoo/pull/212963 But the resulting relations were still incorrect: the old record still was linked in the relation, and the new record was not properly linked in the inverse field. This was happening due to similar typo in the inner code of JS models: deletion and addition of respectively old and new records were done with respectively `recordList.delete(recordList)` and `recordList.add(recordList)`. The error comes from passing `recordList` instead of `recordList._.owner`, i.e. the old/new records. The typo comes from `RecordUses` that also have methods `add` and `delete` and have `recordList` as 1st param. FYI, `RecordUses` is used for very-low level internal links of record being used by other records. Semantically this is like a relational field but the shape differs for improved computational complexity.
Code cleanup and technical improvements
This update simplifies how automated test scenarios are defined across several Odoo Enterprise apps. It reduces maintenance work for the testing framework while keeping the changes limited to internal unit tests, so there is no expected impact on daily user workflows.
Original PR description
## Pull Request HOOT (PRHOOT) 32 This pull requests brings various improvements and fixes to Hoot and the Odoo unit test ecosystem. See the different commit messages for more details. Note: these changes are made in stable to avoid having to support multiple versions of the HOOT API. As such, these changes are intended to be strictly limited to unit tests as to not put the rest of the code base at risk. Community: https://github.com/odoo/odoo/pull/210041 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Miscellaneous changes
When a loyalty program is already applied in a sale order, the same loyalty program could also be triggered in the POS. Steps to reproduce: ------------------- * Create a simple loyalty program with a discount of 10% on order that is applied automatically if the total of the order is more than 1$ * Create a sale order with a product of 10$ and apply the loyalty program * You will have a disount of 1$ in the sale order * Open the PoS and settle the order * A new discount will appear in t
Original PR description
When a loyalty program is already applied in a sale order, the same loyalty program could also be triggered in the POS. Steps to reproduce: ------------------- * Create a simple loyalty program with a discount of 10% on order that is applied automatically if the total of the order is more than 1$ * Create a sale order with a product of 10$ and apply the loyalty program * You will have a disount of 1$ in the sale order * Open the PoS and settle the order * A new discount will appear in the PoS with a discount of 0.9$. > Observation: You now have 2 discounts coming from the same program Why the fix: ------------ We now adapt the `_programIsApplicable` function to check if the program was already used in the sale order. If it was, we ignore the program in the PoS. opw-4381890 Forward-Port-Of: odoo/odoo#209877
This fix ensures the website payment donation test runs reliably even when demo data is not installed. It helps keep automated checks stable for custom builds without changing customer-facing payment or donation behavior.
Original PR description
Commit [1] added the use of the portal user in test_01_donation. Its forward-port at [2] was adapted so that it works without demo data, and more, as it became the new default in that version. But [1] still made our test fail in some custom non-demo runbot builds. This commit fixes that by backporting the relevant parts of [2]. [1]: https://github.com/odoo/odoo/commit/4229a3f68e17f05b75bd13347589497682575bd0 [2]: https://github.com/odoo/odoo/commit/c4418cdbf82627fa7c0dc43087de790d61c01208 runbot-223118
The HTML editor now safely handles attempts to crop external images, which cannot be cropped. Instead of causing an error, it closes the cropper and shows a clear notification that the image type is not supported.
Original PR description
**Current behavior before PR:** Steps to reproduce the issue: - Upload an external image. - Click on it to open the toolbar. - Try to open image cropper. - Clicking on "Apply" button leads to traceback. This issue happens because after merging this commit [1] `closeCropper` method closes the cropper only if `cropperOpen` flag is true. In case of external image, cropper should be closed before it gets fully mounted as such images are uncroppable. In this case `cropperOpen` flag is false and `closeCropper` fails to close cropper which results in traceback later. **Desired behavior after PR is merged:** Cropper gets closed in case of external image and there is a toaster notification at the top-right showing "This type of image is not supported for cropping". [1]: https://github.com/odoo/odoo/commit/df64afb4e9504413f966a153772c568b625a5e13 task-4677287 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where the deadline date picker could remain visible after users navigated away from a task using the browser back button. The change ensures the pop-up is properly tied to the page component lifecycle, improving the user experience and avoiding stray interface elements.
Original PR description
Steps to reproduce ================== - Go to project - Open a project - Open a task - Click on the deadline field - Go to the previous page using the browser back button => The datepicker stays open Cause of the issue ================== `datetimePicker.create` was called using three parameters. But since bb1f912f04fbc4b1efe57847bceffce5895ced9b, it only accepts two. Solution ======== `createPopover` should be added to the `hookParams` This allows the popover to be closed when the owner component is destroyed. https://github.com/odoo/odoo/blob/bb1f912f04fbc4b1efe57847bceffce5895ced9b/addons/web/static/src/core/popover/popover_hook.js#L65 opw-4811594
This update corrects an automated test related to flexible time off expiration rules. It helps ensure the Human Resources time off module remains reliable when validating leave balance behavior.
This fix improves validation of domain filters when expressions are not allowed. It now detects invalid expressions inside nested filter sections, helping users catch configuration mistakes before they cause incorrect behavior.
Original PR description
If allowExpressions = false, the domain field is supposed to detect when expressions are used in the domain and notify the user that the domain is invalid. The current version of domainContainsExpressions do not allow detection of expressions in sub domains used in conjunction with the any operator. We fix that.
This fixes an issue where some sales order lines could have no product name in the first line. It helps ensure sales orders display correctly and avoids confusion when reviewing order details.
Original PR description
Finetuning of 47d223759f07c6b393f8fb6b031fd9d8b1acc1a6 Some lines might not have a product in the first line. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Scheduled messages sent from the chatter now correctly carry over the subject entered by the user. This prevents recipients from receiving emails with a missing or incorrect subject when scheduled messages are sent immediately.
Original PR description
Steps to reproduce =================== 1. Open a record with chatter, and open the full composer. 2. Add a custom subject and add a body. 3. Schedule message to send in the future. 4. Click on send now from chatter. => Subject is not propagated to the mail After this commit ================= This commit propagate subject to mail. Task-4845440
Fixes an issue in the mail module where replacing an item in a related record list could delete the wrong underlying record. This improves data reliability for features built on Odoo's mail-related JavaScript models without changing user workflows.
Original PR description
Before this commit, when defining a `fields.Many()` in JS models with an inverse as `fields.One()`, assign a new record on index of the `Many()` field leads to erroneously record deletion. This…
Before this commit, when defining a `fields.Many()` in JS models with an inverse as `fields.One()`, assign a new record on index of the `Many()` field leads to erroneously record deletion. This happens because when record list changes, it should sync the inverse relation by deleting the old record from the record list. In the internal code of JS models, all relational fields are stored as recordList, and the removal of a record from a relational field is made with recordList.delete(). In business code, Many fields values are returned as recordList, but One fields are returned as record or undefined. The recordList is not exposed. When the inner-code has to retrieve the record list of the relational field, it should make sure to use raw accessors rather than proxy accessors. Due to a typo in internal code of JS models, it retrieved the record rather than the record list of the One relational field, and thus called `record.delete()` instead of `recordList.delete()`, which lead the bug at hand. This commit fixes the issue by ensuring proper access to relational field to retrieve the record list even with One relational fields. The `toRaw()._raw` is to "remove" the proxy layer so we retrieve the raw object of relation which is always the record list for all relational fields.
Changing a company's country-specific VAT label now reliably updates the label shown on contact forms. This prevents users from seeing outdated form labels after configuration changes, reducing confusion and ensuring the interface matches the saved settings.
Original PR description
**PROBLEM** When changing the vat label associated to the country of the user's company, it should change the label of the `vat` field. The cached partners views are not invalidated as they should…
**PROBLEM** When changing the vat label associated to the country of the user's company, it should change the label of the `vat` field. The cached partners views are not invalidated as they should and the old views with the old label are presented to the user instead of the new ones. This can be confusing to the user, because while their change had an effect on the database, it doesn't reflect on the views showed to them. **STEP TO REPRODUCE** 1. On a fresh database, install the contact app. 2. From the contact app, Configuration->Countries, select United States which should be the country of the demo company. 3. Change the Vat Label field value. 4. Go on any contact form view, and notice the label of the `vat` field wasn't updated. 5. You can refresh the pages, and sometimes the new value will be there, sometimes not. **CAUSE** https://github.com/odoo/odoo/blob/ac106704f3c2d3e3fa94415134b9d5522b325378/odoo/addons/base/models/res_partner.py#L41C1-L55C1 In the mixin `FormatVATLabelMixin` we modify the form view, changing the label of the vat field accordingly. However, the `_get_view_cache_key` override that would add the field used to make the change (`self.env.company.country_id.vat_label`) to the cache key is missing. Which means the cache isn't invalidated when it should. **FIX** Add the `_get_view_cache_key` override to invalidate the cache when needed. opw-4825749
This fixes an issue where switching to the Follow-up Report from a customer statement could fail if journal filters had been cleared. Accounting users can now change reports more reliably without encountering an unexpected error.
Original PR description
When executing follow-up actions, a KeyError could occur if the 'journals' key was missing from the options dictionary Steps to reproduce: Go to Accounting > Reports, open the Follow-up Report, and click Options. Untick journals so that the 'journals' list is effectively removed. Go to Customers, select any customer, Click on Customer Statement. Try to change Report (up right) to Follow_Up Report OPW-4798813
Before this commit, creating bills through uploading XMLs with alphabetic codes in SchemeID was causing an error. This happened because these codes were not allowed in partner peppol_eas selection field. This commit adds these alphabetic codes as indicated in this reference sheet: https://ec.europa.eu/digital-building-blocks/sites/download/attachments/467108974/Electronic%20Address%20Scheme%20Code%20list%20-%20version%205%20-%20published.xlsx?version=1&modificationDate=1639417211464&api=v2
Original PR description
Before this commit, creating bills through uploading XMLs with alphabetic codes in SchemeID was causing an error. This happened because these codes were not allowed in partner peppol_eas selection field. This commit adds these alphabetic codes as indicated in this reference sheet: https://ec.europa.eu/digital-building-blocks/sites/download/attachments/467108974/Electronic%20Address%20Scheme%20Code%20list%20-%20version%205%20-%20published.xlsx?version=1&modificationDate=1639417211464&api=v2 task-4823915 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#212114
Ensure that automatically generated discount lines inherit the analytic distribution from the original invoice lines. This allows consistent reporting and accurate profitability analysis in analytic accounting. 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#209566 Forward-Port-Of: odoo/odoo
Original PR description
Ensure that automatically generated discount lines inherit the analytic distribution from the original invoice lines. This allows consistent reporting and accurate profitability analysis in analytic accounting. 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#209566 Forward-Port-Of: odoo/odoo#208279
- Ensured that when a group of taxes is selected, the designated label is displayed on the invoice instead of the tax names. Task-4637341 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#203532 Forward-Port-Of: odoo/odoo#201308
Original PR description
- Ensured that when a group of taxes is selected, the designated label is displayed on the invoice instead of the tax names. Task-4637341 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#203532 Forward-Port-Of: odoo/odoo#201308
Description of the issue/feature this PR addresses: Issue: if only one line is edited/added and it's account is not of type off-balance, the check will fail to raise the warning Steps to reproduce the error: 1. Create entry 2. Account move line 1 with account off balance 3. Account move line 2 with account off balance 4. Save move 5. Edit line 2, change the account to an asset type account. 6. Save move. The system does not give a warning. Current behavior before PR: Desired beha
Original PR description
Description of the issue/feature this PR addresses: Issue: if only one line is edited/added and it's account is not of type off-balance, the check will fail to raise the warning Steps to reproduce the error: 1. Create entry 2. Account move line 1 with account off balance 3. Account move line 2 with account off balance 4. Save move 5. Edit line 2, change the account to an asset type account. 6. Save move. The system does not give a warning. 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#211811
### Steps to reproduce: **Issue 1:** - Go to To-do. - Type any text and apply a gradient color. - Select the text and increase the font size. - The top part of the text became invisible. **Issue 2:** - Write and select some text . - Apply a gradient text/background color. - Click the 'Remove Format' button in the toolbar. - Gradient styles are removed, but the font size class remains. - Only on a second click, the font size class is removed. ### Description of the issue/feature
Original PR description
### Steps to reproduce: **Issue 1:** - Go to To-do. - Type any text and apply a gradient color. - Select the text and increase the font size. - The top part of the text became invisible. **Issue 2:**…
### Steps to reproduce: **Issue 1:** - Go to To-do. - Type any text and apply a gradient color. - Select the text and increase the font size. - The top part of the text became invisible. **Issue 2:** - Write and select some text . - Apply a gradient text/background color. - Click the 'Remove Format' button in the toolbar. - Gradient styles are removed, but the font size class remains. - Only on a second click, the font size class is removed. ### Description of the issue/feature this PR addresses: - When text or background color is applied using classes, applying a font size would nest the font-size <span> inside the <font> tag. - Font size class was not removed when gradient styles were present, as the closest element after `removeFormat` contained the gradient styles, not the font size class. ### Desired behavior after PR is merged: - Font size is now applied outside the <font> tag even when it has color-related classes. - `removeFormat` correctly removes both gradient styles and font size classes. task-4736914 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#207458
Before this commit, when paying a sale order in PoS with a downpayment line and a fiscal position available in PoS, the negative downpayment line at the end did not retain its tax. opw-4746761 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#212397
Original PR description
Before this commit, when paying a sale order in PoS with a downpayment line and a fiscal position available in PoS, the negative downpayment line at the end did not retain its tax. opw-4746761 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#212397
Scenario: - add an URL rewrite (308) of a route with only GET method (eg. test_website route /get rewritten to /get_new) - add a link in any website page to the original route (eg. /get) - open that page as public or user without website editing right Issue: an error 500 is shown instead of the page Cause: since the introduction of URL rewritting in be8fc2296b3822baffe0bc68cb4b7efdfe53fa91 the url_for method only worked for rewrite of route that had a POST method. In a GET method t
Original PR description
Scenario: - add an URL rewrite (308) of a route with only GET method (eg. test_website route /get rewritten to /get_new) - add a link in any website page to the original route (eg. /get) - open that page as public or user without website editing right Issue: an error 500 is shown instead of the page Cause: since the introduction of URL rewritting in be8fc2296b3822baffe0bc68cb4b7efdfe53fa91 the url_for method only worked for rewrite of route that had a POST method. In a GET method there was no try/except to handle a rewrite. Fix: handle GET method rewrite as it's done for POST method. Note: the added test without the fix fails with a 500 status code instead of the 200 expected. opw-4817473 Forward-Port-Of: odoo/odoo#212969
Scenario: - have "Editor and Designer" group and not "Administration/Settings" - go to the website, open editor and click on "Theme" > "Switch Theme" - click to install/update any theme Issue: an error is raised because we don't have the group "Administration/Settings" necessary to install a module. Fix: don't show the switch theme button if we don't have access to install it. opw-4782294 __pr note:__ for me the current behavior is ok but not very user friendly, lebl on the tick
Original PR description
Scenario: - have "Editor and Designer" group and not "Administration/Settings" - go to the website, open editor and click on "Theme" > "Switch Theme" - click to install/update any theme Issue: an error is raised because we don't have the group "Administration/Settings" necessary to install a module. Fix: don't show the switch theme button if we don't have access to install it. opw-4782294 __pr note:__ for me the current behavior is ok but not very user friendly, lebl on the ticket suggested that we could hide the "Switch Theme" button. side note: in 18.0 we get a usual access error (no read access to ir.module.module.dependency), while in 16.0 we get a manual access check: https://github.com/odoo/odoo/blob/097c9c928d88c10a01446131273fd2d10036f3dd/odoo/addons/base/models/ir_module.py#L70-L72 Forward-Port-Of: odoo/odoo#211289 Forward-Port-Of: odoo/odoo#211225
Problem: When selecting multi-line highlighted text that includes inline SVGs, the `selectedBlocks` includes both the parent `<p>` and the inner `<svg>` elements. These SVGs are incorrectly considered the deepest blocks, which prevents the parent `<p>` from being used to apply text styles (since styles can't be applied on `<svg>` elements). Example: ``` <p> <span class="o_text_highlight"> <span class="o_text_highlight_item">text<svg></span> <span class="o_text_highli
Original PR description
Problem: When selecting multi-line highlighted text that includes inline SVGs, the `selectedBlocks` includes both the parent `<p>` and the inner `<svg>` elements. These SVGs are incorrectly…
Problem:
When selecting multi-line highlighted text that includes inline SVGs, the `selectedBlocks` includes both the parent `<p>` and the inner `<svg>` elements. These SVGs are incorrectly considered the deepest blocks, which prevents the parent `<p>` from being used to apply text styles (since styles can't be applied on `<svg>` elements).
Example:
```
<p>
<span class="o_text_highlight">
<span class="o_text_highlight_item">text<svg></span>
<span class="o_text_highlight_item">text<svg></span>
</span>
</p>
```
As a result, style changes (like font) on the selection do nothing.
Solution:
Filter out non-editable blocks (e.g., `<svg>`) from `selectedBlocks` to ensure valid blocks like `<p>` are correctly handled as the deepest block.
Steps to reproduce:
1. Go to Website.
2. Add a paragraph with multiple lines of text.
3. Select all text and apply highlight.
4. Try to change the text style on the same selection. → The style change has no effect.
opw-4438171
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#210305When the user opens the chatter and expands the sidebar, the chatter's topbar overlaps the sidebar. This overlap disrupts the layout and can be frustrating, as it may hide some article links. To fix this, we'll update the sidebar's z-index so it sits above regular elements but remains below modals. Task-4636494 Forward-Port-Of: odoo/enterprise#86462
Original PR description
When the user opens the chatter and expands the sidebar, the chatter's topbar overlaps the sidebar. This overlap disrupts the layout and can be frustrating, as it may hide some article links. To fix this, we'll update the sidebar's z-index so it sits above regular elements but remains below modals. Task-4636494 Forward-Port-Of: odoo/enterprise#86462
The `MoveArticleDialog` component uses the display name to indicate which article will be moved. However, this field is not loaded on the record object, resulting in an undefined value. As a result, the modal incorrectly displays the article as untitled. Steps to reproduce the issue: 1. Open an article in Knowledge 2. Make sure that the article has a title 3. Click on the "Move To" option from the kebab menu => The modal says "Move the untitled article under:" TO BE: The modal should
Original PR description
The `MoveArticleDialog` component uses the display name to indicate which article will be moved. However, this field is not loaded on the record object, resulting in an undefined value. As a result, the modal incorrectly displays the article as untitled. Steps to reproduce the issue: 1. Open an article in Knowledge 2. Make sure that the article has a title 3. Click on the "Move To" option from the kebab menu => The modal says "Move the untitled article under:" TO BE: The modal should say: "Move <display_name> under:" To fix the issue, we will add the `display_name` field to the field dependencies of the `KnowledgeTopbar` component. Task-4636494 Forward-Port-Of: odoo/enterprise#86059
Before this commit the opening balance in the iras audit export was always at 0. This was caused because it would call _query_values which was not returning the initial balances. The fix was to instead call _get_initial_balance_values. With this we could finally get the opening balances. task-4826744 Forward-Port-Of: odoo/enterprise#86600
Original PR description
Before this commit the opening balance in the iras audit export was always at 0. This was caused because it would call _query_values which was not returning the initial balances. The fix was to instead call _get_initial_balance_values. With this we could finally get the opening balances. task-4826744 Forward-Port-Of: odoo/enterprise#86600
The XML already reports **PesoBrutoVehicular** in metric tonnes, as required by the Carta Porte complement. However, the PDF layout labelled the value as **kg**. * Updated QWeb template to display the unit `t`. Legal basis ----------- * Complemento Carta Porte 3.1 – Instructivo de llenado: “Peso Bruto Vehicular… atributo requerido para indicar **en toneladas** el peso bruto vehicular permitido… de acuerdo con la NOM-SCT-012-2017”. :contentReference[oaicite:0]{index=0} Forward-Port-Of:
Original PR description
The XML already reports **PesoBrutoVehicular** in metric tonnes, as required by the Carta Porte complement.
However, the PDF layout labelled the value as **kg**.
* Updated QWeb template to display the unit `t`.
Legal basis
-----------
* Complemento Carta Porte 3.1 – Instructivo de llenado: “Peso Bruto Vehicular… atributo requerido para indicar **en toneladas** el peso bruto vehicular permitido… de acuerdo con la NOM-SCT-012-2017”. :contentReference[oaicite:0]{index=0}
Forward-Port-Of: odoo/enterprise#85798The recognition entry for corporate tax was incorrect as it was crediting the expense while debiting the liability. This fixes the entry to: Debit: Tax Report Counter Part Account Credit: Liabilities Account for Tax Report Task ID: 4808001 Forward-Port-Of: odoo/enterprise#86315
Original PR description
The recognition entry for corporate tax was incorrect as it was crediting the expense while debiting the liability. This fixes the entry to: Debit: Tax Report Counter Part Account Credit: Liabilities Account for Tax Report Task ID: 4808001 Forward-Port-Of: odoo/enterprise#86315