Monday, September 14, 2026
21 changes · saas-19.4
Enhancements to existing features
Accounting reports can now use a consolidation availability setting so they only appear when multiple companies are selected and the report is affected by more than one company. This helps business users see consolidation-related reports only in relevant multi-company contexts, reducing clutter in normal reporting.
Original PR description
With the related enterpise pr, add a new variant availability "consolidation" which makes the report visible only if it is impacted by several companies (company selector has at least 2 companies selected and options['companies'] is more than 1. This new type of variant should prioritize the other types in the selection. task-6398453 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286730
Financial reports now better adapt when users work across multiple companies, showing consolidation-specific variants only when several companies are selected. This helps multi-company users see the most relevant reports while avoiding variants that only match secondary companies.
Original PR description
1) Add a new variant availability "consolidation" which makes the report visible only if it is impacted by several companies (company selector has at least 2 companies selected and options['companies'] is more than 1. This new type of variant should prioritize the other types in the selection. 2) Activate by default the "consolidation" filter in multi-company. 3) In multi-company, the variants of availability type "Coa match" or "Country match" should only be visible if they match the main company, not the secondary ones. task-6398453 Forward-Port-Of: odoo/enterprise#130484
Resolved issues and error corrections
Maintenance requests must now have both a start and end date for scheduled work, or neither. This prevents the manufacturing planning view from failing when an incomplete maintenance schedule is entered, helping teams keep work order planning accessible.
Original PR description
#### Issue: Opening the MRP planning view could raise a traceback when a maintenance request had a `schedule_end` but no `schedule_date`. `TypeError: '<' not supported between instances of 'NoneType'…
#### Issue: Opening the MRP planning view could raise a traceback when a maintenance request had a `schedule_end` but no `schedule_date`. `TypeError: '<' not supported between instances of 'NoneType' and 'datetime.datetime'` #### Steps to reproduce: 1. Install maintenance, mrp, and mrp_maintenance. 2. Create a work center. 3. Create a maintenance request linked to that work center. 4. set a `Scheduled end` and Leave `Scheduled Date` empty. 5. Go to MRP > Planning > Work Orders. #### Cause: `maintenance.request` stores `schedule_end` as a writable field, but no constraint enforces that `schedule_date` and `schedule_end` must be set together. Later, `mrp_maintenance` in `_get_maintenances_intervals` fetches maintenance intervals for the gantt view without filtering null bounds. If a request has `(schedule_date, schedule_end)` = `(False, datetime)`, that interval is passed to `Intervals(...)`, which crashes when comparing `None` with a `datetime`. #### Fix: Add a constraint on `maintenance.request` to require `schedule_date` and `schedule_end` to either both be set or both be empty. Also filter out incomplete intervals in the MRP maintenance gantt query in this enterprise PR: https://github.com/odoo/enterprise/pull/117710 opw-6225772 enterprise PR: https://github.com/odoo/enterprise/pull/117710 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265838 Forward-Port-Of: odoo/odoo#265208
This fix prevents an error when users open Studio's list editor for sales order lines on an existing sales order. Businesses can now customize columns and add fields to the order line list without interruption.
Original PR description
Before this change: When opening Studio on a Sales Order with existing line items, clicking "Edit List View" on the order lines component triggered a JavaScript error. This prevented users from customizing columns or adding custom fields to the sale order line list view. To reproduce: 1. Open the Sales app and create a new Sales Order with at least one product line. 2. Toggle Studio on. 3. Select the Sale Order Lines list component and click "Edit List View". After this change: Clicking "Edit List View" on sale order lines in Studio works as intended without throwing errors, allowing standard view customizations. opw-6545970
This fixes an issue where users could not open the list editor for sales order lines in Studio when a sales order already had products. Businesses can now customize sale order line columns and add fields without interruption.
Original PR description
Before this change: When opening Studio on a Sales Order with existing line items, clicking "Edit List View" on the order lines component triggered a JavaScript error. This prevented users from customizing columns or adding custom fields to the sale order line list view. To reproduce: 1. Open the Sales app and create a new Sales Order with at least one product line. 2. Toggle Studio on. 3. Select the Sale Order Lines list component and click "Edit List View". After this change: Clicking "Edit List View" on sale order lines in Studio works as intended without throwing errors, allowing standard view customizations. opw-6545970
This update prevents crashes when users edit or select product images through the media dialog. It restores a smooth image-editing flow after recent editor changes caused errors in places such as Point of Sale product setup.
Original PR description
**Description of the issue/feature this PR addresses:** When opening the media dialog to edit an image or when saving a selected image, the UI crashes with strict prop validation and undefined…
**Description of the issue/feature this PR addresses:** When opening the media dialog to edit an image or when saving a selected image, the UI crashes with strict prop validation and undefined property errors. This occurs due to recent refactoring in the `html_editor` framework. First, the base `MediaDialog` now strictly requires the `document` object as a prop. Because it was omitted in the payload, Owl's validation rejected the component. Second, the dialog's state management was updated, meaning `activeTab` is no longer accessed via `this.state.activeTab`, but rather via the `this.activeTab()` method. This commit fixes these issues by passing `window.document` into the dialog's initial props and when calling `renderMedia`. It also updates how we access activeTab. **Steps to reproduce:** - POS > Products > Products > choose any product > click the ‘edit’ button in the image > search something, e.g. ‘burger’ > select one of the resulting images **Current behavior before PR:** - Errors either after clicking the 'edit' button or after selecting one of the resulting images **Desired behavior after PR is merged:** - No errors when editing or saving images opw-6445843
The media tools now handle empty or incomplete image attachments without crashing. This keeps the Media Dialog and Chatter usable even when an upload is interrupted or an email creates a malformed attachment.
Original PR description
Problem: Interrupted uploads or malformed email payloads can create 0-byte binary `ir.attachment` records where the `checksum` is `False`. Accessing the computed `image_src` field on these records…
Problem:
Interrupted uploads or malformed email payloads can create 0-byte binary `ir.attachment` records where the `checksum` is `False`. Accessing the computed `image_src` field on these records triggers a `TypeError: 'bool' object is not subscriptable` when attempting to slice `attachment.checksum[:8]`. This crashes the Media Dialog and Chatter.
Purpose:
Add a fallback boolean guard to `attachment.checksum` inside `_compute_image_src` so that empty attachments evaluate safely to a string ('0') instead of raising a traceback, allowing the UI to render gracefully.
Steps to Reproduce on Runbot:
1. Go to Settings > Technical > Database Structure > Attachments.
2. Create a new record: Name: `test.png`, Type: `File` (Binary), File Content: [leave empty], Is public document: Checked.
3. Open any record with a Chatter (e.g., Contact or CRM Lead) and click "Insert Image" to open the Media Dialog.
4. The system attempts to evaluate `image_src` and throws the `TypeError`.
Notes:
A test (`test_compute_image_src_empty_checksum`) was added to `test_ir_attachment.py`
opw-6482674
Forward-Port-Of: odoo/odoo#287758
Forward-Port-Of: odoo/odoo#287444Fixed a stock delivery issue where items packed into separate packages could appear under the same package on the final delivery when related moves were merged. This helps warehouse teams keep package tracking accurate during multi-step deliveries and avoids confusion at shipment time.
Original PR description
Steps to reproduce --- 1. Set the warehouse to deliver in 3 steps. 2. Create a delivery pick not tied to a procurement group (not from a sale order) with a consumable product, and validate it. 3. On…
Steps to reproduce --- 1. Set the warehouse to deliver in 3 steps. 2. Create a delivery pick not tied to a procurement group (not from a sale order) with a consumable product, and validate it. 3. On the pack transfer, put the goods in a package and validate. 4. Duplicate the pick, validate it, put its goods in a second package on the pack transfer, and validate. 5. Open the final delivery: both lines sit in the same package instead of one line per package. Issue --- The two picks share no procurement group, so their delivery moves merge onto a single move keyed by partner. Validating the second pack tops up that already partially reserved move: for a consumable, `_action_assign` builds its lines from `_get_available_move_lines`, which reports the availability of every upstream package without discounting what the move already reserved. https://github.com/odoo/odoo/blob/05af9e6877fd0f044bb46c983fe7300eb1db9307/addons/stock/models/stock_move.py#L1907-L1909 The package already reserved on the first line is therefore offered again and reused, collapsing both lines onto one package. The reserved-product branch below already subtracts the move's own reservation before allocating; doing the same here leaves each package on its own line. opw-6498532 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287935 Forward-Port-Of: odoo/odoo#284956
Hong Kong payroll and batch payment exports now handle missing employee ID details without crashing and validate required AutoPay information before generating files. This helps users catch missing bank reference or identification data early, reducing failed or incomplete HSBC/Hang Seng payment submissions.
Original PR description
When both identification_id and passport_id are empty (False), re.sub() receives a bool and raises: TypeError: expected string or bytes-like object, got 'bool'. Fall back to an empty string and normalize the passport fallback the same way as the HKID. The HSBC/Hang Seng (l10n_hk_mri) AutoPay file format requires a Payment Set Code, a First Party Reference and a per-payment identifier (HKID or passport number); without them the file was silently generated with missing data. Validate these in l10n_hk.bank.format._validate() so the check is shared by both consumers of the format: the payroll payment report and the generic batch payment export. Add the matching Party Reference check to l10n_hk_payment_autopay's journal validation so batch payments get a proper RedirectWarning to the journal instead of a bare error. Task-6536846
Mexican electronic payment complements now report tax amounts using the correct decimal precision for the payment currency. This prevents valid payments from being rejected by the PAC/SAT validation, especially for MXN payments and foreign-currency invoice settlements.
Original PR description
The 'ImpuestosP' node of the payment complement (Pagos 2.0) is reported with 6 decimals while the SAT expects the amounts to be expressed with the number of decimals supported by the currency of the…
The 'ImpuestosP' node of the payment complement (Pagos 2.0) is reported with 6 decimals while the SAT expects the amounts to be expressed with the number of decimals supported by the currency of the payment ('MonedaP'), as published in the 'c_Moneda' catalog, for example 2 decimals for MXN.
Steps to reproduce:
- Have an MX Company setup with Quadrum as PAC.
- Create and sign a customer invoice in MXN with a 16% IVA tax.
- Register a full payment and send the payment complement to the PAC.
Issue:
Payment will be rejected
```
Code : CRPER654
Message : El importe del campo BaseP que corresponde a Traslado, no tiene la cantidad de decimales que soporta la moneda (MonedaP)
```
Analysis:
Quadrum recently aligned its validation on that rule and now rejects the document having fields with too much decimals and, currently, fields like BaseP, ImporteP are pinned to 6 decimals in the template.
Reporting them with the decimals of the payment currency is not enough when the payment settles a document expressed in another currency: those amounts are also compared with the ones of the related documents converted with 'EquivalenciaDR', and the PAC expects the values truncated or rounded
```
Code : CRP20274
Extra Info : Traslados: La sumatoria de ImporteDR es mayor al ImporteP 1.30.
Valores minimos permitidos: Truncado: 1.29 o redondeado: 1.3
```
opw-6561617
Forward-Port-Of: odoo/enterprise#131343
Forward-Port-Of: odoo/enterprise#131267This fixes an issue where some Belgian customers or suppliers could no longer be reached through Peppol after their identifier type changed. Odoo now rechecks the alternative Belgian Peppol identifier when sending, improving the chances that electronic invoices reach the correct recipient.
Original PR description
Some partners were registered on Peppol with EAS 9925 (Belgian VAT) but have since moved to 0208. They became unreachable via Peppol because we never check if they exist on the network with EAS 0208, which makes their status `not_valid`. This fix forces the re-checking of the status with EAS 0208 for partners having EAS 9925 and a `not_valid` status. task-6296017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278919 Forward-Port-Of: odoo/odoo#270742
Large blog imports could fail or finish incomplete when many links needed updating. This change processes link replacements in smaller batches, helping imports complete reliably without timing out.
Original PR description
This commit fixes an issue where huge blog requests were timing out due to large replacements for links that weren't controlled with our batch creation wrapper. This resulted in incomplete imports. The fix is to put the text replacements in the batch create wrapper which will avoid timeouts and let it continue reliably.
This fix ensures that when a past point-of-sale order is later invoiced, the Spanish VeriFactu tax report cancels the original simplified receipt rather than the newly created full invoice. This prevents incorrect cancellation data from being sent to AEAT and keeps fiscal records aligned with the actual sale flow.
Original PR description
When creating an invoice for a previous POS order, the data sent to AEAT cancels the full invoice instead of the order's simplified invoice. Steps to reproduce: - Open a POS and make a sale without invoicing it; - In the POS, go to the Order tab; - Select the order and fully invoice it. Issue: The AEAT cancellation line added to the pos order actually cancels the full invoice just created [opw-6471927](https://www.odoo.com/odoo/project/49/tasks/6471927) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284277
General Ledger exports now use the same search behavior as the on-screen report. This ensures that when users filter account lines, the exported file includes the same results they see in the interface, reducing confusion and reconciliation errors.
Original PR description
When applying a search filter in the General Ledger, the lines displayed in the UI differ from the ones exported. The discrepancy comes from the fact that the UI search bar filters lines using a simple "contains" logic on the displayed line name, while the backend export relies on the account model’s `_name_search` behavior, just as in the chart of accounts. For example, searching for "40" displays the accounts 400000, 400010, and 124000 but the last one (124000) is not is in the export results. task: 5917435 Forward-Port-Of: odoo/enterprise#131011 Forward-Port-Of: odoo/enterprise#107928
This fix prevents Taiwan B2B invoices with down payments from being rejected by ECPay because of small tax rounding differences. E-invoices now report the same tax amounts as the posted invoice, reducing failed submissions and mismatched tax records.
Original PR description
Current behavior: -- Sending a B2B invoice that deducts a down payment is rejected by ECPay with "(item tax discrepancy exceeds 1 NT$)", so the invoice cannot be issued at all. When it is accepted,…
Current behavior: -- Sending a B2B invoice that deducts a down payment is rejected by ECPay with "(item tax discrepancy exceeds 1 NT$)", so the invoice cannot be issued at all. When it is accepted, the tax on the e-invoice can still differ from the tax the invoice books. Expected behavior: -- The invoice is accepted, and the tax reported on the e-invoice is the one the invoice booked. Steps to reproduce: -- - Set a company up in Taiwan (TWD) with the ECPay credentials filled in - Create a sale order of 190,630 for a customer with a VAT number - Invoice a 50% down payment through the down payment wizard, then a 30% one, and post both - Invoice the remainder and post it - Send the final invoice to ECPay Cause of the issue: -- _l10n_tw_edi_prepare_item_list rebuilt the tax from the raw amount of every line and rounded that total once. Both steps also disagree with the invoice. Negative lines resulting from downpayments seem to be more strictly checked on ECPay and taxes cannot be re-derived easily by ECPay's system. There is a also a relevant but slightly different issue where the invoice amount is calculated differently but the ECPay page will show a different value. e.g. the invoice rounds each computation key on its own: 50.00 - 16.50 = 33.50 rounds to 34 where the invoice books 50 - 17 = 33. No issue was detected for purely positive lines (a transaction with different products but no downpayment) Fix: -- Use the tax amount the line carries when it has one, and fall back to the raw amount otherwise, so the payload reports what the invoice booked. Send the tax of each line in the ItemTax field. Let ECPay derive its own per-item tax and checks it against the declared total for purely positive lines, and recalculate them for negative so the rounding difference between them is spread one unit at a time across the lines, the way ECPay distributes it. opw-6424237 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281928
This fix improves copy and paste behavior in the HTML editor when working with list items that contain nested lists. Users can now copy either a full list item or selected parts of it without accidentally losing the outer list or including unselected nested content.
Original PR description
Problem: Copying content from a list item containing a nested list can either include the unselected nested list or lose part of the copied content. Solution: - Detect whether the whole `<li>` was selected before copying the full list item with its nested lists. - When only part of the list item is selected, copy only the selected content and rebuild the required `<li>` wrapper. - Apply this logic only to list items with multiple top-level children. Steps to reproduce: - Add bullet list with nested list. - CTRL+A - Press Enter twice to create new paragraph. - Paste. - Observe the outer list is lost. task-6438347 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281205
Creating multiple helpdesk teams with website forms now reuses the same website Help menu instead of adding duplicate menu entries. This keeps the website navigation clean and prevents confusion for visitors and administrators.
Original PR description
Currently on creating new helpdesk team everytime a new website menu is created. ### **Steps to Reproduce:** 1) Install website_helpdesk 2) Navigate to `Helpdesk>Configuration>Helpdesk Team`. 3)…
Currently on creating new helpdesk team everytime a new website menu is created. ### **Steps to Reproduce:** 1) Install website_helpdesk 2) Navigate to `Helpdesk>Configuration>Helpdesk Team`. 3) Create 2 helpdesk team with `Website Form` option enable. 4) Navigate to Website. ### **Observed Behavior:** Two Help menus are created. ### **Expected Behavior:** Multiple menus should not be created. ### **Root Cause:** The menu creation logic relies on the following [condition](https://github.com/odoo/enterprise/blob/b66097122ba3a758734ac6fb2b26579c35cb72c2/website_helpdesk/models/helpdesk.py#L111-L112) `team_count_by_website` is built from `_read_group(..., ['website_id'], ...)`, which keys its result by the `website_id` *recordset*, not its id. Looking it up with `team_count_by_website.get(website.id, 0)` therefore always misses and falls back to `0`, so `team_count <= 1` is always `True` regardless of how many teams already exist for that website. The only thing left guarding menu creation is `any(team.website_menu_id for team in teams)`, which only looks at the teams in the current create/write call, not every team on that website. So saving a second team in a separate call always creates another menu. ### Fix: Make the website menu a resource shared by every team with the website form enabled on a given website, instead of "owned" by whichever team created it: - Before creating a new menu, look up other teams (active or archived) that already point to a menu, matched through the `website_menu_id` relation between teams rather than a hardcoded `/helpdesk` URL, so a customized menu URL doesn't cause a duplicate to be created. Reuse that menu when found. - Only delete a menu once no team (active or archived) still references it, checked before removing a team's own reference. **opw-6303846** Forward-Port-Of: odoo/enterprise#130401 Forward-Port-Of: odoo/enterprise#121120
This fix prevents the Project app from crashing when users open a saved My Tasks favorite in the Pivot view. It ensures personal task stages are handled correctly in pivot reporting, so users can continue analyzing their tasks without interruption.
Original PR description
Since the introduction of `read_grouping_sets` for Pivot views, opening the Pivot view from a saved favorite filter can crash. ### **Steps to reproduce:** - Install Project. - Open My Tasks. - Save…
Since the introduction of `read_grouping_sets` for Pivot views, opening the Pivot view from a saved favorite filter can crash. ### **Steps to reproduce:** - Install Project. - Open My Tasks. - Save the current filter as a favorite. - Switch to the Pivot view. ### **Error:** ``` ValueError: Cannot convert project.task.personal_stage_id to SQL because it is not stored. ``` ### **Root Cause:** Since [commit](https://github.com/odoo/odoo/pull/194413/changes/166a546ec52784c413f5b5d7d29af89d618d6519), Pivot views use `_read_grouping_sets` instead of `_read_group`. `project.task` only remaps `personal_stage_type_id` to the stored `personal_stage_type_ids` in [_read_group](https://github.com/odoo/odoo/blob/5f6fb63d5d7585805642c702d096b2f882e73761/addons/project/models/project_task.py#L2169-L2179), so the remapping is bypassed for Pivot views. The ORM then attempts to group by the non-stored `personal_stage_type_id` relation, leading to the SQL conversion error. ### **Fix:** Mirror the remapping logic in `_read_grouping_sets` so Pivot views use `personal_stage_type_ids` before the ORM generates the SQL query. **opw-6306389** Forward-Port-Of: odoo/odoo#272985
This fixes a mobile and tablet issue where selecting a file inside an editable list could unexpectedly trigger an autosave and close the row being edited. Users can now add files to these list rows without their in-progress edits being silently discarded.
Original PR description
The form view autosaves on 'visibilitychange' (e.g. when the user switches tab/app) to avoid losing unsaved changes. On mobile, opening the native file picker for a binary field also fires 'visibilitychange', which triggered this autosave. When that binary field was part of an editable x2many list, the autosave forced the row out of edition before the file could be selected, silently discarding the edition in progress. Skip the autosave when a x2many field of the root record currently has a row in edition. Can be reproduced in eLearning > course > content > Additional Resources, on mobile devices (must force "desktop mode" in the browser), and on tablets. opw~6517735 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#287855 Forward-Port-Of: odoo/odoo#287581
Blog imports now reliably match posts to the correct blog even when multiple blogs share the same name. The change uses external identifiers to avoid mix-ups, improving accuracy when generating or migrating website blog content.
Original PR description
Blogs with the same name was creating a conflict in the mapping of id to created odoo blog, which meant that the blog post matching with the blog itself was failing. This fix introduces external ids for the blogs which is the id of the foreign website, making it much easier to keep track of the mapping between the external records and the created odoo records.
The delivery method wizard now recalculates shipping charges when a user manually changes the shipment weight. This prevents rule-based delivery fees from being added at an incorrect zero price, improving quotation and order accuracy.
Original PR description
Steps to reproduce ------------------ - Install `website_sale_stock` and `sale_management` module. - Create a product. - Create a rule-based delivery method with: - In Pricing tab click add a line -…
Steps to reproduce ------------------ - Install `website_sale_stock` and `sale_management` module. - Create a product. - Create a rule-based delivery method with: - In Pricing tab click add a line - condition: `Quantity >= 0` - variable factor: `weight` - price per unit: 2 - Create a quotation containing the product. - Open the delivery method wizard by clicking into `Add Shipping` - Select the rule-based delivery method. - Change the total weight from 0 to 10. - Add the delivery method. Issue ----- - Changing the total weight does not recompute the delivery price. - The delivery line is added with a price of 0 instead of 20. Cause ----- The delivery wizard defines `_onchange_carrier_id` for both `carrier_id` and `total_weight` https://github.com/odoo/odoo/blob/9860ba5a593c5e7723494674b62890d16ae1a9a8/addons/delivery/wizard/choose_delivery_carrier.py#L41-L50 The call flow is expected to be: `total_weight` change -> `_onchange_carrier_id` -> `_get_delivery_rate` -> `rate_shipment` `_get_delivery_rate` passes the manually entered weight through the `order_weight` context key: https://github.com/odoo/odoo/blob/9860ba5a593c5e7723494674b62890d16ae1a9a8/addons/delivery/wizard/choose_delivery_carrier.py#L87-L90 The rule-based carrier gives this context value priority over the saved order weight and the weight computed from order lines: https://github.com/odoo/odoo/blob/9860ba5a593c5e7723494674b62890d16ae1a9a8/addons/delivery/models/delivery_carrier.py#L588-L594 For example, with `total_weight = 10` and a price factor of 2, the expected calculation is: `delivery_price = 0 + 2 * 10 = 20` However, the pickup-location implementation added an override in `website_sale_stock` that declared only `carrier_id` as an onchange trigger: https://github.com/odoo/odoo/blob/0da3259034ff3b2b79f417df53969fe017207195/addons/website_sale_stock/wizard/choose_delivery_carrier.py#L13-L16 Since the override uses the same method name, its decorator replaces the base onchange specification. Therefore, changing `total_weight` does not call the method and the initial `delivery_price = 0` is kept. This does not occur in saas-19.2. because `website_sale_stock` does not override the delivery wizard there. The base method remains registered for both `carrier_id` and `total_weight`: The conflicting override was introduced later in this [commit](https://github.com/odoo/odoo/commit/0da3259034ff3b2b79f417df53969fe017207195) from saas-19.3 Fix --- Add `total_weight` to the `website_sale_stock` onchange decorator so the inherited delivery-rate computation runs when the user edits the weight. --- opw-6516301 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285864