Monday, February 9, 2026
15 changes · 19.0
Resolved issues and error corrections
Recruiters can now send emails to applicants even after those applicant records have been archived or refused. This prevents missed communication and keeps follow-up actions available throughout the hiring process.
Original PR description
Version: - 17.0 Steps to reproduce: - Create an applicant. - Archive the applicant. - Select the archived applicant. - Click the Send Email action. Issue: - Unable to Send Emails to Refused Applicants Cause: - The applicant_ids many2many field does not include archived applicants. Because of this, when an applicant is archived, the field becomes empty. Solution: - Add active_test to the field context. Task - 5786195 Forward-Port-Of: odoo/odoo#244691
This fixes an issue in Indian payroll/time off localization where employees without manager rights could see an error when opening their already approved past time off. The change prevents unnecessary updates while viewing the record, so employees can access their validated leave information normally.
Original PR description
Steps to reproduce: ------------------- 1. Install `l10n_in` and `l10n_in_hr_holidays` 2. Switch to an Indian company 3. Create a user and related employee without Time Off rights 4. Log in with the…
Steps to reproduce: ------------------- 1. Install `l10n_in` and `l10n_in_hr_holidays` 2. Switch to an Indian company 3. Create a user and related employee without Time Off rights 4. Log in with the new user and create a past time off 5. Approve the time off as an time off manager/admin 6. Open the validated time off record as the employee Issue: ------ Opening a validated time off raises the following UserError: ```python You must have manager rights to modify/validate a time off that already begun. ``` Cause: ------ The `_get_durations` method in `l10n_in_hr_holidays` was updating the `l10n_in_contains_sandwich_leaves` field every time it was executed. When a user opened a validated time off record, this triggered a `write()` operation. Since non-manager users are not allowed to write on already started validated leaves, this caused a [UserError](https://github.com/odoo/odoo/blob/047d5b61a5f3fc5c41f5bc3975938a53b5da49a7/addons/hr_holidays/models/hr_leave.py#L793-L798) The field `l10n_in_contains_sandwich_leaves` does not need to be updated when `l10n_in_is_sandwich_leave` is False. See [[1]](https://github.com/odoo/odoo/blob/047d5b61a5f3fc5c41f5bc3975938a53b5da49a7/addons/l10n_in_hr_holidays/models/hr_leave.py#L156-L157) & [[2]](https://github.com/odoo/odoo/blob/047d5b61a5f3fc5c41f5bc3975938a53b5da49a7/addons/l10n_in_hr_holidays/models/hr_leave.py#L62) And this [part of the code](https://github.com/odoo/odoo/blob/047d5b61a5f3fc5c41f5bc3975938a53b5da49a7/addons/l10n_in_hr_holidays/models/hr_leave.py#L160-L173) is responsible to update `l10n_in_contains_sandwich_leaves` value. **NOTE:** Opening future validated time off records as a non-manager user triggers `AccessError` as it is not allowed to update the validated time off record. Solution: --------- Ensure that `l10n_in_contains_sandwich_leaves` is updated only when `indian_leaves` is applicable. opw-5373055 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#246078 Forward-Port-Of: odoo/odoo#240056
Time off entries now create calendar events with the correct start and end times when users are outside UTC or book half-day/custom-hour leave. Full-day absences also appear as full-day calendar events even when the leave type is configured in half days, reducing scheduling confusion.
Original PR description
Forward port of https://github.com/odoo/odoo/pull/238941 which was not included by mistake here: https://github.com/odoo/odoo/pull/234703 Additionally, fix an issue where a full day leave was not displayed as a fullday event in the calendar if the leave type unit was half days.
The Indian TDS report now displays withheld tax amounts as positive values instead of negative ones. This restores the expected presentation for all TDS sections, helping accounting users review reports without confusion.
Original PR description
**Steps to reproduce:** * Install the **l10n_in** module. * Create vendor bills with applicable **TDS taxes** (e.g. Section **194C**, **194A**, **195**). * Post the bills. * Go to **Accounting → Reporting → TDS Report**. **Observed behavior:** * TDS amounts are displayed as **negative values** across all sections (192, 193, 194A–Q, 195, etc.). * This differs from versions up to **18.3**, where TDS amounts were shown as positive. **Cause:** * In v19, the automatic **+/− sign handling** was removed from the tax grid logic. [REF](https://github.com/odoo/odoo/commit/17a6117ed88c29b5bc4db0c872bcdbc109a7d98b) * TDS report formulas were missing an explicit **negative sign prefix**, causing amounts to appear inverted. **Fix:** * Add the required **negative sign prefix** to all TDS section formulas in `account_tax_report_tds_data.xml`. * Ensures TDS amounts are displayed as **positive values**. * Applies to all TDS sections. opw-5502385
This fix corrects how kit product quantities are calculated when sales use multi-step deliveries and returns. It prevents Odoo from creating unnecessary extra transfer orders after a returned kit sale is reduced to zero, improving inventory accuracy and reducing manual cleanup.
Original PR description
### Steps to reproduce: 1. In the settings enable: Multi-steps route 2. Put your warehouse in 2-step deliveries 3. Create a kit product: - With one component - There is one component in the stock 4.…
### Steps to reproduce: 1. In the settings enable: Multi-steps route 2. Put your warehouse in 2-step deliveries 3. Create a kit product: - With one component - There is one component in the stock 4. Create and confirm a SO with 1 x K 5. Process the pick and ship 6. Return the delivery 7. Set the sol qty to 0 #### > Two unexpected pickings are created to put the kit in output ### Cause of the issue: Decreasing the sol quantity to 0 will call the `_action_launch_stock_rule` in order to create and run procurements related to that quantity change. However, the quantity currently handled by other procurements is determined here by the `_compute_kit_quantities`: https://github.com/odoo/odoo/blob/87e176ad76c9d7b87cd622ae38a8b9a62813b1cb/addons/sale_stock/models/sale_order_line.py#L388 https://github.com/odoo/odoo/blob/87e176ad76c9d7b87cd622ae38a8b9a62813b1cb/addons/sale_mrp/models/sale_order_line.py#L154-L166 https://github.com/odoo/odoo/blob/87e176ad76c9d7b87cd622ae38a8b9a62813b1cb/addons/mrp/models/stock_move.py#L578-L580 Now, the issue is that `_compute_kit_quantities` does not handle move chains properly, as all delivery moves contribute to the `incoming_qty` and all return moves contribute to the `outgoing_qty`. This results in an `incoming_qty` of 1 (for the pick) + 1 (for the ship) and an `outgoing_qty` of 1 (for the 1-step return), that is a `qty_processed` of 1. As a result, the procurement will be generated for a quantity of `0 - 1` (rather than 0): https://github.com/odoo/odoo/blob/87e176ad76c9d7b87cd622ae38a8b9a62813b1cb/addons/sale_stock/models/sale_order_line.py#L388-L402 which leads to the unexpected picking creations. opw-5432558 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Inventory adjustments for products valued by lot now use the lot's own cost instead of the product-wide average cost when adding stock to a single lot. This keeps lot costs accurate and updates overall product valuation correctly, improving accounting accuracy for businesses using lot valuation.
Original PR description
**Problem:** when adding quantities to a lot via the physical inventory the move created, uses the standard_price of the product and not the standard_price from the lot even if the product is valued…
**Problem:** when adding quantities to a lot via the physical inventory the move created, uses the standard_price of the product and not the standard_price from the lot even if the product is valued by lot. **Steps to reproduce:** - create an avco perpetual product, tracked and valued by lot - confirm a PO for a quantity of 1 and a price of 10 - on the picking set the lot as 'lot1' and validate the picking - confirm a PO for a quantity of 1 and a price of 16 - on the picking set the lot as 'lot2' and validate the picking - open "Inventory/ Operations/ Adjustments/ Physical Inventory" - on the quant line of the lot1 change the quantity from 1 to 2 and apply - open the product form **Current behavior:** the move created has a value of 13 (the standard price of the product), so : 1) the standard price of the product is still at 13 2) if you select the smart button for lots/serial number and select lot1 you can see that the new cost is 11.5 **Expected behavior:** the move created should have a value of 10 because we added a quantity without specifying a cost in a lot which has a value of 10, so: 1) the standard price of the product should now be 12 2) the cost of the lot should stay 10 **Cause of the issue:** when calling _get_value_data on the move, and that we use _get_value_from_std_price (because there is remaining_qty after previous steps), https://github.com/odoo/odoo/blob/555df96ac87a51405767c32f0396f762d458fd29/addons/stock_account/models/stock_move.py#L382-L384 inside _get_value_from_std_price, we use the standard price of the product https://github.com/odoo/odoo/blob/555df96ac87a51405767c32f0396f762d458fd29/addons/stock_account/models/stock_move.py#L450-L452 But if : - the product is valued by lots, - we're not in the case where we want to call _get_standard_price_at_date (when the product is standard_price and at_date is set) in this case we should use the standard_price of the lot **fix** in case there is multiple lots on the move, we stay with the standard_price of the product because it's not clear that a weighted average would be better opw-5898837
This fixes an issue where Firefox users could be unexpectedly logged out when viewing chatter images that had been routed through email security services such as Cisco Secure Email or Microsoft SafeLinks. Odoo now avoids replacing a valid user session during these image requests, keeping users signed in while images load normally.
Original PR description
## Problem A logout occurs when an image in the chatter is requested through a third-party security proxy (like Cisco Secure Email or Microsoft SafeLinks) via a boomerang redirect following this…
## Problem
A logout occurs when an image in the chatter is requested through a third-party security proxy (like Cisco Secure Email or Microsoft SafeLinks) via a boomerang redirect following this flow:
- A user (Person A) opens an Odoo record. The chatter contains an image previously sent by a correspondent (Person B) whose email client or mail server rewrote the image URL to point to a security proxy.
- Firefox tries to load the image. The URL points to `cisco.com/...`. (for example)
- The proxy scans the link and redirects the browser back to the original Odoo URL: `odoo.com/web/image/...`.
- Firefox follows the strict (now deprecated) `rfc6265bis` rule: it looks at the whole redirect chain.
Since it sees a cross-site hop (cisco.com), it flags the final request as cross-site.
-> Because Odoo's session_id is `SameSite=Lax`, Firefox refuses to send
the cookie on this "false" redirect
- Odoo receives the request at `/web/image` without a session_id.
- Odoo creates a new, empty session to process the request.
- At the end of the request, because save_session is True by default, Odoo sends a `Set-Cookie: session_id=NEW_EMPTY_ID` header in the response.
- The browser receives this `Set-Cookie` header, and this time *applies a different policy*: it considers the header as same-origin, allowing it to overwrite the previously valid session cookie with this new one that corresponds to a fresh, unauthenticated session.
- The user is instantly logged out of their current Odoo tab.
## Context on Web Compatibility
This "redirect chain consideration" was a controversial part of the `RFC6265bis` draft.
Chrome and Safari never fully implemented it because telemetry showed it broke ~1% of the web. In March 2024, the HTTP Working Group (HTTPWG) officially decided to remove this requirement from the spec (reverting to a more permissive model) because it was deemed not web-compatible. Firefox, however, still enforces this strict behavior in many versions.
## How to we fix this
We set `routing={'save_session': False}` on the `/web/image controller`.
- This prevents Odoo from sending the `Set-Cookie` header if the session is dirty or new.
- Even if Firefox sends the request without a cookie, Odoo won't "reply" with a new session ID.
- The user's legitimate session cookie remains untouched in the browser.
## Sources
- HTTPWG Decision (March 2024): https://github.com/httpwg/http-extensions/issues/2104
- Reverting RFC6265bis: https://github.com/httpwg/http-extensions/pull/2750
opw-5184217
opw-4698750
opw-5166151
Forward-Port-Of: odoo/odoo#242582
Forward-Port-Of: odoo/odoo#242061This fixes a crash that could happen when using autocomplete fields, such as Contact selection in CRM, while the dropdown was still loading results. Users can now continue working normally even when the browser is zoomed in or the dropdown becomes scrollable.
Original PR description
Steps to reproduce: 1. Ensure you have a good amount of contacts set up in your database 2. Ensure that you have an IAP Account setup for the service "Partner Autocomplete" 3. Zoom in on your browser…
Steps to reproduce: 1. Ensure you have a good amount of contacts set up in your database 2. Ensure that you have an IAP Account setup for the service "Partner Autocomplete" 3. Zoom in on your browser to at least 150% AND/OR make your browser window incredibly short 4. Go to the CRM app 5. Go into the form view of an opportunity 6. Type 3 characters or more into the 'Contact' field 7. Observe the error An Unhandled Promise error could occur if, after typing more than 3 characters in an autocomplete field, the dropdown is scrollable, and Partner Autocomplete finishes loading before the normal autocomplete does. In this scenario, normal autocomplete is still loading and has not rendered it's options. This causes a `null` element to be passed [`scrollTo()`](https://github.com/odoo/odoo/blob/555df96ac87a51405767c32f0396f762d458fd29/addons/web/static/src/core/utils/scrolling.js#L80), which causes an error when it tries to access `element.parentElement`. This change ensures that this scenario is properly handled and does not cause the database to crash. opw-5491270
This fix prevents Safari users from seeing an error when opening or editing collaboratively updated rich-text descriptions. It keeps the previous valid text selection when Safari reports an unusable one, improving reliability for cross-browser collaboration.
Original PR description
Before this commit: safari returns invalid document in collaboration, typically when a chrome user is sending history steps with undo. Reproduction steps: 1. In chrome, use an existing task with…
Before this commit: safari returns invalid document in collaboration, typically when a chrome user is sending history steps with undo. Reproduction steps: 1. In chrome, use an existing task with empty description or create a task in the project (first create the task title in the kanban view, then click edit), enter 4 lines of text 2. In one of the middle lines, delete one character --> undo --> add a new character 3. Save the task, open the task in Safari incognito, log in as demo (not admin), go to the task and click the description field 4. TraceBack: IndexSizeError: The index is not in the allowed range. After this commit: we use the range of the DOM selection to set the offsets of activeSelection. If the DOM selection is too wrong to be corrected, e.g. the selection's anchor node isn't the same with range's start container (or end container if direction is right to left), we do not set new activeSelection but just return the previous activeSelection task-5428788 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247484 Forward-Port-Of: odoo/odoo#246056
This fix ensures sales orders show the correct delivered quantity when a point-of-sale order is partially refunded and marked to ship later. Businesses get more accurate order status and inventory-related information after refunds, reducing confusion for sales and fulfillment teams.
Original PR description
The qty_delivered on sale.order.line was not correctly computed when the original order was refunded with a ship later. Steps to reproduce: ------------------- * Create a sale order for 5 quantities of any product * Confirm the sale order * Settle the order in the PoS * At this point the qty_delivered on the sale order line is 5 * Now go back to the PoS and refund partially the order for 3 quantities and use the "Ship Later" option > Observation: The qty_delivered is 0 instead of 2 Why the fix: ------------ We group the pos.order.line by procurement group and then check if all pickings related to these lines are done before adding the qty to the qty_delivered. We also make sure to include the refund lines in the computation opw-5059560 Forward-Port-Of: odoo/odoo#245959 Forward-Port-Of: odoo/odoo#240945
This update fixes an issue where failure messages weren't shown when a quality check was marked as failed. The change ensures that the correct failure message appears immediately after a quality check is marked as failed, improving user feedback and process clarity. This was achieved by correctly passing the view to display the failure message.
Original PR description
*= quality_control, quality_mrp_workorder, mrp_workorder Currently, when a user fails a quality check using the quick-action button, the failure message defined for that quality control point isn’t…
*= quality_control, quality_mrp_workorder, mrp_workorder Currently, when a user fails a quality check using the quick-action button, the failure message defined for that quality control point isn’t shown. **Steps to produce:** * Install `Quality` and `Manufacturing` with demo data * Go to MRP > Configuration > Operations > Manual Assembly * Create a pass/fail quality point with a failure message * Create and confirm an MO for `Table Top` * Go to Shop Floor > Activate work centers if inactive > Manual Assembly * Fail the assembly using the quick-action button Replication video: [Link](https://drive.google.com/file/d/1gBHrvQEAavhjU4lS-bKQHQjAa9qDHj6-/view?usp=sharing) **Observed Behavior:** * No failure message is displayed when the quality check is failed. **Root cause:** * This happens because pressing the quick-action button triggers `failCheck` [1] , which calls `doActionNext` [2], which then runs the server function `action_fail_and_next` [3]. That function sets `quality_state = fail` and calls [4] to get the view. But since [3] wraps that view inside a dictionary, the check in [5] never passes, so the message never appears. **Solution:** * Pass the view correctly to display the failure message. Since the quick action already marks the quality state as failed we can hide the Confirm and Back buttons by passing the context and checking it in the view to show a single OK button, similar to earlier versions. **Before:** <img width="1673" height="813" alt="image" src="https://github.com/user-attachments/assets/029e347b-5f2c-463a-833e-3b55677137b6" /> **After:** <img width="1687" height="829" alt="image" src="https://github.com/user-attachments/assets/e4c85093-ea0d-44ca-bc9c-0fab5ac08fbc" /> [1]: https://github.com/odoo/enterprise/blob/59c06537d82fedd1916b7aeb808dc73904f6a751/quality_mrp_workorder/static/src/mrp_display/quality_check.js#L83-L86 [2]: https://github.com/odoo/enterprise/blob/59c06537d82fedd1916b7aeb808dc73904f6a751/mrp_workorder/static/src/mrp_display/mrp_record_line/quality_check.js#L147-L163 [3]: https://github.com/odoo/enterprise/blob/59c06537d82fedd1916b7aeb808dc73904f6a751/quality_mrp_workorder/models/quality.py#L86-L89 [4]: https://github.com/odoo/enterprise/blob/59c06537d82fedd1916b7aeb808dc73904f6a751/quality_mrp_workorder/models/quality.py#L48-L68 [5]: https://github.com/odoo/enterprise/blob/19.0/mrp_workorder/static/src/mrp_display/mrp_record_line/quality_check.js#L154-L161 opw-5403465 Forward-Port-Of: odoo/enterprise#102095
This update fixes an issue where the XML export for Belgium VAT listings was incomplete, only including the initial batch of partners. The change adjusts the export process to ensure all partners, regardless of the 'Load More' setting, are correctly included in the generated XML file. This improves the accuracy of VAT reporting.
Original PR description
# Steps to reproduce: * Install **Accounting** and **l10n_be_reports**. * Enable **debug mode**. * Go to **Accounting → Reporting → Belgium → Partner VAT Listing**. * Create invoices with invoice…
# Steps to reproduce: * Install **Accounting** and **l10n_be_reports**. * Enable **debug mode**. * Go to **Accounting → Reporting → Belgium → Partner VAT Listing**. * Create invoices with invoice lines with no product set on it, just a label, so that **more than 10 Belgian partners** appear in the report and ensure each partner has a **VAT number**. * Open the report **Options** tab and set **Load More Limit** to **5**. * Click **Load More** until all partners are visible. * Click **Returns** and create a return for the month you have created invoices for, and submit it. * Download the generated XML. # Observed behavior: * The XML file contains only the first batch of partners. * Partners shown after clicking **Load More** are missing from the export. # Cause: * In v17, the XML export button was defined as: https://github.com/odoo/enterprise/blob/42ef1fe589fc4e7fe4b611736253251c44506578/l10n_be_reports/models/partner_vat_listing.py#L53-L59 * This meant clicking the button would go through the [export_file](https://github.com/odoo/enterprise/blob/42ef1fe589fc4e7fe4b611736253251c44506578/account_reports/models/account_report.py#L4927) method, which sets `options['export_mode'] = 'file'` before calling the export function. The test in v17 explicitly sets `export_mode = 'file'` to simulate what `export_file` does in production. * In v19, the architecture changed: - The XML export is now triggered via the account.return workflow and a submission wizard [1.](https://github.com/odoo/enterprise/blob/19.0/l10n_be_reports/wizard/vat_listing_submission_wizard.py) - The wizard's `print_xml` method calls [_get_closing_report_options()](https://github.com/odoo/enterprise/blob/19.0/account_reports/models/account_return.py#L1601) which does NOT set `export_mode = 'file'`. - The controller then calls `dispatch_report_action(options, file_generator)` directly, bypassing `export_file`. * Why the test changed: - In v17 test: `export_mode = 'file'` was set to mimic the `export_file` → `partner_vat_listing_export_to_xml` flow. - In v19 test: `export_mode = 'file'` should NOT be needed in the test because the fix is to set `export_mode = 'file'` inside `partner_vat_listing_export_to_xml` itself. # Fix: * Enable **export mode** when generating the XML. * Ensures all partners are included regardless of the load limit. opw-5494247
This update corrects an issue where Modelo 390 reports for past years were generating empty BOE files. The fix ensures the report period is correctly identified, pulling accurate data for the specified year from the Spanish tax agency. This resolves a reporting discrepancy impacting tax compliance.
Original PR description
### Issue: When exporting Modelo 390 reports for a past year, the BOE file was empty — all values were 0 ### Cause: In `export_boe()`, the `report_lines` were get based on the `section_report`…
### Issue: When exporting Modelo 390 reports for a past year, the BOE file was empty — all values were 0 ### Cause: In `export_boe()`, the `report_lines` were get based on the `section_report` options However, `section_reports` do not store the date or return periodicity of the selected report As a result, using their options always fetched data for the current period instead of the specified year ### Note: `_generate_mod_390_page2()` also had issues: some lines were missing or incorrectly indexed The mod 360 format, it strict in the structure with specific index so it may produce invalid documents The latest documentation for mod 390: https://sede.agenciatributaria.gob.es/static_files/Sede/Disenyo_registro/DR_300_399/archivos_25/dr390e2025.xlsx ### Steps to reproduce: - Install `l10n_es_reports` and switch to ES Company - Create an Invoice and a Bill (Any product, Price: 100.00, Tax: 21%, Invoice Date: 01/01/2025) - Open Tax Return, switch to Mod 390, and set year to 2025 - You should see data in the 2 first sections - Use the gear icon, and download the BOE - Use the gear icon to download the BOE, fill the wizard (Natural Person – Name: Test, Principal activity: Test, Activity Code: 12345), and generate the file Before the fix: all values in the BOE were 0 instead of matching the report opw-5457374 Forward-Port-Of: odoo/enterprise#106676 Forward-Port-Of: odoo/enterprise#104928
This update resolves a bug preventing users from installing modules after setting up a Belgian company with the account_accountant module. The issue stemmed from a registry reload delay during module installation, now corrected to ensure proper module installation.
Original PR description
Encountered this bug while trying to reproduce a bug from one of my ticket. **STEP TO REPRODUCE** On a fresh db with module account_accountant. 1. Create a new company with country set to Belgium. After l10n_modules are install, and the chart template loaded: 2. Try installing a module, and notice you can't. **CAUSE** button_install() doesn't reload the registry, so the sepa modules states are set to `to install` but are not install until the registry is reloaded, which doesn't happen on its own. button_immediate_install() does the same as button_install(), and reload the registry which trigger the actual installation process. Indirectly related to opw-5880247: when trying to reproduce the bug, I had to create a company, setup a chart of account on it. I created a belgium company -> setting it to belgium trigger the button_install, preventing me from installing payment module afterward.
This update resolves a problem where long item codes were causing errors in the AvaTax integration. The system now automatically limits item codes to 50 characters, ensuring successful tax calculations and preventing transaction failures. This improves the reliability of our tax processing.
Original PR description
Link to Avalara (Avatax) documentation: https://developer.avalara.com/api-reference/avatax/rest/v2/models/LineItemModel/ Expected Behaviour: The itemCode sent to the AvaTax API should be 50…
Link to Avalara (Avatax) documentation: https://developer.avalara.com/api-reference/avatax/rest/v2/models/LineItemModel/ Expected Behaviour: The itemCode sent to the AvaTax API should be 50 characters or fewer to comply with Avalara's field length constraints. Actual Behaviour before the Fix: When an itemCode exceeded 50 characters, the system attempted to send the request as-is. This resulted in the AvaTax API returning an error, causing the transaction or tax calculation to fail. Behaviour with the Fix: The system now ensures that the itemCode adheres to the 50-character limit before the API call is made, by trancating the code to the first 50 characters if it exceeds 50 characters. This prevents API rejection and ensures successful tax processing for items with long identifiers. Steps to reproduce: 1. Create or select a product/item with a reference (or barcode if using UPC) longer than 50 characters. 2. Trigger an action that calculates tax via the AvaTax integration (e.g., creating an invoice or updating a line item). 3. Observe the API response. - Before fix: API returns a validation error regarding the itemCode length. - After fix: Request is successful as the itemCode is properly handled/validated. opw-5406451 Forward-Port-Of: odoo/enterprise#106085 Forward-Port-Of: odoo/enterprise#105017