Daily updates from Odoo
Monday, October 27, 2025
25 changes · 18.0
Enhancements to existing features
When Uruguay tax authority rejects an electronic invoice and Odoo cancels it, the system now notifies responsible users so the issue is not missed. The update also makes it easier to review and correct invoices whose tax authority status later changes, reducing unnoticed billing inconsistencies.
Original PR description
Added 3 improvements to the process of updating the state of an invoice in Odoo, according to the state in DGI: **For invoices that have been rejected by DGI:** - Added logic to automatically notify…
Added 3 improvements to the process of updating the state of an invoice in Odoo, according to the state in DGI: **For invoices that have been rejected by DGI:** - Added logic to automatically notify relevant users when an electronic invoice (CFE) is rejected by the DGI and, as a result, canceled in the system. The goal is to ensure that there is always someone responsible who is informed to correct and resend the receipt. - Added logs in the terminal to make the debug easier in case we want to identify rejected invoices. **Particular case of an invoice that had been rejected by DGI but the user somehow fixes it and then DGI accepts it:** - Added logic to verify both DGI state and Invoice state and adjust it accordingly when updating invoice DGI status. - Make 'Update DGI status' button always visible to be able to adjust invoices states. **== Context of the Problem ==** Previously, when Odoo detected that a CFE had been rejected by the DGI, the system proceeded to cancel the invoice automatically. However, this process was carried out silently, without generating any notification. This could mean that if no user or salesperson was actively monitoring the status of the receipts, the cancellation would go unnoticed, resulting in invoices that were never corrected or reissued. For the case of a previously rejected and then accepted invoice, we always thought that 'Rejected' state in DGI was a definite state and could not suffer any change. But recently it has been a case that this state changed, creating inconsistencies in Odoo invoices states as they appear as cancelled. With these changes, the user can adjust the invoices state by clicking 'Update DGI status' button. **== Automatic Notification Logic ==** With the new functionality, every time an invoice is automatically canceled due to a DGI rejection, the system posts a message in the document chatter to report the situation. The logic for determining who is notified is as follows: _Scenario 1: Invoice with Internal Followers_ - If the canceled invoice has at least one internal follower (an Odoo user), the system will perform the following actions: - It will post a message in the invoice chatter. - It will tag (@) all internal followers to notify them directly. _Scenario 2: Invoice without Internal Followers_ - If the invoice does not have any internal followers, the system will search for a more general but relevant audience to ensure that the notification is addressed: - It will post a message in the invoice chat. - It will tag (@) all users who belong to the “Accounting Manager” permission group (technical name: group_account_manager). Task ODOO: #[1362](https://latam-localizations.odoo.com/web?debug=1#id=1362&cids=1&menu_id=88&action=131&active_id=16&model=project.task&view_type=form) Task ADHOC: #[54799](https://www.adhoc.inc/odoo//project.task/54799)
Resolved issues and error corrections
This fix makes an internal mail test less sensitive to timing delays when checking channel subscriptions. It helps prevent false failures in automated validation, improving release confidence without changing user-facing behavior.
Original PR description
Before this commit, the test was checking the channels that were subscribed to in the websocket by filtering on their name. This could cause a condition with the debounce of the update_channel in the websocket. Indeed, if waiting too much time (300 ms at the present) between the presences subscription and the channel subscription, the first one would yield an empty array of subscription since not a discuss channel subscription. This commit fixes the issue by just taking the subscription into account if any channel is in the list, otherwise we simply avoid the step in the test. fixes-runbot-161477 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230608
Companies without an applicable VAT number can now connect to CodaBox using their company registry number instead. This avoids connection issues for non-taxable Belgian companies that mark VAT as non-applicable.
Original PR description
If a company is not subject to taxes, they may not have a VAT number. In that case, the field can be left empty, such that the Company Registry is used instead for the CodaBox connection. However, the case where "/" (Non Applicable) was used as the VAT number was handled. This commit now handles VAT="/" in the same way it handles no VAT at all by using the company registry as a fallback. The commit also cleans up how the company ID is used to avoid duplicated code by creating a computed field. opw-5164155
This fixes an issue where creating a warehouse could accidentally generate many duplicate replenishment routes if an existing global route had been renamed. Warehouses now reuse the intended route correctly, reducing clutter and preventing confusion in inventory configuration.
Original PR description
In _find_or_create_global_route, use the asked 'route_name' instead of the potentially modified name of `data_route`. This ensures that if '_find_or_create_global_route' is called with the exact same values a new route will not be re-created. https://github.com/user-attachments/assets/815adf60-aa2d-4699-a79d-f9ad9607cbea ## How to reproduce (in runbot 17.0): - Enable "Multi-steps Routes" - Unarchive route "Replenish on Order (MTO)", change the name, set company to "My company (San Francisco)" - Go to "My Company (Chicago)" - Create new Warehouse => Check all the routes: ~100 MTO routes with the modified name have been created. OPW-5149842 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#232613
Sales orders with different fiscal positions now generate separate draft invoices instead of being combined into one. This helps ensure taxes and accounts are calculated using the correct fiscal rules for each order, reducing billing errors.
Original PR description
Problem: When a user selects multiple sale orders from the list view to create invoices, if the selected orders have different fiscal positions, they are all incorrectly merged into a single draft…
Problem: When a user selects multiple sale orders from the list view to create invoices, if the selected orders have different fiscal positions, they are all incorrectly merged into a single draft invoice. An invoice can only have one fiscal position. This merging causes unexpected behavior, as the accounts and taxes are computed based on the single (and potentially incorrect) fiscal position of the final invoice, rather than the respective fiscal positions of the originating SOs. Solution: This commit modifies the 'Create Invoices' action to group the selected sale orders by their `fiscal_position_id`. It will now create as many separate draft invoices as there are unique fiscal positions among the selected orders. task: 5188965 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#232821
Creating multiple accounting journals of the same type could fail when no alias domain was configured because Odoo reused the same generated alias. This fix makes the alias uniqueness check include aliases without a domain, preventing save errors and allowing users to create journals normally.
Original PR description
**Issue** When creating two new journals and selecting the *type* before the *name*, Odoo generates an alias using the type (e.g. `sale--...`). When saving a second journal with the same type, the…
**Issue** When creating two new journals and selecting the *type* before the *name*, Odoo generates an alias using the type (e.g. `sale--...`). When saving a second journal with the same type, the alias conflicts and raises a "This alias already exists" error. **Steps to Reproduce** 1. Navigate to Accounting > Configuration > Journals. 2. Create a new journal. 3. Set the Type to Sales before entering the Name. 4. Save the journal. 5. Repeat the process to create another journal of the same type. 6. Observe that an error occurs: alias name is already used. **Root Cause** The uniqueness check in _ensure_unique_alias only compares alias_name against existing aliases with the same alias_domain. However, many aliases are created with alias_domain = False. Since those were excluded from the domain, the check failed to detect duplicates correctly. **Fix** Update the domain in _ensure_unique_alias to also include aliases where alias_domain is unset. This ensures that aliases are always unique regardless of whether a domain is configured. Opw-5028713 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#225537
Completed mail activities are now archived instead of being removed, so users can find them with the Done filter. This preserves activity history and makes the activity overview more reliable for tracking completed work.
Original PR description
When doing a search on activities with the filter "done", no activity will appear. Steps to reproduce: ------------------- * Go to "View all activities" from clock button on top * Add filter "Done" -> Issue no activity appears. Observation: ------------------ The search is made on the field "active" in mail.activity model. But when an activity is marked as done, it's not only marked with that field but also completly erased: https://github.com/odoo/odoo/blob/5207f5f07d00703e5e822852bd5ce212f8051426/addons/mail/models/mail_activity.py#L577 I have juste made all activity archived, but I will try to see if with the keep_done variable added in this commit is possible to solve the problem. https://github.com/odoo/odoo/commit/b6c236df54abb66b30d8643dea797f385d3036f1#diff-37df585509f3129b2a4473822341a8d5af404cd7a50bb7d2876bdf8472b43d87R74 opw-5159884
This update stabilizes an automated barcode test by ensuring the screen has finished updating before the test checks the result. It helps prevent false test failures in development pipelines without changing how users interact with barcode features.
Original PR description
This commit fixes a test that sometimes failed, because we didn't wait for an animationFrame after the macro was complete. As a consequence, there was no guarantee that the form view had been updated before the check. runbot error~226829 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
This update prevents an accounting process from failing when it encounters an empty value where a number is expected. It helps users continue their work without seeing a confusing error message.
Original PR description
Description of the issue/feature this PR addresses: ValueError: invalid literal for int() with base 10: '' Current behavior before PR: ValueError: invalid literal for int() with base 10: '' Desired behavior after PR is merged: not giving valueerror --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Missing translation in settings for "Configure Signature Certificates" in spanish Steps to reproduce: ------------------- * Install module l10n_mx * Switch to a Mexican Company * Go in setting/accouting -> Issue: "Configure Signature Certificates" is not translated. Observation: ------------ It's translated from 18.2+ https://github.com/odoo/enterprise/commit/8e14c5b9c43e109754e5411588d18b93b37335d6 opw-4942599
Original PR description
Missing translation in settings for "Configure Signature Certificates" in spanish Steps to reproduce: ------------------- * Install module l10n_mx * Switch to a Mexican Company * Go in setting/accouting -> Issue: "Configure Signature Certificates" is not translated. Observation: ------------ It's translated from 18.2+ https://github.com/odoo/enterprise/commit/8e14c5b9c43e109754e5411588d18b93b37335d6 opw-4942599
This fix improves how Odoo calculates product unit prices in BIS3 electronic invoices when tax-included pricing is used. It prevents small rounding differences from causing Peppol validation failures, helping invoices be accepted correctly.
Original PR description
At the moment, the UBL's Price/PriceAmount node is rounded to the same number of decimals as the database's product price precision. This causes a Peppol schematron validation error due to rule PEPPOL-EN16931-R120 in the case where the user uses tax-included prices. For example, if you have a tax-included unit price of 12.95, a quantity of 8 and a 21% tax, then the tax-excluded subtotal is 85.62. Divide 85.62 by 8 and you get a raw unit price of 10.7025. But if we round to 2 decimal places, we get 10.7 but `10.7 * 8 = 85.6 != 85.62`. Solution: We need to round the unit price to enough decimal places to ensure that unit price * quantity ~= line subtotal (with a tolerance of less than 0.02) opw-5072134
This fix restores Swedish point-of-sale blackbox validation so orders can be processed correctly under Sweden’s fiscal requirements. It also fixes receipt reprint tracking and corrects organisation number formatting, reducing compliance and operational disruption risks for Swedish POS users.
Original PR description
Before this commit, the Swedish blackbox was completely broken in 18.0 because the `push_single_order` function is no longer used. To fix this, the same approach as `pos_blackbox_be` was used, where the `preSyncAllOrders` function was overridden instead. In addition, the old receipt reprinting logic was no longer working, and so it now uses the `nb_print` field to keep track of the number of reprints. Finally, we also forward port a fix from 17.0 (ddbc1fc) to correct the format of the organisation number, which for some reason was not forward ported originally. task-5077448
This fix prevents company bank account setup from failing when a default account-code prefix is missing. It helps affected accounting migrations complete reliably instead of stopping with an error.
Original PR description
The 'bank_account_code_prefix' field is False by default instead of an empty string. This change ensures proper handling by falling back to an empty string when the field is False. ```traceback…
The 'bank_account_code_prefix' field is False by default instead of an empty string. This change ensures proper handling by falling back to an empty string when the field is False.
```traceback
module l10n_co: Running migration [$1.0] end-migrate_update_taxes
Traceback (most recent call last):
File "/home/odoo/src/odoo/18.0/odoo/service/server.py", line 1361, in preload_registries
registry = Registry.new(dbname, update_module=update_module)
File "<decorator-gen-13>", line 2, in new
File "/home/odoo/src/odoo/18.0/odoo/tools/func.py", line 97, in locked
return func(inst, *args, **kwargs)
File "/home/odoo/src/odoo/18.0/odoo/modules/registry.py", line 129, in new
odoo.modules.load_modules(registry, force_demo, status, update_module)
File "/home/odoo/src/odoo/18.0/odoo/modules/loading.py", line 523, in load_modules
migrations.migrate_module(package, 'end')
File "/home/odoo/src/odoo/18.0/odoo/modules/migration.py", line 222, in migrate_module
exec_script(self.cr, installed_version, pyfile, pkg.name, stage, stageformat[stage] % version)
File "/home/odoo/src/odoo/18.0/odoo/modules/migration.py", line 259, in exec_script
mod.migrate(cr, installed_version)
File "/home/odoo/src/odoo/18.0/addons/l10n_co/migrations/1.0/end-migrate_update_taxes.py", line 8, in migrate
env['account.chart.template'].try_loading('co', company)
File "/home/odoo/src/odoo/18.0/addons/account/models/chart_template.py", line 160, in try_loading
return self._load(template_code, company, install_demo, force_create)
File "/home/odoo/src/odoo/18.0/addons/account/models/chart_template.py", line 228, in _load
self._post_load_data(template_code, company, template_data)
File "/home/odoo/src/enterprise/18.0/account_reports/models/chart_template.py", line 10, in _post_load_data
super()._post_load_data(template_code, company, template_data)
File "/home/odoo/src/odoo/18.0/addons/account/models/chart_template.py", line 681, in _post_load_data
self._setup_utility_bank_accounts(template_code, company, template_data)
File "/home/odoo/src/odoo/18.0/addons/account/models/chart_template.py", line 845, in _setup_utility_bank_accounts
accounts = self.env['account.account']._load_records([
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 5526, in _load_records
records = self._load_records_create([data['values'] for data in to_create])
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 5430, in _load_records_create
records = self.create(vals_list)
File "<decorator-gen-208>", line 2, in create
File "/home/odoo/src/odoo/18.0/odoo/api.py", line 498, in _model_create_multi
return create(self, arg)
File "/home/odoo/src/odoo/18.0/addons/account/models/account_account.py", line 997, in create
start_code = prefix.ljust(digits - 1, '0') + '1' if len(prefix) < digits else prefix
TypeError: object of type 'bool' has no len()
```
Databases affected by this traceback error:
https://upgrade.odoo.com/odoo/request/3191023/tbg/2150
task-5167397
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prWebsite forms now handle field names that include the “|” character when setting conditional visibility rules. This prevents dependent fields from staying hidden incorrectly, helping form builders use flexible field labels without breaking form behavior.
Original PR description
Before this commit, after selecting a field containing the char "|" for conditional display, the field on which the condition is set will never appear again. This commit enable the use of any characters in form fields Steps to reproduce the bug: - Add a form - Add two fields (A and B) - Rename the field A with a string that contains "|" - Set the field B visibility to "Visible only if" - Set the field A as the visibility condition for field B (field B visible only if field A contains 'hello', for example) - Save the changes - Complete the field A according to the visibility condition (The second field does not appear) task-3893749
Requests for quotation created from approvals now use the currency configured for the product's vendor instead of defaulting to the company currency. This keeps purchase pricing consistent with other RFQ creation flows and avoids currency mismatches when updating existing purchase orders.
Original PR description
Issue: When creating an RFQ from an approval, the created purchase order does not use the currency set on the vendor of the product. Rather, it uses the currency of the company, with the value converted based on the vendor's currency to get the price. This is not consistent with other ways we create RFQs, which all respect the vendor currency. Solution: Pass the vendor's currency into the values sent when creating the purchase order. In the case of modifying an existing purchase order, only modify purchase orders matching vendor's currency. opw-4549937
Fixes an issue where editing the “Terms and conditions” link on a product page could cause an error. The website editor now correctly handles color removal for links styled with special text classes, making this editing flow reliable for users.
Original PR description
Problem: On website > shop > product page, when trying to edit the link of "Terms and conditions", a traceback occurs. Cause: When applying changes on "Terms and conditions" in `shop/product`, `ColorPlugin.removeAllColor()` is called on the `a` element. Its color was applied by the `text-muted` class. This case in color removal was not properly handled. Solution: In `getFonts`, consider elements that have those special classes (e.g., `text-muted`) when processing color removal. Steps to reproduce: 1. Open website/shop. 2. Open any product page. 3. Open the editor. 4. Select the "Terms and conditions" text. 5. Click edit in the link popover. 6. Click apply. 7. Traceback occurs. opw-5130016 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Odoo now routes Peppol participant lookup requests through its central IAP service instead of relying on soon-to-be-deprecated DNS lookup methods. This keeps electronic invoicing connectivity working as Peppol changes its DNS requirements and makes future lookup changes easier to manage centrally.
Original PR description
From November 1st, CNAME DNS will be deprecated for Peppol lookups. From February 1st CNAME lookups will no longer be supported. The replacement are NAPTR DNS records. Multiple solutions were available, such as using DoH (e.g. with cloudflare DNS), but we ended up choosing to proxy DNS requests through IAP to centralize the lookups and make such specs upgrades easier to handle in the future. IAP is now responsible of doing the DNS lookup and fetching the service groups of the found SMP. IAP-side: https://github.com/odoo/iap-apps/pull/1227 task-5179969 Forward-Port-Of: odoo/odoo#232483
The point of sale product grid now displays product cards more consistently on mobile devices. This prevents card sizing conflicts that could make the sales screen look uneven or harder to use.
Original PR description
This commit fixes an issue related to the `product card` which has an enforced `4 /3` aspect ratio. Currently, there are two different grid layouts in `point_of_sale` depending on the breakpoint. On…
This commit fixes an issue related to the `product card` which has an enforced `4 /3` aspect ratio. Currently, there are two different grid layouts in `point_of_sale` depending on the breakpoint. On Mobile, we use a `3 cols` layout with each col being the same size, which conflicts with the grid layout as it try to enforce a specific `width/height` on the element. On other devices, we use an `auto-fill` rule, which provides way more flexibility for items to grow, but even there the aspect-ratio is not working as the item is sized as the other grid items. To fix this issue, we remove the `aspect-ratio` property, which was not affecting the design of the item and rely on the default grid sizing behaviour, to prevent any issue. task-4965395 | 18.0 and above | This PR | |--------|--------| | <img width="391" height="844" alt="image" src="https://github.com/user-attachments/assets/a191bfcf-20f6-4621-832b-a40ed42c2358" /> | <img width="391" height="844" alt="image" src="https://github.com/user-attachments/assets/7f07000e-b0e5-411e-bce6-12a5072bb854" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The sale product catalog now shows the discounted price for a single sale order line, instead of showing the original unit price. This prevents pricing confusion and keeps the catalog display aligned with the actual order total.
Original PR description
Description of the issue/feature this PR addresses: When using the product catalog in sale orders, if a sale order line has a discount applied via the `discount` field, the catalog displays the base…
Description of the issue/feature this PR addresses: When using the product catalog in sale orders, if a sale order line has a discount applied via the `discount` field, the catalog displays the base `price_unit` instead of the discounted price. This creates an inconsistency between what's shown in the catalog and the actual price in the order line. Current behavior before PR: - A sale order line with price_unit=120.00 and discount=15% shows subtotal=102.00 in the order - The product catalog shows price=120.00 (without discount applied) - This only happens when `len(self) == 1` in `_get_product_catalog_lines_data()` - The multi-line case (`elif self:`) correctly calculates the price using pricelist Desired behavior after PR is merged: - The product catalog should show price=102.00 (with discount applied) - Consistency between catalog price and order line subtotal - The discount field is properly considered in the price calculation for single lines - Behavior matches the multi-line case where pricelist correctly calculates discounted prices --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The sales product catalog now shows prices that correctly reflect discounts for products already added to an order. This prevents misleading catalog prices and helps sales teams quote customers accurately.
Original PR description
Catalog prices do not consider discounts when displayed separately from the unit price on the order line (if any for a given product). It was fixed for the /update_order_line_info route with 5d1837e47c20f04458472658c4f8ea71284fb6ca, but the issue still remained when fetching the original catalog data on opening, through the /order_lines_info route. This only happened when the product was already added to the order, because in this case we avoid recomputing the pricelist price and use the existing sale order line price. This commit makes sure that the sale order line discount field is correctly considered in that case, and also adds tests to cover the catalog more extensively. Fixes #232219 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures Saudi e-invoicing configuration checks still run when a company has no country set. It helps prevent misconfigured invoices from causing errors that can block automated EDI processing jobs.
Original PR description
ZATCA invoice misconfigurations are only checked for if the company has Saudi Arabia set as its country. However, ZATCA EDIs can be generated without Saudi Arabia set as the country. Thus, companies without a company set can create EDI documents for misconfigured invoices. This may cause traceback errors which prevent the "EDI : Perform web services operations" cron from running at all. This commit ensures that configuration checks are run on companies without countries set (and adds a relevant unit test). opw-5057792 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#231255
Lithuanian payslips no longer apply the employee pension contribution twice when pension accumulation is enabled. This prevents overstating payroll deductions and helps ensure payslips match expected Lithuanian social security rules.
Original PR description
**Issue**
When generating a payslip for an employee with the `l10n_lt_pension` setting enabled on the contract ("Participate to pension accumulation system"):
- the SSC is raised from 19.5% to 22.5%
- a 3% pension contribution ("Pension Scheme") is added This effectively doubles the expected contribution.
Various sources (e.g. https://taxsummaries.pwc.com/lithuania/individual/other-taxes) seem to show this is not correct.
opw-5067664
Forward-Port-Of: odoo/enterprise#95880Contact complete addresses now include the second street address line when it is filled in. This ensures email templates and other uses of the complete address show the full mailing address, reducing omissions in customer communications.
Original PR description
Issue: If a user with `street2` wants to utilize the `contact_address_complete` field, the `street2` field is not included. Purpose of this PR: To include the `street2` field in the `contact_address_complete` Steps to reproduce on Runbot: install contact fill in a contact's `street2` create email template that uses the `contact_address_complete` `street2` is omitted from the complete address opw-5186218 Forward-Port-Of: odoo/enterprise#98103
Code cleanup and technical improvements
This update simplifies automated test files by removing unnecessary grouping labels that repeated the file name or could be misleading. It does not change product behavior, but makes tests easier for developers to read and maintain.
Original PR description
This commit removes test files using a single 'describe' call to wrap its tests, with a name being either redundant with the test file itself or is too misleading.
Regular expression used to find isolated suites:
```js
/^\s*import.*(?:\n(?!describe\()(?!test\().*)+\ndescribe\("[\w\s.]+",.*(?:\n(?!describe\().*)+\n\}\);\n(?!\n)/
```
Tip for reviewers: tick **"Hide whitespace"** when reviewing diff
<img width="237" height="205" alt="image" src="https://github.com/user-attachments/assets/373f7cc6-5e0e-4599-968a-39aad8fac2f0" />
Enterprise: https://github.com/odoo/enterprise/pull/98046
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update simplifies several automated test files by removing redundant grouping labels that did not add useful information. It does not change product behavior, but it makes the test suite easier for developers to read and maintain.
Original PR description
This commit removes test files using a single 'describe' call to wrap its tests, with a name being either redundant with the test file itself or is too misleading.
Regular expression used to find isolated suites:
```js
/^\s*import.*(?:\n(?!describe\()(?!test\().*)+\ndescribe\("[\w\s.]+",.*(?:\n(?!describe\().*)+\n\}\);\n(?!\n)/
```
Tip for reviewers: tick **"Hide whitespace"** when reviewing diff
<img width="237" height="205" alt="image" src="https://github.com/user-attachments/assets/373f7cc6-5e0e-4599-968a-39aad8fac2f0" />
Community: https://github.com/odoo/odoo/pull/233006