Daily updates from Odoo
Friday, August 8, 2025
25 changes · saas-18.3
Resolved issues and error corrections
Refund payments with withholding taxes now use the correct refund tax allocation, so tax reports reflect amounts in the right direction. The change also prevents payment editing problems when withholding tax lines use the company's default transfer account.
Original PR description
Currently, there is an issue with how the repartition line is selected when registering payment for a refund for withholding taxes. It would select the invoice repartition line, causing the tax amounts to affect the tax report in the wrong way. - It is not setting the is_refund param on the base line, leading to incorrect lines on the payment's entry. - Detecting if we are a refund is tricky with the current system, which is based on the wizard payment_type. It requires some changes in order to be able to have withholding lines with a type_tax_use which doesn't match the payment wizard. Also fixes an issue where a payment could not be edited after creation if the withholding tax line is using the company's default transfer account. In this case, the lines would be counted as counterparts and cause issues. As the account on the base line does not matter that much, we decided to use the simple solution of blocking its usage. Forward-Port-Of: odoo/odoo#220509
The Spanish VeriFactu electronic invoicing module can now be installed even if certain optional tax records have been removed. This prevents installation failures for affected Spanish accounting setups and helps businesses continue enabling compliance features without manual data repair.
Original PR description
In case some taxes for which we specify Applicability info (field `l10n_es_applicability`) do not exist the module can not be installed. I.e. the `_l10n_es_edi_verifactu_post_init_hook` raises. Reproduce 1. Install `l10n_es` without installing `l10n_es_edi_verifactu` 2. Delete tax with xmlid `account_tax_template_s_iva_e` (sales tax with description "VAT 0% export (services)") 3. Install `l10n_es_edi_verifactu` 4. A "Validation Error" appears ``` The operation cannot be completed: - Create/update: a mandatory field is not set. - Delete: another model requires the record being deleted. If possible, archive it instead. Model: Tax (account.tax) Field: Tax Name (name) ``` opw-5003231 opw-4996685 opw-4999922 Forward-Port-Of: odoo/odoo#222313 Forward-Port-Of: odoo/odoo#222225
Invoice PDFs now handle very long product descriptions more reliably when line-item tables continue onto additional pages. This prevents text from overlapping the table header, making printed invoices clearer and more professional for customers.
Original PR description
**Steps to reproduce**: 1. Install the `account` module. 2. Create a Invoice using this any product. 3. add long descripition (approx. 40-45 lines). 4. Print the PDF of Invoice (via gear icon).…
**Steps to reproduce**: 1. Install the `account` module. 2. Create a Invoice using this any product. 3. add long descripition (approx. 40-45 lines). 4. Print the PDF of Invoice (via gear icon). **Observation**: The long product description overlaps with the table header when the table spans multiple pages in the generated PDF. **Issue**: wkhtmltopdf does not handle multi-page table headers properly by default. causing header/content overlap when the table breaks across pages. **Solution**: Apply a known wkhtmltopdf workaround by explicitly setting: `<thead style='display: table-row-group;'>` This ensures headers will not repeat same as this. [#53909](https://github.com/odoo/odoo/pull/53909) before: <img width="818" height="231" alt="image" src="https://github.com/user-attachments/assets/8bcc6ced-5911-4abd-b91e-97ffa8fb735e" /> after: <img width="821" height="253" alt="image" src="https://github.com/user-attachments/assets/2ccc6995-c239-4beb-8f68-53d548b7f2f2" /> opw-4982735 Forward-Port-Of: odoo/odoo#222286 Forward-Port-Of: odoo/odoo#221681
Survey invitation emails now respect the subject line configured on the email template instead of replacing it with the default survey subject. This ensures customized survey invitations keep the intended wording when users share surveys by email.
Original PR description
Description of the issue/feature this PR addresses: When a user updates the subject on a template used for a survey, it does not pull the subject from the template. It uses the default subject that…
Description of the issue/feature this PR addresses:
When a user updates the subject on a template used for a survey, it does not pull the subject from the template. It uses the default subject that is used when computing the subject for a survey email that is sent out. This bug came as a part of [this commit](https://github.com/odoo/odoo/commit/220e0271bf43e914950b8ae0d4a1cca5f3ea6d9c).
I've used an elif condition over here as opposed to calling super which was being done before so that the default of Participate to X survey still becomes the default subject.
opw-4654411
Steps to reproduce on runbot:
1. Go to mail templates and search for Survey
2. Open the Survey: Invite template
3. Update the subject on this template
4. Open the Surveys app and select any survey
5. Click on Share and then enable send by email
6. The subject here will default to "Participate to {Survey Name}"
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#219122
Forward-Port-Of: odoo/odoo#211153Manufacturing orders created manually in a 3-step warehouse setup now correctly increase the stock forecast for the final warehouse location. This helps planners see expected inventory accurately and avoid unnecessary replenishment orders.
Original PR description
### Steps to reproduce: - In the settings enable Multi-Steps Routes - Put your warehouse in manufacture in 3 steps - Create a storable product P - Create and confirm an MO for 1 unit of P - Go to…
### Steps to reproduce: - In the settings enable Multi-Steps Routes - Put your warehouse in manufacture in 3 steps - Create a storable product P - Create and confirm an MO for 1 unit of P - Go to Inventory > Operations > Procurement > Replenishment - Create a new one for P in WH/stock #### > The forecasted quantity in stock is still 0 but should be at 1, just as if the the MO had been generated using the replenishment for 1 unit ### Cause of the issue: When an MO is created using a procurement, a `location_final_id` is set to WH/Stock on the MO and propagated on the move for the finished product: https://github.com/odoo/odoo/blob/8d4e6df0c0ac5ebc6362f3578ae8cc8edf4a76f7/addons/mrp/models/stock_rule.py#L165 https://github.com/odoo/odoo/blob/8d4e6df0c0ac5ebc6362f3578ae8cc8edf4a76f7/addons/mrp/models/mrp_production.py#L1169-L1175 As such, even if the manufacturing is now handled in push, this move will contribute positively to the forecast in the `virtual_available` quantity of the product in WH/Stock bevause of the `location_final_id`. By contrast, if hte MO is created by hand, it does not bear a `location_final_id` so that the MO can only contribute to the stock forecast has been processed and the related internal transfer `WH/post-prod -> WH/Stock` is created. opw-4882390 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221462 Forward-Port-Of: odoo/odoo#221003
This update rolls back a previous web interface change that caused an unwanted horizontal scroll bar on form pages. The revert restores the prior behavior while the team prepares a better fix for editor avatars overlapping the status bar during scrolling.
Original PR description
This reverts commit 72acbe0 because of unexpected horizontal inner scroll on `o_form_sheet_bg` element. A better fix will be found in the futur.
Fixed an issue where products tracked by lot could be counted twice when a sales order with multiple lots was paid through Point of Sale. The order is now split correctly by lot, keeping delivered quantities accurate and preventing inventory discrepancies.
Original PR description
When creating a sale order for a product, confirming it, and then modifying the stock move to use 2 different lots. Then paying the order in the POS, the picking created for the pos order will have double qty Steps to reproduce: ------------------- * Create a product tracked by lot * Create 2 lots for that product * Create a sale order for that 3 quantity of that product * Confirm the sale order * Modify the stock move to use 2 different lots, for example: - Lot 1001: 2 units - Lot 1002: 1 unit * Pay the order in the POS * Check the picking created for the pos order > Observation: The picking created for the pos order has double the quantity for the lots. Why the fix: ------------ A PoS line can only hold one lot, so when we import a sale order with multiple lots, we need to split the line into multiple lines, each with a single lot opw-4804704 Forward-Port-Of: odoo/odoo#221625 Forward-Port-Of: odoo/odoo#217537
Fixes several self-ordering issues that could block tables or devices when payments failed, direct sales were synced, or orders were cancelled. It also makes ticket printing more reliable by printing preparation and customer tickets one after another.
Original PR description
*: pos_restaurant, pos_online_payment_self_order, pos_self_order When self-ordering is enabled and in pay after each mode, the table selection was handled via table_id fields, which caused issues…
*: pos_restaurant, pos_online_payment_self_order, pos_self_order When self-ordering is enabled and in pay after each mode, the table selection was handled via table_id fields, which caused issues when a customer had an issue with its payment and wanted to pay later. It was blocking the table with its order, so if another customer wanted to scan the same QR code, it would not be able to add anything to the cart. Now in pay after each mode, the table selection is handled via floating_order_name, which allows the order to be processed without blocking the table. This way, the table can be reused for another customer, and the order can be paid later. --- Regarding direct sale in `point_of_sale`, when a customer wanted to pay by card the order was synced with the server when the waiter clicked on the payment method, if the direct sale had no table and no floating order name, when synching on other devices the order was blocking them. Now if no table and no floating order name is set, when synching the order, the pos_reference is set to the floating_order_name, which prevents the order from blocking other devices. --- Regarding self order cancellation from a PoS, when the waiter was cancelling an order it was not synced with the self-order app, which caused the self-order app to keep the order in the cart, preventing the customer from starting a new order. --- Regarding self order ticket printing, when an order arrives on the PoS to be printed, we were trying to print the preparation ticket and the customer ticket at the same time, which caused issues with the printing. Now we printing them one after the other.
This update corrects how Malaysian e-Invoicing data is filled for foreign customers and consolidated invoices. It helps ensure invoices meet Malaysian reporting requirements and reduces the risk of submission errors.
Original PR description
## Before this commit: The `CountrySubentityCode` was computed by simply using the `state code` of the partner, without handling the following cases: - Non-Malaysian Partners: For partners located outside Malaysia, the format requires the `state name` to be passed instead of the `state code`. - Consolidation Entries: For consolidation invoices, a fixed value `17` should be passed as the `CountrySubentityCode`, regardless of the partner’s state. ## After this commit: The computation of `CountrySubentityCode` has been updated to handle both cases correctly: - For non-Malaysian partners, the `state name` is used. - For consolidation entries, the fixed value `17` is used. - For regular Malaysian partners, the `state code` continues to be used as before. This ensures compliance with Malaysian e-Invoicing specifications and prevents errors. > Task-4938198 Forward-Port-Of: odoo/odoo#222153 Forward-Port-Of: odoo/odoo#219201
This fix stops users from creating website menu structures that go deeper than the supported two levels, which previously caused some menu items to disappear from the site. It also enforces clearer rules around mega menus so website navigation remains predictable and easier to manage.
Original PR description
Steps to Reproduce: 1. Go to the website. 2. Create a new menu (e.g., 'Test 1') using the 'Edit Menu' option and add it under another menu (e.g., 'Contact Us'), creating a sub-menu. 3. Turn on the…
Steps to Reproduce:
1. Go to the website.
2. Create a new menu (e.g., 'Test 1') using the 'Edit Menu' option and add it under another menu (e.g., 'Contact Us'), creating a sub-menu.
3. Turn on the developer mode.
4. Go to Configuration -> Menus and add two menus (e.g., 'menu 1' and 'menu 2') under the new sub-menu (e.g., 'Test 1').
5. Notice that the two menus ('menu 1' and 'menu 2') are not visible on the website.
Description:
As per functional specifications, creation of multi-level sub-menus should not be allowed.
Key Changes:
raises a `UserError` if a menu exceeds the two-level hierarchy by checking the parent and grandparent levels.
- Implements mega menu restrictions:
- A mega menu cannot have a parent menu.
- A mega menu cannot have child menus.
- Any menu cannot be a child of a mega menu.
- Prevents menus with child menus from being added as submenus to existing menus.
This ensures that the website menu structure adheres to the defined functional specifications, providing a consistent and predictable user experience.
task-3901371
Forward-Port-Of: odoo/odoo#222254
Forward-Port-Of: odoo/odoo#168801Accounting administrators without expense permissions can now create their own expense reports without triggering a confusing validation error. To prevent mistakes, those users are no longer allowed to create expenses on behalf of other employees unless they have the proper expense access rights.
Original PR description
- Create a user and its related employee without any expense access rights but with accounting admin rights. - With that user create a new expense. - On the employee field select a different employee…
- Create a user and its related employee without any expense access rights but with accounting admin rights. - With that user create a new expense. - On the employee field select a different employee and save. - The following error appears: Validation Error The operation cannot be completed: Missing required value for the field 'Description' (name). Model: 'Expense' (hr.expense) - create/update: a mandatory field is not set - delete: another model requires the record being deleted, you can archive it instead Since b1ac6f52d37cd59fdb973ce87f93d1d0a69dd204, the field employee_id is no longer invisible for users without hr_expense rights. However, in the method _search_filter_for_expense, users without hr_expense rights but with account rights are able to select every employee (commit 87cca4a9ee64c890ccbd24e2d6766f9f8799a0c0). But in hr_expense, the method _compute_is_editable only considered hr_expense rights, which meant that users trying to create a new expense with only accounting rights would get an error if they were not the approver of the employee they tried to create the expense for. After this commit: If the user has no hr_expense rights but has account rights, they will only be able to create expenses for themselves. opw-4780218 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#215452
Changing an item quantity with the Point of Sale numpad is now saved immediately in the local browser database. This prevents checkout carts from reverting to the original quantity if the page is refreshed, reducing order mistakes and cashier frustration.
Original PR description
If you modified the quantity of a pos order line with the numpad, then refreshed the page the new quantity would be lost. Steps to reproduce: ------------------- * Open PoS * Add any product to the cart * Modify the quantity using the numpad * Direclty refresh the page > Observation: The quantity of the product is back to 1 Why the fix: ------------ When modifying a pos order line it was not synched with the indexed local database. We now make sure that when a pos order line is modified it is synched correctly. opw-4801613
Archiving or restoring a company now refreshes the company information shown to users correctly. This prevents outdated company lists and avoids errors in related apps such as Timesheets and Italian point of sale when a company is restored.
Original PR description
Currently below error occurs while archive/unarchive company: - Company list is not being updated. - In `hr_timesheet` KeyError will be encountered on unarchiving a company. - In `l10n_it_pos` module…
Currently below error occurs while archive/unarchive company: - Company list is not being updated. - In `hr_timesheet` KeyError will be encountered on unarchiving a company. - In `l10n_it_pos` module an AccessError will be encountered on unarchiving a company. **Root Cause:** Since https://github.com/odoo/odoo/commit/22e9d822e8cab08114c006eb8c4054c4de0c40f2, the `session_info` method relies on `user_companies` at [1], which fetches only active company IDs via `_get_company_ids()`. However, `_get_company_ids` uses caching as shown at [2]. When a company is archived or unarchived, 'write' method is called. Now, here the cache is invalidated before writing to the company as shown at [3]. Due to which '_get_company_ids' method doesn't receive the updated list of companies, causing this issue. **Solution:** This commit prevents error by ensuring companies are stored before invalidating the cache. [1]- https://github.com/odoo/odoo/blob/d3482e32f7dbe273125de84f1bbc434ac3c9ffc3/addons/web/models/ir_http.py#L146 [2]- https://github.com/odoo/odoo/blob/7db62d6d65bd57f6ed43ce52a820cf03df19efdd/odoo/addons/base/models/res_users.py#L927-L931 [3]- https://github.com/odoo/odoo/blob/3173a5f993a3ffa3d3a14d29713142e5b6b314d9/odoo/addons/base/models/res_company.py#L343-L367 Sentry-6251348500 Forward-Port-Of: odoo/odoo#219044
Winbooks data imports now continue even when the source chart of accounts differs from Odoo's default setup. This prevents import failures for draft accounting data, allowing users to review and adjust records inside Odoo afterward.
Original PR description
When importing Winbooks data, if the CoA configuration in Winbooks is different from Odoo's default, users will experience a failure with a message similar to ``` Validation Error Tax Receivable Account (411000 VAT Recoverable) should be an account of type "Receivable" or "Payable" with both options "Allow Reconciliation" and "Non Trade" enabled. ``` This occurs because the account 411000, meant to store the tax provisions, in Winbooks was used as tax receivable. In similar cases we should not raise any error and should let the import go through: the data is imported in draft and the user has the possibility to bring the modifications in Odoo opw-4850314 Forward-Port-Of: odoo/enterprise#91828
The Task Analysis report in Field Service now keeps the correct Field Service filter when users drill into pivot report numbers. This prevents unrelated tasks from appearing and helps teams review accurate operational details.
Original PR description
Issue: - When the user drills down in the pivot view, all tasks are displayed. Cause: - The action was not passing the FSM project domain. Fix: - In this commit, we have passed the FSM project domain, so that only the relevant FSM tasks will be displayed during drill down. Steps to reproduce: - Install the industry_fsm module. - Go to Industry > Reporting > Task Analysis. - Group by Assignees. - Check any count column number and drill down. task-4688139 Forward-Port-Of: odoo/enterprise#83295
The Indian GSTR document summary now excludes cancelled invoices that were never officially posted, preventing inaccurate tax reporting totals. It also improves serial continuity checks by return period and keeps the document summary view consistently visible in the GSTR-1 section.
Original PR description
Before: The document summary included all cancelled invoices, even those that were never posted. After: Only invoices that were posted and subsequently cancelled are now considered in the summary. Additional Changes: - Updated check_serials to validate serial continuity within current company. - Made the document summary view always visible in the GSTR-1 section. opw-4940053 Forward-Port-Of: odoo/enterprise#91971 Forward-Port-Of: odoo/enterprise#90160
Scheduled bank statement reconciliation now uses the correct company context, preventing incorrect currency rates from being applied. The related code was also cleaned up to avoid duplicated logic, making future maintenance safer.
Original PR description
In this commit: https://github.com/odoo/enterprise/pull/89244/commits/788d79cea3c2d45582e16b25847c7821a6521da1 we fixed a bug where the cron would be trigger with the wrong company which impacted the currency rate. We decided to put the change in the try_auto_reconcile, but it was a bit of code duplication so this commit will refactor that. Task-4933083
Odoo can now handle large files sent through WhatsApp without running into memory errors. This helps ensure customer messages with bigger attachments are received reliably instead of failing silently or causing errors.
Original PR description
Currently a below occurs or content is not receiving to odoo WhatsApp when the user uploads a large file (tried with > 35 MB). Stack Trace: ``` MemoryError: null File "odoo/http.py", line 2383, in…
Currently a below occurs or content is not receiving to odoo WhatsApp when the user uploads a large file (tried with > 35 MB).
Stack Trace:
```
MemoryError: null
File "odoo/http.py", line 2383, in __call__
response = request._serve_db()
File "odoo/http.py", line 1913, in _serve_db
return self._transactioning(
File "odoo/http.py", line 1976, in _transactioning
return service_model.retrying(func, env=self.env)
File "odoo/service/model.py", line 134, in retrying
result = func()
File "odoo/http.py", line 1943, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
File "odoo/http.py", line 2187, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
File "odoo/addons/base/models/ir_http.py", line 227, in _dispatch
result = endpoint(**request.params)
File "odoo/http.py", line 757, in route_wrapper
result = endpoint(self, *args, **params_ok)
File "home/odoo/src/enterprise/saas-17.4/whatsapp/controller/main.py", line 42, in webhookpost
wa_account_id._process_messages(value)
File "home/odoo/src/enterprise/saas-17.4/whatsapp/models/whatsapp_account.py", line 206, in _process_messages
datas = wa_api._get_whatsapp_document(messages[message_type]['id'])
File "home/odoo/src/enterprise/saas-17.4/whatsapp/tools/whatsapp_api.py", line 236, in _get_whatsapp_document
file_response = self.__api_requests("GET", file_url, auth_type="bearer", endpoint_include=True)
File "home/odoo/src/enterprise/saas-17.4/whatsapp/tools/whatsapp_api.py", line 46, in __api_requests
if 'error' in res.json():
File "requests/models.py", line 971, in json
return complexjson.loads(self.text, **kwargs)
File "requests/models.py", line 928, in text
encoding = self.apparent_encoding
File "requests/models.py", line 793, in apparent_encoding
return chardet.detect(self.content)["encoding"]
File "__init__.py", line 49, in detect
detector.feed(byte_str)
File "chardet/universaldetector.py", line 274, in feed
if prober.feed(byte_str) == ProbingState.FOUND_IT:
File "chardet/charsetgroupprober.py", line 70, in feed
state = prober.feed(byte_str)
File "chardet/hebrewprober.py", line 240, in feed
byte_str = self.filter_high_byte_only(byte_str)
File "chardet/charsetprober.py", line 73, in filter_high_byte_only
buf = re.sub(b"([\x00-\x7F])+", b" ", buf)
File "__init__.py", line 186, in sub
return _compile(pattern, flags).sub(repl, string, count)
```
At line [1], the code `'error' in res.json()` is used, which reads all the json content of `res`, but at times users upload large files, it will cause the above error because the `json()` tries to read all bytes from res, which is a very large amount to handle in memory.
This commit will fix the above issue by returning a response if the response
contains content_length more than 10 MB.
[1] - https://github.com/odoo/enterprise/blob/aca7ae2a7cf4aad5427a60d5cad60d08774357d0/whatsapp/tools/whatsapp_api.py#L46
sentry-5810101850
Forward-Port-Of: odoo/enterprise#70001Luxembourg VAT report XML exports now include certain special-scheme fields only when the reporting period includes dates in 2025 or later. The annual VAT report also fills required fields when related mandatory fields are present, helping businesses submit legally compliant tax files.
Original PR description
As per legal requirements, the 491, 492 and 493 fields of the xml export of the tax return only need to be included if at least one day of the period includes dates in 2025 or later. As per legal requirements too, the 192 and 193 fields are mandatory in the annual report if some other fields are present. Among those are 361 and 362 which are mandatory even if null so if 192 and 193 are not there yet, we set them to 362 and 363 values (0.0 in most cases). --- from feedback on task-4587067 opw-4757770 Forward-Port-Of: odoo/enterprise#91859 Forward-Port-Of: odoo/enterprise#89437
Fixed an issue where invoices or bills linked to payments in a validated batch could remain marked as in payment after matching the batch with a bank statement line. This ensures payment statuses update correctly when bank journals do not use outstanding payment or receipt accounts.
Original PR description
Setting a batch payment having payments without journal entry with a statement line does not reconcile the invoices/bills linked to the payments. Steps: - Make sure to not have outstanding receipts/payments accounts set on bank journal - Create two invoices, confirm and register payment for both - Create a batch payment with tho payments, validate - Create a statement line with amount = sum of the 2 invoices - Add the batch to the statement line - Go back to invoice tree view -> Both invoices are still 'in_payment' instead of 'paid' opw-4980004
This fix keeps the standard expiration message when an expiration is related to upsells rather than renewals. This avoids showing renewal-specific messaging in cases where it does not apply, making the customer-facing notice clearer and more accurate.
Original PR description
Upsell expiration are not handled the same way as renewal expiration, so we can keep the default expiration message for any expiration reasons other than a renewal Forward-Port-Of: odoo/enterprise#91839 Forward-Port-Of: odoo/enterprise#91730
EC Sales List reports now correctly populate values when a country-specific report has more than the standard three columns. This prevents extra required columns, such as those used in Slovenia, from appearing empty and supports more accurate tax reporting.
Original PR description
Before this commit, when an ec sales list report had more than the 3 bases columns (goods, service, triangular) the value was not filled. For example in slovinia, the ec sales list has 5 columns, the two extras columns where always empty. task-4963633 Forward-Port-Of: odoo/enterprise#90669
Demo employee contracts for Egypt, Saudi Arabia, and Turkey now use the appropriate local payroll structures. This prevents Belgian payroll settings from being applied accidentally when the Belgian payroll module is also installed, making demo data more reliable for evaluations and testing.
Original PR description
*: eg, sa, tr - Assign the correct payroll structure to employee contracts in demo data to prevents incorrect assignment of the Belgian payroll structure when l10n_be is installed. Task: 4862722 Forward-Port-Of: odoo/enterprise#87409
The VoIP softphone now avoids taking focus back after a call when the user is typing in another field. This prevents interruptions and accidental input issues during everyday call handling.
Original PR description
Before switching the focus back to the softphone after a call, make sure the user isn't typing somewhere else. Only autofocus if the focus is not on an editable element. Task-4997513.
Hong Kong payslips now show the employee's regular name when surname and first name fields are not filled in. This prevents payslips from displaying an empty or incorrect legal name, improving clarity for payroll documents.
Original PR description
Explanation: In hong kong payroll, the legal name is joined by surname and first name. However both fields are not madatory therefore it will display False on Payslip. After this commit, it will display the name field when both surname and first name are not used. opw-4944968 Forward-Port-Of: odoo/enterprise#90250