Wednesday, July 22, 2026
159 changes
6 changes
Resolved issues and error corrections
The AI module's automated tests were adjusted to focus only on editable email content. This keeps test results reliable after a related editor change created an extra background copy of the content.
Original PR description
This commit updates the tests after https://github.com/odoo/odoo/pull/276332 to query only the editable content, ignoring the DOM clone created by `convert_inline`. opw-3776054
The spreadsheet editor now stops further loading steps when a spreadsheet model cannot be created. This avoids an additional error screen or traceback after the user has already been notified of the original problem.
Original PR description
Current behavior before PR: - In 4204ceb, model creation errors were caught and a notification was shown to the user. - However, syncSheetFromRouter() was still called afterward. Since it relies on model getters, it raise a traceback when no model existed. Desired behavior after PR is merged: - Call syncSheetFromRouter() only after the model has been created successfully. - This prevents accessing model getters when model creation fails and avoids the resulting traceback. Task: [6355245](https://www.odoo.com/odoo/project/2328/tasks/6355245) Forward-Port-Of: odoo/enterprise#122650
# Problem Cost of production in the inventory valuation report does not respect 'As of' date, and will show current costs of production regardless of the specified date. # Solution `_get_report_data` in `mrp_account` is just missing the date enforcement when calling `_get_location_valuation_vals`, so we will simply pass this in. # Steps to reproduce (runbot v19) - FIFO Perpetual component with non-zero value - Manufactured product that consumes the above component 1. Set a cost of pro
Original PR description
# Problem Cost of production in the inventory valuation report does not respect 'As of' date, and will show current costs of production regardless of the specified date. # Solution `_get_report_data` in `mrp_account` is just missing the date enforcement when calling `_get_location_valuation_vals`, so we will simply pass this in. # Steps to reproduce (runbot v19) - FIFO Perpetual component with non-zero value - Manufactured product that consumes the above component 1. Set a cost of production account on the production location 2. Create and confirm an MO for the manufactured product 3. Go to Accounting > Review > Inventory Valuation, and set the At Date to something far in the past, befroe any move history in the db. Note the Cost of Production accounts have data that does not apply to this period opw-6229088 Forward-Port-Of: odoo/odoo#277025 Forward-Port-Of: odoo/odoo#269911
## Current behavior: Currently, when we go into POS using l10n_tw localization, none of the customers appear on the list. ## Expected behavior: All customers should be shown when using Taiwan localization ## Steps to reproduce: 1. Install l10n_tw and POS modules 2. Use the default US company, observe the customer list in POS. All of them are shown 3. Create and switch to a Taiwan company, go back to POS 4. Observe that no customers are shown ## Cause of the issue: Since 19.0, the
Original PR description
## Current behavior: Currently, when we go into POS using l10n_tw localization, none of the customers appear on the list. ## Expected behavior: All customers should be shown when using Taiwan localization ## Steps to reproduce: 1. Install l10n_tw and POS modules 2. Use the default US company, observe the customer list in POS. All of them are shown 3. Create and switch to a Taiwan company, go back to POS 4. Observe that no customers are shown ## Cause of the issue: Since 19.0, there is a check where if the default payable or receivable account set on the partner is non-trade, those accounts do not appear ## Fix: - Updated AR accounts in COA template file - Added migration script to version 1.1 opw-6298634 Forward-Port-Of: odoo/odoo#274150 Forward-Port-Of: odoo/odoo#270738
Before this commit, two issues affected custom snippet saves. First, the new builder allowed saving the Alternative Products block from product pages as a custom snippet. This block is generated from the current product alternatives, so it is page-specific content. Second, a block saved as a custom snippet could keep `oe_unremovable` or `oe_unmovable` on its root. A saved custom snippet is meant to become a normal reusable block. Once the user drops it on another page, they should be able
Original PR description
Before this commit, two issues affected custom snippet saves. First, the new builder allowed saving the Alternative Products block from product pages as a custom snippet. This block is generated from the current product alternatives, so it is page-specific content. Second, a block saved as a custom snippet could keep `oe_unremovable` or `oe_unmovable` on its root. A saved custom snippet is meant to become a normal reusable block. Once the user drops it on another page, they should be able to remove it or move it like any other block. After this commit, builder plugins can declare selectors that cannot be saved as custom snippets, and `website_sale` uses this to exclude the Alternative Products block. The saved copy also drops `oe_unremovable` and `oe_unmovable` on its root before calling `ir.ui.view.save_snippet`. task-6296872 Forward-Port-Of: odoo/odoo#277092 Forward-Port-Of: odoo/odoo#275303
Miscellaneous changes
_**Description of the issue/feature this PR addresses:**_ SaleOrder._onchange_order_line retrieves the linked lines of each order line by calling SaleOrderLine._get_linked_lines(). That method filters the whole order_line recordset on every call. Since the onchange is triggered by any change to order_line, this noticeably slows down every modification of the lines on large orders even when the order contains no combo product at all. _**Current behavior before PR:**_ For every order line,
Original PR description
_**Description of the issue/feature this PR addresses:**_ SaleOrder._onchange_order_line retrieves the linked lines of each order line by calling SaleOrderLine._get_linked_lines(). That method…
_**Description of the issue/feature this PR addresses:**_
SaleOrder._onchange_order_line retrieves the linked lines of each order line by calling SaleOrderLine._get_linked_lines().
That method filters the whole order_line recordset on every call.
Since the onchange is triggered by any change to order_line, this noticeably slows down every modification of the lines on large orders even when the order contains no combo product at all.
_**Current behavior before PR:**_
For every order line, _onchange_order_line calls line._get_linked_lines(), and each call re-scans the entire order_line recordset with filtered(). The cost therefore grows with the total number of lines (regular lines included), so editing any line on a large order is sluggish.
_**Desired behavior after PR is merged:**_
The {line: linked_lines} mapping is computed in a single pass via the new method SaleOrderLine._get_linked_lines_by_line(), called once per onchange instead of once per line.
The method _get_linked_lines() is kept as a thin single-record wrapper delegating to the batched method, preserving backward compatibility for external callers. Behavior is unchanged and only the performance is improved: the onchange now scales linearly with the number of order lines.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#277620
Forward-Port-Of: odoo/odoo#2771852 changes
Resolved issues and error corrections
Issue :- Steps to Reproducet: SaaS 19.3 - Create a new database Install the Sale module. - Create a product set some On Hand quantity for that product (via Inventory adjustment). - Create a Quotation using that product. - Confirm the quotation (turning it into a Sales Order). - Open the Forecasted Report for that product. The Reserve / Unreserve button in the Forecasted Report not render. <img width="1811" height="323" alt="image" src="https://github.com/user-attachments/assets/4093b
Original PR description
3 changes
Resolved issues and error corrections
Before this commit, two issues affected custom snippet saves. First, the new builder allowed saving the Alternative Products block from product pages as a custom snippet. This block is generated from the current product alternatives, so it is page-specific content. Second, a block saved as a custom snippet could keep `oe_unremovable` or `oe_unmovable` on its root. A saved custom snippet is meant to become a normal reusable block. Once the user drops it on another page, they should be able
Original PR description
Before this commit, two issues affected custom snippet saves. First, the new builder allowed saving the Alternative Products block from product pages as a custom snippet. This block is generated from the current product alternatives, so it is page-specific content. Second, a block saved as a custom snippet could keep `oe_unremovable` or `oe_unmovable` on its root. A saved custom snippet is meant to become a normal reusable block. Once the user drops it on another page, they should be able to remove it or move it like any other block. After this commit, builder plugins can declare selectors that cannot be saved as custom snippets, and `website_sale` uses this to exclude the Alternative Products block. The saved copy also drops `oe_unremovable` and `oe_unmovable` on its root before calling `ir.ui.view.save_snippet`. task-6296872 Forward-Port-Of: odoo/odoo#277092 Forward-Port-Of: odoo/odoo#275303
2 changes
Enhancements to existing features
In order to allow preparation receipts printing from self order mobile, we need reduce the restriction kiosk mode, so that we can call from overrides. see odoo/enterprise#124652 opw-6127663 Forward-Port-Of: odoo/odoo#276886
Original PR description
In order to allow preparation receipts printing from self order mobile, we need reduce the restriction kiosk mode, so that we can call from overrides. see odoo/enterprise#124652 opw-6127663 Forward-Port-Of: odoo/odoo#276886
8 changes
Enhancements to existing features
Embedded views in Knowledge now show the move handle in a more natural position during drag-and-drop interactions. This makes arranging embedded content easier and reduces visual misalignment while editing pages.
Original PR description
This commit adjusts the drag handle position for embedded views to keep the move widget visually aligned with the embedded content during drag interactions. Task-5951196
3 changes
Resolved issues and error corrections
This update registers the WhatsApp Identifiers translation template so it is included in the translation workflow. It helps ensure future text updates for this feature can be properly translated across supported languages.
Original PR description
pot files must be registered there. See 9966b160972a053e051f2213846acc64d133f2a3 Forward-Port-Of: odoo/enterprise#124076 Forward-Port-Of: odoo/enterprise#124026
1 change
Resolved issues and error corrections
**Steps to reproduce:** * Install **l10n_fr_pdp** module. * Create two companies: one French (with PDP activated) and one in another country (e.g. Belgium). * Create a customer invoice in the **non-French company** for a **French customer**. * Open **Send & Print** and try to send via **email**. **Observed behavior:** * Sending fails with: `Errors occurred while creating the EDI document (format: France UBL 2.1 E-Invoicing Format):` `- The following partner's SIREN or SIRET is missing: <
Original PR description
Issue :- Steps to Reproducet: SaaS 19.3 - Create a new database Install the Sale module. - Create a product set some On Hand quantity for that product (via Inventory adjustment). - Create a Quotation…
Issue :-
Steps to Reproducet: SaaS 19.3
- Create a new database Install the Sale module.
- Create a product set some On Hand quantity for that product (via Inventory adjustment).
- Create a Quotation using that product.
- Confirm the quotation (turning it into a Sales Order).
- Open the Forecasted Report for that product.
The Reserve / Unreserve button in the Forecasted Report not render.
<img width="1811" height="323" alt="image" src="https://github.com/user-attachments/assets/4093bddb-f332-4b84-a482-a6604ebcb318" />
Regression from the OWL3 rendering context migration ("[REF] stock,*: run rendering context migration script"), which rewrote the template call `displayReserve(line)` into `this.displayReserve(line)`. https://github.com/odoo/odoo/commit/df40bc9e261a62c045e7e6150a60663a582e7dae and it comes in 19.2 onwards version.
The previous bare call compiled to `ctx['displayReserve'](...)`, so the method executed with `this` bound to that render context, which does own `line` and `line_index`. The lookups resolved by accident, not by design. as far as i have known.
With the explicit [`this.`](https://github.com/odoo/odoo/commit/df40bc9e261a62c045e7e6150a60663a582e7dae#diff-c556e01f9a3ebdb27bb6599d12b74c7bb0a433177cc0e126365cb763a874d9f4R81) form required by OWL3, `this` is correctly the component instance, so `this.line` and `this.line_index` are undefined:
```py
- `this.line_index - 1 >= 0` -> NaN >= 0 -> false, the block is
skipped and `splittedLine` stays true
- `this.lines[this.line_index]` -> undefined
- `.includes(undefined)` -> false, so `isOnHand()` is false
```
<img width="1404" height="786" alt="image" src="https://github.com/user-attachments/assets/6d2cb88b-a695-4388-9b5e-3eac266f1877" />
`displayReserve()` therefore always returns a falsy value and the `t-if` never renders the button. `isOnHand(line)`, which the template also calls directly to render the reservable quantity, is broken for the same reason.
Root cause:
loop variables produced by `t-foreach`/`t-as` live only on the template render context and must never be read off `this` in a component method. The previous code depended on OWL2 resolving a bare template call against that context, which OWL3 no longer does.
``` with the displayReserve(line) ```
<img width="1185" height="599" alt="image" src="https://github.com/user-attachments/assets/ed79f6db-f95c-437f-baf8-f65391df14e7" />
```with the this.displayReserve(line)```
<img width="1020" height="641" alt="image" src="https://github.com/user-attachments/assets/61103db5-7e0a-4362-9dd4-c2f47db2bd97" />
Fix:
derive the values from the `line` argument the methods already receive, instead of reading them off `this`.
```py
- `displayReserve()`: `const line_index = this.lines.indexOf(line)`, and
use the `line` argument in place of `this.line`
- `isOnHand()` / `isReconciled()`: test against `line` directly, since
`this.lines[line_index] === line` inside the loop
```
The template is unchanged: the OWL3-compliant `this.displayReserve(line)` call stays as the migration left it, and no method signature changes.
``` with the current fix```
<img width="1100" height="480" alt="image" src="https://github.com/user-attachments/assets/39147abb-ba5e-42ae-84f5-3d7cbadda1e1" />
<img width="1879" height="304" alt="image" src="https://github.com/user-attachments/assets/fafd3d6a-7591-4dbd-a85c-8fb9de541dd8" />
OPW:- 6363290
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**Problem:** On a job position whose company is left empty ("Visible to all"), the Recruiter dropdown does not propose any user anymore: only the "Create" option is offered. The same happens on applicants without a company. Only saas-19.2 is affected: 19.0/19.1 still use the res.users-based recruiter field, and on saas-19.3 the company became mandatory on job positions. **Steps to reproduce:** 1. Install Recruitment 2. Open a job position whose Company is "Visible to all" (e.g. any demo jo
Original PR description
**Problem:** On a job position whose company is left empty ("Visible to all"), the Recruiter dropdown does not propose any user anymore: only the "Create" option is offered. The same happens on…
**Problem:**
On a job position whose company is left empty ("Visible to all"), the Recruiter dropdown does not propose any user anymore: only the "Create" option is offered. The same happens on applicants without a company. Only saas-19.2 is affected: 19.0/19.1 still use the res.users-based recruiter field, and on saas-19.3 the company became mandatory on job positions.
**Steps to reproduce:**
1. Install Recruitment
2. Open a job position whose Company is "Visible to all" (e.g. any demo job position)
3. Edit the Recruiter field
**Current behavior:**
The dropdown shows no user, only the "Create" option.
**Expected behavior:**
The dropdown lists the recruiters of all companies, as it does (per company) when a company is set.
**Cause of the issue:**
Commit 05e22346050d replaced the res.users-based `user_id` recruiter field with the hr.employee-based `recruiter_id`, declared with `check_company=True`. For check_company fields, `_description_domain()` sends the client `company_id and [('company_id', 'in', [company_id, False])] or [('company_id', '=', False)]`. When the record has no company, the domain falls back to `[('company_id', '=', False)]`, and since `hr.employee.company_id` is required, no employee can ever match. This reintroduces the issue previously fixed by 5dfe494e62af for the old user_id field: the `allowed_user_ids` mechanism introduced there was dropped by the field replacement.
**Fix:**
`check_company=True` brings nothing to these models server-side (neither `hr.job` nor `hr.applicant` has `_check_company_auto`): its only effect is that client-side domain. Folding the company condition directly into the recruiter domain with `('company_id', '=?', company_id)` keeps the per-company filtering when a company is set and degrades to no filtering when it is not, mirroring what is already done for `interviewer_ids` on the job position. The domains become strings so the client keeps evaluating `company_id` per record.
opw-6290312
Forward-Port-Of: odoo/odoo#270529When sending a batch of invoice, we first generate an unique PDF file regrouping every invoice. When at least one invoice needs more than one page to be rendered entirely, the number of pages will be greater than the number of invoices. In this case, we use <hX> tags to split invoices: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/odoo/addons/base/models/ir_actions_report.py#L916-L923 This tag is added for PDF files, using the invoice's title: https://g
Original PR description
When sending a batch of invoice, we first generate an unique PDF file regrouping every invoice. When at least one invoice needs more than one page to be rendered entirely, the number of pages will be…
When sending a batch of invoice, we first generate an unique PDF file regrouping every invoice. When at least one invoice needs more than one page to be rendered entirely, the number of pages will be greater than the number of invoices. In this case, we use <hX> tags to split invoices: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/odoo/addons/base/models/ir_actions_report.py#L916-L923 This tag is added for PDF files, using the invoice's title: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/addons/web/views/report_templates.xml#L627 In some localization modules, this title shouldn't be displayed and it is removed. Example for Chile: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/addons/l10n_cl/views/report_invoice.xml#L149 In this case, no `<h3>` tag will be added and an error is raised as we cannot separate invoices. We propose to add an empty `<h3>` tag if the document title is not defined. opw-6281187 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277131 Forward-Port-Of: odoo/odoo#269100
Miscellaneous changes
Issue: User goes to Event.event Form -> communication tab -> add line - can no longer create a social post in template communication tab Fix: remove "no_create_edit: True" to the associated field in the xml to unblock creation of new mail.templates Reverted from commit (odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b) due to not being able to make social media posts on event communication tab. I originanlly suggested this change because WA Templates need more limitations for creation
Original PR description
Issue: User goes to Event.event Form -> communication tab -> add line - can no longer create a social post in template communication tab Fix: remove "no_create_edit: True" to the associated field in the xml to unblock creation of new mail.templates Reverted from commit (odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b) due to not being able to make social media posts on event communication tab. I originanlly suggested this change because WA Templates need more limitations for creation and edits. This then blocked other creation and edits that rely on this flow. opw-6334168 Forward-Port-Of: odoo/odoo#276031 Forward-Port-Of: odoo/odoo#272262
Miscellaneous changes
Issue: User goes to Event.event Form -> communication tab -> add line - can no longer create a social post in template communication tab Fix: remove "no_create_edit: True" to the associated field in the xml to unblock creation of new mail.templates Reverted from commit (odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b) due to not being able to make social media posts on event communication tab. I originanlly suggested this change because WA Templates need more limitations for creation
Original PR description
Issue: User goes to Event.event Form -> communication tab -> add line - can no longer create a social post in template communication tab Fix: remove "no_create_edit: True" to the associated field in the xml to unblock creation of new mail.templates Reverted from commit (odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b) due to not being able to make social media posts on event communication tab. I originanlly suggested this change because WA Templates need more limitations for creation and edits. This then blocked other creation and edits that rely on this flow. opw-6334168 Forward-Port-Of: odoo/odoo#276031 Forward-Port-Of: odoo/odoo#272262
Printed payslips now include an employee’s departure date when applicable. This gives payroll teams and employees clearer documentation, especially for final payslips and Belgian termination fee reports.
Original PR description
task-6227661
Resolved issues and error corrections
A broken automated checkout test for Mexican point-of-sale invoicing was corrected by adding the missing tax selection step. This helps keep invoice and refund flows reliable during future updates, with no expected change for everyday users.
Original PR description
In this commit: =============== - Fix the failing tour `test_mx_pos_invoice_order_and_refund` due to a missing step for Tax Selection. Error-941398
The WhatsApp identifiers translation file is now properly registered in the translation management configuration. This helps ensure related text can be picked up for translation workflows, reducing the risk of missing translations for users.
Original PR description
pot files must be registered there. See 9966b160972a053e051f2213846acc64d133f2a3 Forward-Port-Of: odoo/enterprise#124076 Forward-Port-Of: odoo/enterprise#124026
This fix ensures the subscription commission test correctly clears currency rate records across companies when demo data is present. It prevents false test failures and helps keep commission calculations reliable in multi-company setups.
Original PR description
Steps to reproduce: 1- Initialize a new database with demo data 2- Run the test `test_sub_commission_no_currency_rate` Issue: `AssertionError: 0 != 10 : Regular invoice, 10 percent of 100` Why this happens: The test used to delete all rows in the res_currency_rate table for the current company only. When we load the database with demo data, the query in `_get_subscription_currency_rates` would find entries for the other companies and wouldn't resort to the default. Later when joining, it would find no rates for the current company and the test fails. runbot-243440 Forward-Port-Of: odoo/enterprise#123971 Forward-Port-Of: odoo/enterprise#116197
Code cleanup and technical improvements
Spreadsheet autofill behavior was adapted to align with recent internal spreadsheet engine changes. This keeps list and pivot autofill working consistently while reducing unnecessary formula processing, with no expected user-facing workflow changes.
Original PR description
The o-spreadsheet commit transformed the autofill plugin into a store. This made the necessary adaptations in odoo. Moslty, the list/pivot autofill plugin were changed into helpers that can be called from the autofill process (they had no state nor command handling). Also changed a bit the autofill helpers so we don't re-compile the cell formula when we already have a compiled formula. Task: 6395361
The VoIP softphone search bar was updated to use newer internal interface tools, keeping the user experience the same while improving maintainability. Existing checks confirm the search field still focuses correctly when reopening the softphone or switching tabs.
Original PR description
Replaces two `useLayoutEffect` calls in `SearchBar` with OWL3 native APIs (`useEffect`, `computed`, `signal`) The useLayoutEffect refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - @voip/softphone/softphone/Search bar is focused after reopen the softphone. - @voip/softphone/softphone/Search bar is focused after switching to a tab with search bar. see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2622059/build/116410158
The emSigner signing flow now places the certificate correctly in signed PDFs after recent changes to emSigner’s interface and API. This prevents incorrectly displayed certificates and helps ensure signed documents look accurate for users.
Original PR description
Before: - Certificate added by emSigner was misaligned in the signed PDF after recent UI changes. After: - Updated coordinates to ensure the emSigner certificate is properly aligned and displayed correctly in Odoo. task-6105264
Users can now click and edit custom fields directly in the Documents list view. This removes an extra step and makes customizations created with Studio behave like standard editable fields.
Original PR description
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The…
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The user has to first click a standard editable field (like "Owner") to put the row into edit mode before they can modify the custom field. This occurs because we use a hardcoded whitelist (`editableColumns`) of standard fields allowed to trigger edit mode. Custom fields (`x_`) are missing from this static list. This commit resolves the issue by dynamically injecting visible, non-readonly custom fields into the `editableColumns` whitelist. This allows user-created fields to be edited inline as expected. **Steps to reproduce:** - Documents > Studio > List view > Add any field that accepts user input (e.g. Text/char) > save/exit - In the same Documents list view > select a row > click the cell belonging to the newly created field > observe that the row does not enter edit mode - In the same Documents list view > select a row > click a standard editable cell, then click the cell belonging to our newly created field > observe that this then allows us to edit our field **Current behavior before PR:** - Custom fields do not trigger inline edit mode **Desired behavior after PR is merged:** - Custom fields trigger inline edit mode opw-6378102
**Steps to reproduce:** * Install **l10n_fr_pdp** module. * Create two companies: one French (with PDP activated) and one in another country (e.g. Belgium). * Create a customer invoice in the…
**Steps to reproduce:** * Install **l10n_fr_pdp** module. * Create two companies: one French (with PDP activated) and one in another country (e.g. Belgium). * Create a customer invoice in the **non-French company** for a **French customer**. * Open **Send & Print** and try to send via **email**. **Observed behavior:** * Sending fails with: `Errors occurred while creating the EDI document (format: France UBL 2.1 E-Invoicing Format):` `- The following partner's SIREN or SIRET is missing: <BE company name>` `- The following partner's PDP identifier is missing: <BE company name>` **Cause:** * `_get_suggested_invoice_edi_format()` on `res.partner` returned `'ubl_21_fr'` for any French B2B partner regardless of which company was sending the invoice. * This caused `ubl_21_fr` to be stored as the partner's `invoice_edi_format` and selected at send time, even when the sending company has no PDP registration. * The `ubl_21_fr` XML builder then validates that **both** supplier and customer have French PDP credentials (EAS 0225, SIREN/SIRET), which the non-French company cannot satisfy. **Fix:** * In `_get_suggested_invoice_edi_format()`, add a guard on `self.env.company._get_peppol_proxy_type() == 'pdp'` so that `'ubl_21_fr'` is only suggested when the active company is a PDP-registered French company. **Note:** * No test added — reproducing this bug requires two localization modules to be installed simultaneously (e.g. `l10n_fr_pdp` + `l10n_be`), which is not supported in the standard test framework. opw-6392253
This update streamlines how several Odoo Enterprise features access shared internal services. It should make the codebase easier to maintain and reduce future development risk, with little to no visible change for end users.
Original PR description
This commit reduces number of `env.services` occurence by replacing them by `useService` or `plugin`. Some handlers/providers are now scoped to be able to call these hooks and `useService` is now also scope dependent instead of component dependent.