Daily updates from Odoo
Tuesday, July 28, 2026
221 changes
13 changes
Resolved issues and error corrections
This fix updates an internal tracking hook in Planning Field Service so it matches the latest mail activity logging behavior. It helps ensure status changes continue to be recorded correctly without changing how users work.
Original PR description
Rename `_track_subtype` to `_track_log_get_default_subtype` to align with the updated mail tracking. Related Commit https://github.com/odoo/odoo/pull/248505/changes/9c1ce65cdd924b50df3eeef5c69cac110d1eb26b Forward-Port-Of: odoo/enterprise#125666
This change fixes an unreliable automated test in Web Studio that could fail unpredictably. It helps keep release validation stable and reduces false alarms during quality checks, without changing user-facing behavior.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
Belgian payroll now correctly assigns an employee's DMFA work location when a matching work address is used on a new contract version. This helps ensure payroll location and working region information is accurate without requiring a manual address update.
Original PR description
After creating a dmfa location unit, creating a new version for an employee with the matching address_id should have self.l10n_be_location_unit and self.l10n_be_working_region set to the new value. For now, the field is only recomputed when updating address_id field.
- Steps to reproduce:
- With l10n_be_hr_payroll installed, create an employee in a BE company.
- Create a dmfa work location for the employee work address.
- Create a new contract for that employee.
- Employee l10n_be_location_unit field is still False.
- Cause: the compute method is triggered only on address_id field update.
- Solution: add `address_id.l10n_be_dmfa_location_unit_ids` to the depends decorator of the compute method.
Task: 6360653Payroll module upgrades are now protected from a crash caused by warning checks running too early. This helps businesses complete payroll updates more reliably, especially when optional payroll features are installed.
Original PR description
task-6345962
This fix updates an internal payroll test to use its own employee data instead of reusing an employee with existing payroll values. It helps keep India payroll percentage checks accurate and stable without changing payroll behavior for users.
Original PR description
Use a dedicated employee/version for the percentage computation test instead of Rahul, whose existing payroll values affect copied version data. Define the test amounts in common and reuse `employee.version_id` in the test, so percentages are derived from amounts without changing payroll behavior. task-6340923 Forward-Port-Of: odoo/enterprise#124330 Forward-Port-Of: odoo/enterprise#121918
This update prevents occasional errors when a signing PDF preview is closed or detached at just the wrong moment. It improves the reliability of automated checks and helps keep the Sign app stable without changing user-facing behavior.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
This fix prevents the timesheet assistant from crashing when away-time activity is processed without an expected unmatched group. Users can continue reviewing and categorizing time entries without interruption.
Original PR description
Before this commit, when the unmatched group is not found in events before processing afk event, a traceback occurs saying `Cannot read properties of undefined (reading 'Away (afk status 1)')` This commit moves the code checking the group key exists in `this.state.grouped` after processing afk event and before adding the afk event in unmatched group. Forward-Port-Of: odoo/enterprise#124072 Forward-Port-Of: odoo/enterprise#123452
When equipment is manually removed from a field service shift, later edits such as changing shift times or signing in no longer add it back automatically. This helps teams keep shift equipment lists accurate while still refreshing the list when the customer is changed.
Original PR description
Issue: When a user manually removes a specific equipment (SN) from a shift's list, editing the shift times or signing in reloads the entire list, bringing the deleted equipment back. Solution: Skip reassignment if the currently selected lots (`._origin`) are a valid subset of the customer's total equipment. This preserves manual deletions while still correctly updating the list if the customer is completely changed. Task: 6346404
Marketing campaigns no longer crash when a user clears the Target field while editing a campaign. This keeps campaign setup stable and avoids an unexpected error during normal data entry.
Original PR description
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` >…
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` > `Campaigns`. - Create a `new campaign` and clear the `Target` field. `KeyError: False` After the recent commit that added the recipients_count field and its computation [1], when the user removes model_id(Target), model_name is set to False [2]. The domain is then updated by a compute method, which triggers the computation of recipients_count. Since the computation only checks whether domain is set and does not verify that model_name is available, it attempts to access the model using model_name, raising the error [3]. This commit ensures that, when computing the recipient count, it also checks that model_name is set. Since model_id is a required field, once it is set, the recipient count is computed correctly based on the domain and model_name. [recent commit]: https://github.com/odoo/enterprise/commit/5485e8eaa7636c7dd0b305b4e26fb772aff6d030 [1]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L43 [2]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L33 [3]- https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L146-L148 sentry-7612724367
The timesheet assistant now lets long description fields expand so users can read the full content instead of seeing it cut off. This makes reviewing and editing timesheet entries clearer and reduces the chance of missing important details.
Original PR description
- changed the description field to expand dynamically to display long descriptions in full instead of truncating them in the assistant Task-6348575 Forward-Port-Of: odoo/enterprise#124806 Forward-Port-Of: odoo/enterprise#123428
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solu
Original PR description
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, temporary `sudo()` usage is required in specific places. opw-6087460 Forward-Port-Of: odoo/odoo#259299
The image crop tests could fail non-deterministically because the cropper bundle is not yet loaded. As a result, waiting for the cropper does not guarantee that the cropper has finished initializing. Introduce a `waitForCropperReady()` helper that resolves once `ImageCrop.show()` has completed, ensuring that the cropper is fully initialized before the tests continue. runbot- 937826 Forward-Port-Of: odoo/odoo#278037
Original PR description
The image crop tests could fail non-deterministically because the cropper bundle is not yet loaded. As a result, waiting for the cropper does not guarantee that the cropper has finished initializing. Introduce a `waitForCropperReady()` helper that resolves once `ImageCrop.show()` has completed, ensuring that the cropper is fully initialized before the tests continue. runbot- 937826 Forward-Port-Of: odoo/odoo#278037
`t-key` are automatically added to `t-for` elements in templates, but if someone defines `t-key` himself, the converter is supposed to keep it as is. Before this fix: -`t-key` is kept but a closing tag (`>`) is added every iteration. After this fix: -`t-key` is correctly kept, nothing added in addition. Forward-Port-Of: odoo/odoo#276858
Original PR description
`t-key` are automatically added to `t-for` elements in templates, but if someone defines `t-key` himself, the converter is supposed to keep it as is. Before this fix: -`t-key` is kept but a closing tag (`>`) is added every iteration. After this fix: -`t-key` is correctly kept, nothing added in addition. Forward-Port-Of: odoo/odoo#276858
20 changes
Enhancements to existing features
It is mandatory in BE to add a legal note on the invoice when using a "Co-Contractant" tax task-5905176 Forward-Port-Of: odoo/odoo#276628 Forward-Port-Of: odoo/odoo#251797
Original PR description
It is mandatory in BE to add a legal note on the invoice when using a "Co-Contractant" tax task-5905176 Forward-Port-Of: odoo/odoo#276628 Forward-Port-Of: odoo/odoo#251797
Resolved issues and error corrections
This fixes an internal test setup for Indian payroll so percentage calculations are checked using dedicated sample employee data. It helps prevent unrelated employee payroll values from affecting test results, without changing actual payroll behavior for users.
Original PR description
Use a dedicated employee/version for the percentage computation test instead of Rahul, whose existing payroll values affect copied version data. Define the test amounts in common and reuse `employee.version_id` in the test, so percentages are derived from amounts without changing payroll behavior. task-6340923 Forward-Port-Of: odoo/enterprise#124062 Forward-Port-Of: odoo/enterprise#121918
This fix prevents an error that could occur when multiple equity transactions are processed at the same time. It improves reliability for users working with cap table or equity transaction data by avoiding unexpected crashes during price calculation.
Original PR description
When the ``_compute_security_price`` method is called on multiple records, a traceback will appear. Traceback: ```py ValueError: Expected singleton: equity.transaction(1, 2) ``` https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/equity/models/equity_transaction.py#L218 The method filters newly created records using ``self._origin.id``. Since ``self`` is the whole recordset, accessing ``self._origin.id`` on multiple records raises a singleton error. sentry-7626410485 Forward-Port-Of: odoo/enterprise#125307
This fix prevents Swiss payroll processing from failing when a related payroll rule has been archived. It helps ensure payroll data can continue to be handled smoothly without unexpected error screens for users.
Original PR description
Forward-Port-Of: odoo/enterprise#103677
The trial balance report now handles load-more rows that have empty column data, preventing an error in the Colombian partner-grouped variant. This lets users continue expanding accounts and viewing additional report lines without interruption.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451 Forward-Port-Of: odoo/enterprise#124506 Forward-Port-Of: odoo/enterprise#124102
This change adds a test to ensure financial reports handle changing domestic currency rates correctly. It helps prevent incorrect currency translation adjustment values when exchange rates fluctuate during the reporting period.
Original PR description
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD…
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD rate=1 from Jan 1 to Jun 30, USD rate=3 from Jul 1 to Dec 31 EUR rates unchanged: 2 from Jan 1, 4 from Jul 1 Correct conversion factors (= USD_rate / EUR_rate): Jan 1 – Jun 30 (182 days): 1/2 = 0.50 Jul 1 – Dec 31 (184 days): 3/4 = 0.75 Current rate at 2020-12-31: 3/4 = 0.75 Correct average rate: (0.50 * 182 + 0.75 * 184) / 366 = 229/366 ≈ 0.62568 Previsouly bugged average rate (USD fixed at current=3): (1.50 * 182 + 0.75 * 184) / 366 = 411/366 ≈ 1.12295 Historical equity rates (correct vs previously bugged): Mar 1 (USD=1, EUR=2): correct = 1/2 = 0.50; buggy = 3/2 = 1.50 → 40 * 0.50 = 20 vs 40 * 1.50 = 60 Oct 1 (USD=3, EUR=4): correct = 3/4 = 0.75; buggy = 3/4 = 0.75 → 60 * 0.75 = 45 (same by coincidence) task-5953104 Forward-Port-Of: odoo/enterprise#123055
The Belgian minimum salary warning will now only appear for employees using Belgian payroll rules. This prevents irrelevant alerts from showing for employees in other countries, reducing confusion for HR users.
Original PR description
[FIX] l10n_be: fix min salary warning appearance in other l18n Bug reproduc: 1 - Install l10n_be_hr_payroll 2 - Go to some US employee, make its wage to 10. 3 - The warning "Annual salary is below 34654" will be there. Bug cause: 1 - The issue is created without controlling the country of the version Bug solution: 1 - Add Belgium country check to the issue creation task-6412374
This update fixes an unreliable automated tour test in Web Studio. It helps reduce false failures in validation pipelines, making releases and quality checks more dependable without changing user-facing behavior.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
This fix prevents an occasional timing issue from causing errors when the signing document viewer closes or reloads at just the wrong moment. It improves stability for Odoo Sign and helps keep automated validation runs clean without changing user-facing behavior.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
Vehicle references on invoice lines are no longer clickable while an invoice is still in draft. This keeps draft invoice behavior consistent with product links and helps prevent users from navigating to vehicle records before the invoice is finalized.
Original PR description
The vehicle under account on the invoice lines should not be clickable when the invoice is in draft. Only when it is posted, like the product. task-6385436 Forward-Port-Of: odoo/enterprise#124514
Fixed an issue where sales order information could be hidden on planning slot forms for companies using a single-company setup. This ensures users can consistently see and use the relevant sales order field regardless of company configuration.
Original PR description
The `sale_line_id` field was previously injected after `company_id`. Because the first instance of `company_id` in the base view is wrapped inside a `<t groups="base.group_multi_company">` block, the inserted fields were inadvertently hidden in single-company databases. This commit changes the XPath target to `role_id` to ensure the sales order fields are always visible in the planning slot form view, regardless of multi-company settings. task: 6398673 Forward-Port-Of: odoo/enterprise#125712
**Steps to reproduce:** - Enable 2FA - Change user language - Log in in another private window / device - Check the notification email of a login with another device - Email body/subject are not properly adapted to user language **Issue:** View manual rendering doesn't pass the user language. **Fix:** Add it to the context before `_render_template` and subject translation (reapply similar fix [1]). [1] https://github.com/odoo/odoo/commit/4d8d1736ca03a3d6b4e86cbc7463a79a284d1f3c
Original PR description
**Steps to reproduce:** - Enable 2FA - Change user language - Log in in another private window / device - Check the notification email of a login with another device - Email body/subject are not properly adapted to user language **Issue:** View manual rendering doesn't pass the user language. **Fix:** Add it to the context before `_render_template` and subject translation (reapply similar fix [1]). [1] https://github.com/odoo/odoo/commit/4d8d1736ca03a3d6b4e86cbc7463a79a284d1f3c opw-6042550 Forward-Port-Of: odoo/odoo#275705 Forward-Port-Of: odoo/odoo#261468
Steps: - Install sale app. - Create SO for portal user. - Login with portal user. - Vat field is not editable and warning is wrong. Issue: - Before https://github.com/odoo/odoo/pull/211043 and recent fix https://github.com/odoo/odoo/pull/275207 portal user can edit their Vat number even if they have confirmed documents (invoice or SO) if Vat field is not set. Since `is_company` refactoring having set parent_name on address create related company and making `is_commercial_address` False a
Original PR description
Steps: - Install sale app. - Create SO for portal user. - Login with portal user. - Vat field is not editable and warning is wrong. Issue: - Before https://github.com/odoo/odoo/pull/211043 and recent fix https://github.com/odoo/odoo/pull/275207 portal user can edit their Vat number even if they have confirmed documents (invoice or SO) if Vat field is not set. Since `is_company` refactoring having set parent_name on address create related company and making `is_commercial_address` False and because that `Vat` field became reaonly and after recent fix `is_commercial_address` was set from `can_edit_vat` and validation done based on `can_edit_vat` before that `Vat` was editable if they have confirmed documents Fix: - Only make `Vat` readonly if Vat is set and is not individual address Forward-Port-Of: odoo/odoo#278233 Forward-Port-Of: odoo/odoo#277459
When inserting nodes, they are run through `node_to_insert_processors` to possibly handle some conversions - e.g. turning paragraphs into further list items within a list. However the `insertedNodes` returned by the `insert` method are actually the nodes that were initially requested to be added. This commit puts the nodes among the `insertedNodes` after they were potentially converted. task-6364282 Forward-Port-Of: odoo/odoo#277789
Original PR description
When inserting nodes, they are run through `node_to_insert_processors` to possibly handle some conversions - e.g. turning paragraphs into further list items within a list. However the `insertedNodes` returned by the `insert` method are actually the nodes that were initially requested to be added. This commit puts the nodes among the `insertedNodes` after they were potentially converted. task-6364282 Forward-Port-Of: odoo/odoo#277789
Issue: When changing from tracking inventory active > inactive > active the product would create 2 lines in the physical inventory. The first line would correspond to the first moment it was active and it wouldn't change. The second would be the difference between the new value we are trying to set minus the 1st line. Steps to reproduce: Create a product and with tracking selected on 'By Quantity', set 'Quantity On Hand' to 5 and save. Set tracking to blank (false) and save. Set tracking t
Original PR description
Issue: When changing from tracking inventory active > inactive > active the product would create 2 lines in the physical inventory. The first line would correspond to the first moment it was active and it wouldn't change. The second would be the difference between the new value we are trying to set minus the 1st line. Steps to reproduce: Create a product and with tracking selected on 'By Quantity', set 'Quantity On Hand' to 5 and save. Set tracking to blank (false) and save. Set tracking to 'By quantity' and set quantity on hand to 4. Refreshing the page will show 9 (5 + 4). Also, it will appear twice in physical inventory with quantities 5 and 4. Cause: Since the value is not reset when we change from 'By Quantity' to blank, the residual value stays and is not possible to change. Fix: Warning the user that he has to set to 0 the quantity of the product before he can change the tracking to blank. opw-6316788
`Store._deep_freeze()` converted callables to their `__code__` object when building immutable cache keys. While code objects are hashable, keeping them directly in the frozen structure unnecessarily ties cache keys to runtime objects. Instead, identify functions by the hash of their code object. This keeps the ability to distinguish functions without holding a reference to the code object longer than necessary. task-6410303
Original PR description
`Store._deep_freeze()` converted callables to their `__code__` object when building immutable cache keys. While code objects are hashable, keeping them directly in the frozen structure unnecessarily ties cache keys to runtime objects. Instead, identify functions by the hash of their code object. This keeps the ability to distinguish functions without holding a reference to the code object longer than necessary. task-6410303
Account codes are no longer required on accounts. The import template that is given in accounting settings > import still indicates that the code is mandatory. This commit removes this mandatory indicator from the template. task-6313017
Original PR description
Account codes are no longer required on accounts. The import template that is given in accounting settings > import still indicates that the code is mandatory. This commit removes this mandatory indicator from the template. task-6313017
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are themselves fetched in sudo. That override, however, applies to every many2one related/inherited field, not just x2m ones, and ignores the field's own `compute_sudo` attribute. For a field with `compute_sudo=False`, the compute is still forced through `sudo()`, while every subsequent cache lookup on th
Original PR description
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are…
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are themselves fetched in sudo.
That override, however, applies to every many2one related/inherited field, not just x2m ones, and ignores the field's own `compute_sudo` attribute. For a field with `compute_sudo=False`, the compute is still forced through `sudo()`, while every subsequent cache lookup on that field (in `Field.__get__`) is done on the non-sudo environment.
This is visible on `res.users.main_user_id`, an inherited field `res.partner.main_user_id` (compute_sudo=False, depends_context('uid')). The compute succeeds, but the resulting value is written into the sudo cache instead of the caller's cache, so the non-sudo cache check right after considers it missing:
```py
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py", line 1827, in __get__
raise ValueError(f"Compute method failed to assign {missing_recs}.{self.name}")
ValueError: Compute method failed to assign res.users(2,).main_user_id
```
Confirmed in pdb: the id is missing from the plain cache but present in the sudo one:
```py
> /home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py(1823)__get__()
-> missing_recs_ids = tuple(self._cache_missing_ids(recs))
(Pdb) tuple(self._cache_missing_ids(recs))
(2,)
(Pdb) tuple(self._cache_missing_ids(recs.sudo()))
()
```
Steps to reproduce:
- in saas~19.3, open the Users list view
- using Studio, add the `main_user_id` field to the list view
- the view fails to load with: "The requested change caused an error in the view. It could be because a field was deleted, but still used somewhere else."
- The error in logs is the `ValueError` mentioned above
Restrict the forced `sudo()` to x2m fields, which is what the original comment describes and what actually needs it, and let many2one related fields honor their own `compute_sudo` like every other compute does.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prDescription of the issue/feature this PR addresses: report_stock_quantity uses m.quantity instead of the done quantity converted to the product's base UoM when computing the forecast for done inter-warehouse moves. This causes incorrect forecast values when a done stock move uses a UoM with a factor greater than 1. Current behavior before PR: When a done inter-warehouse move uses a UoM with factor > 1 (e.g. a box of 25 units), the forecast only subtracts the raw done quantity (e.g. 2 bo
Original PR description
Description of the issue/feature this PR addresses: report_stock_quantity uses m.quantity instead of the done quantity converted to the product's base UoM when computing the forecast for done…
Description of the issue/feature this PR addresses: report_stock_quantity uses m.quantity instead of the done quantity converted to the product's base UoM when computing the forecast for done inter-warehouse moves. This causes incorrect forecast values when a done stock move uses a UoM with a factor greater than 1. Current behavior before PR: When a done inter-warehouse move uses a UoM with factor > 1 (e.g. a box of 25 units), the forecast only subtracts the raw done quantity (e.g. 2 boxes) instead of the converted quantity in the product's base UoM (e.g. 50 units). This causes the forecast chart to show incorrect negative values before the move date. Steps to reporduce: - Create a storable product with base UoM = Units - Create a UoM "Box of 25" with factor = 25 in the Units category, and add it to the product's allowed UoMs - Create a second warehouse - Do an inventory adjustment of 800 units into warehouse 1 - Create an inter-warehouse transfer of 2 "Box of 25" (= 50 units) from warehouse 1 to warehouse 2 and validate it - Open the forecast chart for the product filtered to warehouse 1 Desired behavior after PR is merged: The forecast report for done inter-warehouse moves correctly converts the done quantity to the product's base UoM using the move's UoM factor, so the forecast chart shows accurate values regardless of the UoM used on the move. opw-6266745 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273797 Forward-Port-Of: odoo/odoo#271766
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module and switch to an IT Company. - Create a new customer and set only the country to Italy and the Tax ID. - Create a new invoice for that customer. - Add a line with `22%` and `4% INPS` taxes. - Go to the `Electronic Invoicing` tab, set the `Document Type` to `TD07 - Simplified invoice`, and c
Original PR description
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module…
Currently, sending a simplified invoice (`TD07`) to the Italian Tax Agency fails when an invoice line contains multiple taxes. **Steps to reproduce:** - Install the `l10n_it_edi_withholding` module and switch to an IT Company. - Create a new customer and set only the country to Italy and the Tax ID. - Create a new invoice for that customer. - Add a line with `22%` and `4% INPS` taxes. - Go to the `Electronic Invoicing` tab, set the `Document Type` to `TD07 - Simplified invoice`, and confirm the invoice. - Try to `Send To Tax Agency`. **Error:** `Node: <Natura t-if="line.tax_ids.l10n_it_exempt_reason" t-out="line.tax_ids.l10n_it_exempt_reason"/>` `ValueError: Expected singleton: account.tax(102, 3)` **Root Cause:** At [1], the code accesses `line.tax_ids.l10n_it_exempt_reason`, but when an invoice contains multiple taxes, causing an error. **Fix:** This commit prevents the error and ensures the user can send a simplified invoice by applying a fix similar to [2]. [1]: https://github.com/odoo/odoo/blob/230483ffd7d8674cd6bf98a4ffb6591f755422e0/addons/l10n_it_edi/data/invoice_it_simplified_template.xml#L14 [2]: https://github.com/odoo/odoo/blob/230483ffd7d8674cd6bf98a4ffb6591f755422e0/addons/l10n_it_edi/data/invoice_it_template.xml#L28-L181 Ticket [link](https://www.odoo.com/odoo/project.task/6354138) Ticket [link](https://www.odoo.com/odoo/project.task/6379377) opw-6354138 opw-6379377 Forward-Port-Of: odoo/odoo#278307 Forward-Port-Of: odoo/odoo#273823
13 changes
Resolved issues and error corrections
Adds a validation test to ensure reports calculate currency translation adjustments correctly when the company's domestic currency rate changes during the year. This helps prevent overstated or understated financial reporting figures in multi-currency scenarios.
Original PR description
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD…
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD rate=1 from Jan 1 to Jun 30, USD rate=3 from Jul 1 to Dec 31 EUR rates unchanged: 2 from Jan 1, 4 from Jul 1 Correct conversion factors (= USD_rate / EUR_rate): Jan 1 – Jun 30 (182 days): 1/2 = 0.50 Jul 1 – Dec 31 (184 days): 3/4 = 0.75 Current rate at 2020-12-31: 3/4 = 0.75 Correct average rate: (0.50 * 182 + 0.75 * 184) / 366 = 229/366 ≈ 0.62568 Previsouly bugged average rate (USD fixed at current=3): (1.50 * 182 + 0.75 * 184) / 366 = 411/366 ≈ 1.12295 Historical equity rates (correct vs previously bugged): Mar 1 (USD=1, EUR=2): correct = 1/2 = 0.50; buggy = 3/2 = 1.50 → 40 * 0.50 = 20 vs 40 * 1.50 = 60 Oct 1 (USD=3, EUR=4): correct = 3/4 = 0.75; buggy = 3/4 = 0.75 → 60 * 0.75 = 45 (same by coincidence) task-5953104 Forward-Port-Of: odoo/enterprise#123055
Mexican electronic invoicing fields are now placed in a stable invoice header area instead of depending on the order of installed localization modules. This prevents the CFDI Origin field from disappearing on Mexican invoices when the Colombian localization is also installed.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
Sales order information on planning slot forms is now visible for single-company users. This prevents important sales details from being hidden because of company configuration, making scheduling linked to sales orders more reliable.
Original PR description
The `sale_line_id` field was previously injected after `company_id`. Because the first instance of `company_id` in the base view is wrapped inside a `<t groups="base.group_multi_company">` block, the inserted fields were inadvertently hidden in single-company databases. This commit changes the XPath target to `role_id` to ensure the sales order fields are always visible in the planning slot form view, regardless of multi-company settings. task: 6398673
This update prevents occasional errors when the Sign PDF viewer is closed or detached while it is still loading. It improves stability in automated testing and reduces the chance of users encountering unexpected Sign document viewing issues.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
This fixes an issue in Mexican payroll where clearing a payslip start or end date could trigger an error and interrupt the workflow. The system now checks that required dates are present before running the salary-limit warning calculation, helping payroll users edit payslips safely.
Original PR description
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI`…
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI` company - Go to `Payslips`, create a payslip. - Set an `employee`, and remove either the `start date` or the `end date` from Period.. `TypeError: unsupported operand type(s) for +: 'bool' and 'relativedelta'` After the [recent commit] adding a warning about the employee exceeding the salary limit, when the user removes the dates from the payslip, the compute method attempts to compute the warning from [1], and when it adds relativedelta to date_from, which is False, it raises the error [2]. This commit ensures that the payslip dates are checked first before adding relativedelta to the date and performing the comparison. [recent commit]: https://github.com/odoo/enterprise/commit/6abfa47dafe439f9328d606ef6ac5126ec6eb1f6 [1]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/hr_payroll/models/hr_payslip.py#L1446 [2]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py#L272-L276 Forward-Port-Of: odoo/enterprise#124187 Forward-Port-Of: odoo/enterprise#122643
Updated AI tool descriptions to remove misleading labels that could cause automated agents to call the wrong function. This helps improve reliability when AI agents search or group records in Odoo.
Original PR description
Purpose: -------- Agents occasionally fail by trying to call a `search` tool that does not exist. This seems to come from the `Tool Name: search` header in the tool description, which can be confused with the actual tool name used by the LLM, i.e. the tool xmlid. This commit removes these headers from the search and read group tool descriptions. They were missed in [this commit](https://github.com/odoo/enterprise/commit/912bce43a98d45e90dbd24328fa2f46caba4c887 ), which removed the same headers from the other tools. Task-6401285 Forward-Port-Of: odoo/enterprise#125110
The timesheet sample data button now works even when ActivityWatch is connected. Users can add sample events alongside real activity data, making demos and testing easier without disconnecting ActivityWatch.
Original PR description
Before this commit, the Generate Sample Data button only worked when the ActivityWatch server was unavailable. When ActivityWatch was running, users could only load real activity data. After this commit, clicking Generate Sample Data while ActivityWatch is connected injects the generated sample events alongside the real ActivityWatch events, allowing both to be displayed together. task-6373606
The Vietnam Sales Tax Report now keeps VAT base amounts positive at the detailed invoice level, matching the totals shown higher in the report. This removes a confusing negative display for sales VAT and helps users review Vietnamese tax reporting figures more confidently.
Original PR description
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should…
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should be consistent with the upper layers and kept positive ## Steps to reproduce: - Install l10n_vn (l10n_vn_reports will install as well) - Switch to VN Company - With demo data, go to Invoicing / Reporting / Tax Report - Change Tax Report (VN) to Sales/Purchase Tax Report (VN) - Unfold the lines all the way to the minimum layer: VAT on sales of goods and services 10% -> INV/2026/00003 - Observe that the VAT 10% line is at negative, which is inconsistent with the Total line below ## Cause of the issue: - In Odoo, tax journal items store tax_base_amount with the accounting sign (negative for sales). This is expected behavior - However, Vietnamese VAT listing expects commercial amounts, which means sales bases need to be displayed as positive numbers ## Fix: Normalized tax_base_amount sign in _query_tax_lines function before building the SQL query opw-6344577 Forward-Port-Of: odoo/enterprise#122785
This fix prevents timesheet-related automation from being affected by unread notification counts in Discuss. It helps avoid incorrect handling of timesheet reminders when message badges appear in the interface.
Original PR description
task: 6416889
The timesheet assistant now uses the correct color cue for total hours, showing green when recorded time is below expected working hours. Flexible-hour schedules no longer receive an unnecessary color indicator, reducing confusion for employees and managers reviewing timesheets.
Original PR description
Fix the wrong color selection of total hours on the timesheet assistant page before: green if total time > working hours after: - green if total time < working hours - no color for flexible hours --- task-6409938
We now search for the rates that can be used, instead of arbitrary filtering on the rates from the current main company, because - a branch could use the rates of its parents - company_id is not required on exchange rate objects ; when it's not set, it's for every company task-5953104 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.o
Original PR description
We now search for the rates that can be used, instead of arbitrary filtering on the rates from the current main company, because - a branch could use the rates of its parents - company_id is not required on exchange rate objects ; when it's not set, it's for every company task-5953104 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#259557
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt -> the ZATCA QR code is too small to be scanned. Why it's happening ------------------ The phase 2 QR code is big because it also contains the invoice hash, signature and public key. We render it at 200 px, which is too small to scan a QR with that much data. The QR image also has no max
Original PR description
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt -> the ZATCA QR code is too small to be scanned. Why it's happening ------------------ The phase 2 QR code is big because it also contains the invoice hash, signature and public key. We render it at 200 px, which is too small to scan a QR with that much data. The QR image also has no max width, so it gets cut when the receipt is narrow. The fix ------- Render it at 400 px, and add `max-width: 100%` so it is not cut on a narrow receipt. opw-6399766 Before <img width="647" height="1036" alt="image" src="https://github.com/user-attachments/assets/6bcb8526-71a8-4d9f-8372-219959416214" /> After <img width="649" height="1031" alt="image" src="https://github.com/user-attachments/assets/70f5fdb5-ba71-4fbe-8f03-ef0a1b29be2e" /> Forward-Port-Of: odoo/odoo#277813
Steps to reproduce the bug: - Load a database without demo data - Install `auth_ldap` - Run the `TestAuthLDAP.test_auth_ldap` test Problem: The test failed with a 404 error on `POST /web/login`: `requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://127.0.0.1:8069/web/login`. The mocked `_get_ldap_dicts` hardcoded the LDAP config's template `user` as `(6, "Marc Demo")`, assuming the demo user `base.user_demo` exists with that id. Without demo data, `res.users(6,)`
Original PR description
Steps to reproduce the bug: - Load a database without demo data - Install `auth_ldap` - Run the `TestAuthLDAP.test_auth_ldap` test Problem: The test failed with a 404 error on `POST /web/login`: `requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://127.0.0.1:8069/web/login`. The mocked `_get_ldap_dicts` hardcoded the LDAP config's template `user` as `(6, "Marc Demo")`, assuming the demo user `base.user_demo` exists with that id. Without demo data, `res.users(6,)` does not exist, so `_get_or_create_user`'s `SudoUser.browse(conf['user'][0]).copy(...)` raised a `MissingError`, which Odoo's HTTP dispatcher turns into a 404. Solution: Create a dedicated "user template" at the start of the test and use it as the LDAP template user, instead of hardcoding a demo-data record id. This makes the test self-contained and independent of whether demo data is loaded. runbot-243648 Forward-Port-Of: odoo/odoo#277463
6 changes
Resolved issues and error corrections
This update prevents occasional errors when the Sign document preview closes or reloads at the same time it is being prepared. It improves reliability in automated testing and reduces the chance of users encountering intermittent failures while opening signing requests.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
The expense Stripe cardholder field now uses the standard setup for selecting related records. This ensures any selection rules configured in the view are applied correctly, helping users see the right cardholder options.
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 Forward-Port-Of: odoo/enterprise#125346
The AI assistant guidance was cleaned up to remove misleading labels that could cause it to request a non-existent search action. This reduces avoidable agent failures and helps AI features behave more consistently.
Original PR description
Purpose: -------- Agents occasionally fail by trying to call a `search` tool that does not exist. This seems to come from the `Tool Name: search` header in the tool description, which can be confused with the actual tool name used by the LLM, i.e. the tool xmlid. This commit removes these headers from the search and read group tool descriptions. They were missed in [this commit](https://github.com/odoo/enterprise/commit/912bce43a98d45e90dbd24328fa2f46caba4c887 ), which removed the same headers from the other tools. Task-6401285 Forward-Port-Of: odoo/enterprise#125110
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solu
Original PR description
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, temporary `sudo()` usage is required in specific places. opw-6087460 Forward-Port-Of: odoo/odoo#259299
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 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.odo
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 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#278123
Steps to reproduce the bug: - Load a database without demo data - Install `auth_ldap` - Run the `TestAuthLDAP.test_auth_ldap` test Problem: The test failed with a 404 error on `POST /web/login`: `requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://127.0.0.1:8069/web/login`. The mocked `_get_ldap_dicts` hardcoded the LDAP config's template `user` as `(6, "Marc Demo")`, assuming the demo user `base.user_demo` exists with that id. Without demo data, `res.users(6,)`
Original PR description
Steps to reproduce the bug: - Load a database without demo data - Install `auth_ldap` - Run the `TestAuthLDAP.test_auth_ldap` test Problem: The test failed with a 404 error on `POST /web/login`: `requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://127.0.0.1:8069/web/login`. The mocked `_get_ldap_dicts` hardcoded the LDAP config's template `user` as `(6, "Marc Demo")`, assuming the demo user `base.user_demo` exists with that id. Without demo data, `res.users(6,)` does not exist, so `_get_or_create_user`'s `SudoUser.browse(conf['user'][0]).copy(...)` raised a `MissingError`, which Odoo's HTTP dispatcher turns into a 404. Solution: Create a dedicated "user template" at the start of the test and use it as the LDAP template user, instead of hardcoding a demo-data record id. This makes the test self-contained and independent of whether demo data is loaded. runbot-243648 Forward-Port-Of: odoo/odoo#277463
2 changes
Resolved issues and error corrections
This fixes a display issue where Mexican CFDI invoice fields could disappear when Colombian e-invoicing was also installed. The fields are now placed in a stable invoice header area, so Mexican users can reliably see the CFDI Origen information.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
This fixes FedEx label generation so outbound shipments are no longer incorrectly treated as return shipments when return labels are enabled. Businesses using FedEx returns should now see the expected reference information on original shipment labels, improving traceability and reducing label confusion.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
3 changes
Enhancements to existing features
Comply with new provincial fiscal transparency regulations (CABA, Entre Ríos, Chubut, and other provinces still not defined) that mandate detailing Perception IIBB taxes on B2C invoices (Factura/Invoice B): - Some jurisdictions mandate a new description for IIBB perception taxes on the invoice, - We need to put the IIBB perception taxes in the special "Fiscal Transparency Regime" table, and exclude them from the standard tax table, task-6367087 Forward-Port-Of: odoo/odoo#277673
Original PR description
Comply with new provincial fiscal transparency regulations (CABA, Entre Ríos, Chubut, and other provinces still not defined) that mandate detailing Perception IIBB taxes on B2C invoices (Factura/Invoice B): - Some jurisdictions mandate a new description for IIBB perception taxes on the invoice, - We need to put the IIBB perception taxes in the special "Fiscal Transparency Regime" table, and exclude them from the standard tax table, task-6367087 Forward-Port-Of: odoo/odoo#277673
Resolved issues and error corrections
This fixes FedEx shipping labels so regular outbound shipments are no longer treated as courtesy returns when return labels are enabled. As a result, the expected reference field appears correctly on the original shipment label, improving label accuracy for warehouse and shipping teams.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
`_get_belgian_cocontractant_note()` resolves the co-contractant fiscal position through chart_template.ref(), which uses env.company. The "Send invoices automatically" cron runs as the inactive OdooBot user, so env.company is OdooBot's default company, not the invoice's. That company can differ from the invoice's and even be archived, in which case ref() raises "IndexError: tuple index out of range" (parent_ids is empty for an archived company) Steps to reproduce: - Set the main company to a
Original PR description
`_get_belgian_cocontractant_note()` resolves the co-contractant fiscal position through chart_template.ref(), which uses env.company. The "Send invoices automatically" cron runs as the inactive OdooBot user, so env.company is OdooBot's default company, not the invoice's. That company can differ from the invoice's and even be archived, in which case ref() raises "IndexError: tuple index out of range" (parent_ids is empty for an archived company) Steps to reproduce: - Set the main company to a non-Belgian company, and invoice from another active Belgian company. - Move every active user off the main company and archive it - Send a Belgian 0% invoice through the cron. => IndexError: tuple index out of range in chart_template.ref opw-6398778 Forward-Port-Of: odoo/odoo#278473 Forward-Port-Of: odoo/odoo#278326
34 changes
Enhancements to existing features
The Discuss header no longer shows separate star and delete buttons because those actions are already available in the More menu. This reduces duplicate options and makes the interface simpler and more consistent with the Discuss team's intended workflow.
Original PR description
Remove the star and delete buttons from the Discuss header since both actions are already available from the "More" dropdown menu. This avoids duplicate actions in the UI and aligns the interface with the Discuss team's requested behavior. task-6420174 <img width="1197" height="308" alt="image" src="https://github.com/user-attachments/assets/f424e605-d4c8-4d29-9b7e-fe69b853324c" />
The Dimona check button for Belgian payroll is now shown when debug mode is enabled or when the sandbox environment is open. This makes it easier for authorized users to test and verify Dimona-related employee information in the right contexts without affecting normal production use.
Original PR description
Update the check dimona button to appear if the debug mode is open or sandbox is opened Task Id : 6398635
The payroll dashboard no longer shows an invalid language warning for Belgian payslips. Instead, it now warns users when the DMFA work location language is missing, helping payroll teams fix the setting that matters for official payslip delivery.
Original PR description
Currently, Payslip is sent both in employee language and the DMFA work location language. This happen to make sure the payslip is sent in one of the official language. In this PR, expected to improve the warning that appears in Payroll Dashboard. The specifications required to: - Remove the warning about "Invalid Language" - Add a warning regarding the DMFA work location if the language is not set task-6377966
Payroll localization modules are now installed through Odoo's standard country-based auto-install process instead of a later setup hook. This reduces upgrade surprises and keeps payroll localization status more consistent during installations and updates.
Original PR description
Previously, a post-init hook was used in `hr_payroll` to install `l10n_XX_hr_payroll` modules for each country where a company is located. This could lead to issues and unexpected behavior during upgrades as this is run later in the process. Modules installed by the hook were considered as `uninstalled` until the `hr_payroll` was loaded. However, this auto_install behavior is now fully handled by the `auto_install` + `countries` mechanism in the manifests. The hook can then be safely removed. All the `l10n_XX_hr_payroll` modules where already using the configuration `auto_install: ['hr_payroll']` with `countries: ['XX']`, no change is needed in those modules. Only `l10n_us_hr_payroll` was still using that hook since it had a dependency on `l10n_us`. This was fixed in a [dedicated PR]. [dedicated PR]: https://github.com/odoo/enterprise/pull/120279
Resolved issues and error corrections
This update replaces shared editable defaults with safer fixed values in record search settings across many Odoo Enterprise modules. It reduces the risk of rare cross-record side effects and prepares the codebase for stricter automated quality checks, with no expected change to day-to-day user workflows.
Original PR description
Mutable default values share state across all instances of the class. This can lead to bugs when the attributes are changed in one instance, as those changes will unexpectedly affect all other instances.[^1] Most `_rec_names_search` are defined as lists, but could be defined as immutable tuples instead. Found using the linter at odoo/odoo#217724. This linter will be merged only after all existing findings are resolved. This merge contains 2 commits: 1. The execution of the `tuple-rec_names_search` upgrade-code script. 2. The fixes to address the (true/false)-negatives of the script. task-6396049 [^1]: https://docs.astral.sh/ruff/rules/mutable-class-default/
This fix removes an outdated setting from the FedEx delivery integration setup. It helps keep the shipping connection logic consistent after a previous change, reducing the chance of confusion or minor configuration issues.
Original PR description
Follow up of 6b5d4eb which forgot to remove the now unused `make_return` key. ----- Ticket: opw-6101620
This update adjusts several scheduling, map, subscription, and WhatsApp-related screens to work correctly with the newer interface framework rules. It prevents missing buttons or broken popovers in Gantt and map views while keeping the change internal and low risk for users.
Original PR description
Follow-up to the community change that makes the owl3 compatibility layer throw on `static defaultProps`. Owl 3 ignores that attribute; defaults must go through `useProps(...).optional(default)`.…
Follow-up to the community change that makes the owl3 compatibility layer throw on `static defaultProps`. Owl 3 ignores that attribute; defaults must go through `useProps(...).optional(default)`.
Remove the remaining `static defaultProps` and fold the defaults into the props schema:
- web_gantt: GanttPopover -> `props = useProps(ganttPopoverProps)`, defaults become `.optional(() => ...)`. Export `ganttPopoverProps` (props is now an instance field, so `GanttPopover.props` no longer resolves).
- web_map: MapPopover -> `props = useProps({...})`.
- whatsapp phone_field: the `patch(PhoneField, { defaultProps, props })` augmented dead statics; augment the exported `phoneFieldProps` schema instead, folding `enableWhatsAppButton: true` into `.optional(true)`.
Fix consumers broken by `props` becoming an instance field:
- appointment: AppointmentGanttPopover built its schema from `GanttPopover.props.concat(...)`; build on the exported `ganttPopoverProps`.
- sale_subscription: the `patch(Product, { props })` override augmented the now-dead static `props`; augment the exported `productProps` schema instead.This fix prevents leftover collaboration test activity from affecting an unrelated Knowledge tour. It improves build reliability by avoiding misleading errors during automated validation, with no expected change for end users.
Original PR description
This aims to fix Runbot build error #937788 ([1]). A collaboration error was thrown during a tour which makes no use of collaboration. This makes sure the bus from the previous test doesn't persist when running this tour so it doesn't interfere. [1]: https://runbot.odoo.com/odoo/runbot.build.error/937788 Forward-Port-Of: odoo/enterprise#125509
Uploading a document no longer causes an error when Auto Sort immediately moves it to another folder. This keeps the Documents workflow stable for users, with no visible change when the moved file is no longer in the current folder.
Original PR description
When Auto Sort is enabled, an uploaded document can be moved to a different folder as part of the sort. The subsequent model reload only fetches records for the current folder to select/scroll to the new record. But, the new document's is absent from `env.model.root.records`. `newRecords` ends up empty, making `newRecords[0]` undefined, which then crashes accessing record.resId. To fix this, we just return early because if the record isn't in the current folder, there's nothing to select or scroll to anyway, so returning early here doesn't change anything visible behavior, it just avoids the crash. Steps to reproudce: 1.Go to Documents. 2.Go to Company->Inbox 3.Go to the gear icon and make sure the "Auto Sort" is enabled with "Move to folder" 4.Add a new document that's sortable. 5.You'll get the error. opw-6281558 Forward-Port-Of: odoo/enterprise#121069
Users with IoT access but without Point of Sale access can now enable the LNA setting on IoT box records without seeing an access error. This removes an unnecessary permission-related interruption and helps IoT administration tasks run smoothly.
Original PR description
Before this commit, if a user who has IoT permissions but not POS permissions tries to enable LNA on an IoT box record, they will receive an Access Error. After this commit, a `sudo` is added to the `onchange` handler fixing the issue. task-6392548 Forward-Port-Of: odoo/enterprise#124656
The salary attachment form now shows the refund option again, matching the data already stored in the system. This helps payroll users correctly identify salary attachments that should be treated as refunds without relying on a separate wizard.
Original PR description
In an old PR (https://github.com/odoo/enterprise/pull/109195) the is_refund field was removed from the salary attachment view, although the field itself was not removed from the db. In a later PR (https://github.com/odoo/enterprise/pull/114188) the field was removed from the database but later reverted (https://github.com/odoo/enterprise/pull/123728). As it stands now, the field is in the database and is present in the view of a wizard but not in the standard form view of the salary attachment. This PR is reintroducing it. Task: 6415857 Forward-Port-Of: odoo/enterprise#125420
The U.S. accounting reports now handle deleted Profit and Loss summary lines without showing an error. This prevents interruptions when users customize report layouts and keeps the report accessible.
Original PR description
## Steps to Reproduce: 1. Install the Accounting module with demo data. 2. Enable developer mode. 3. Go to Reporting > Profit and Loss. 4. Click Configuration and delete the 'Gross Profit' line. 5. Return to the report. ## Error: `ValueError: External ID not found in the system: l10n_us_reports.pl_gross_profit` ## Cause: The report assumes the summary lines always exist and tries to fetch XML IDs. If any of these lines has been deleted, looking up will raises an error. ## Fix: Only apply the bold class to summary lines whose XML IDs are available. sentry-7601831925 Forward-Port-Of: odoo/enterprise#125200 Forward-Port-Of: odoo/enterprise#124011
This update prevents Swiss payroll processing from failing when a related payroll rule has been archived. It helps payroll teams continue monthly value handling without unexpected system errors caused by inactive rules.
Original PR description
Forward-Port-Of: odoo/enterprise#103677
Audit reports now refresh the number of invalid records when a check is reviewed successfully. This prevents users from seeing outdated anomaly counts after a check has been corrected, improving confidence in audit cycle results.
Original PR description
Problem: Sometimes after an audit check passes (gets reviewed successfully), the count of invalid records in the audit report is not updated. Steps to reproduce: 1. Add a check for an audit cycle 2. Make sure the check's domain is satisified by at least one record 3. Check the audit report and see the check you added 4. The check status should show an anomaly and the count of invalid records will be greater than 0 5. Now, edit the check so that the domain is not satisfied by any record 6. Check the audit report again and see the check you edited 7. The check status should show "Reviewed" but the count of invalid records will still be greater than 0, which is not correct Cause: When updating the status of an audit check, the count of invalid records is not updated, only the status gets updated. opw-6264177 Forward-Port-Of: odoo/enterprise#125491 Forward-Port-Of: odoo/enterprise#119227
The AI-powered SEO autofill now generates page titles and metadata in the website page's language instead of the user's personal language. This prevents multilingual websites from receiving SEO content in the wrong language, improving consistency for visitors and search engines.
Original PR description
The SEO "Fill with AI" autofill used the user's language for generation. On a website whose language differs from the user's, the generated seo metadata was therefore in the wrong language. This commit fixes this by using the page language instead. Forward-Port-Of: odoo/enterprise#123786 Forward-Port-Of: odoo/enterprise#123447
This fix prevents an error that could occur when multiple equity transactions are processed at the same time. It helps ensure equity transaction calculations complete reliably without interrupting users.
Original PR description
When the ``_compute_security_price`` method is called on multiple records, a traceback will appear. Traceback: ```py ValueError: Expected singleton: equity.transaction(1, 2) ``` https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/equity/models/equity_transaction.py#L218 The method filters newly created records using ``self._origin.id``. Since ``self`` is the whole recordset, accessing ``self._origin.id`` on multiple records raises a singleton error. sentry-7626410485 Forward-Port-Of: odoo/enterprise#125307
Accounting users no longer see a technical error when running auto reconciliation with no bank statement lines available. Instead, the system shows a clear warning, helping users understand that there is simply nothing to reconcile.
Original PR description
Currently, an error occurs when user tries to reconcile when there are no bank statements to reconcile. Steps to replicate: - Install `accountant` with demo. - Open Accounting and Click `To…
Currently, an error occurs when user tries to reconcile when there are no bank statements to reconcile. Steps to replicate: - Install `accountant` with demo. - Open Accounting and Click `To Reconcile` on the Bank Journal. - Go to the list view > Select all > From the Cog menu > Reset to draft. - Again select all and delete all the statement lines. - From Cog menu click on `Run Auto Reconciliation` > Run. Error: ``` SyntaxError: syntax error at or near ')' LINE 44: WHERE st_line.id IN () ``` Cause: - Error occurs because the [search] returns no results and the method `_try_auto_reconcile_statement_lines()` is called on an empty recordset. - Later in the flow the function `_partner_mapping()` [1] is call which makes the `self.ids` as empty tuple [2] this causes the query to have a syntaxerror. Solution: - When there are no statement lines to reconcile we show a warning notification. [search]: https://github.com/odoo/enterprise/blob/ec408cb9a569f321afc99f4065a7a0f545d4faf4/account_accountant/wizard/bank_rec_auto_reconcile_wizard.py#L21-L27 [1]: https://github.com/odoo/enterprise/blob/ec408cb9a569f321afc99f4065a7a0f545d4faf4/account_accountant/models/account_bank_statement.py#L427 [2]: https://github.com/odoo/enterprise/blob/1516209ee077cda03155686d1377eb70080538f1/account_accountant/models/account_bank_statement.py#L620 sentry-7615011817 Forward-Port-Of: odoo/enterprise#124804
This fixes an error that could occur when users loaded more partner-grouped trial balance lines for Colombian reports. The trial balance now handles empty column information correctly, so users can continue reviewing report details without interruption.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451 Forward-Port-Of: odoo/enterprise#124506 Forward-Port-Of: odoo/enterprise#124102
Fixed an issue where very large sales commission achievement records could not be opened because their identifiers were not handled correctly in the browser. Users can now access these records without seeing an erroneous “record does not exist” message.
Original PR description
Steps to reproduce: - Open an achievement with id > JS limit Issues: - We get a pop-up saying the record does not exists The reason we get this error is because since we are browsing a record with an id greater than JS limit the browser truncate it. In order to solve this issue the following PR was made #108751. A field `id_str` was added but it still wasn't working as we weren't retrieving the `id_str`. We now do this by passing `id_str` in the context and retrieving it on the `web_read`. Forward-Port-Of: odoo/enterprise#123757 Forward-Port-Of: odoo/enterprise#113701
The project forecast view was updated so its subtask button correctly connects to the current subtask action. This prevents a small interface mismatch and helps users access subtasks reliably from project task views.
Original PR description
Issue --- The inherited xpath still targets the old action-based subtask button Fix -- Update the inherited xpath to target action_open_subtasks. task-5966684 Forward-Port-Of: odoo/enterprise#124721 Forward-Port-Of: odoo/enterprise#123035
This update keeps planning field service activity tracking working with the latest mail tracking changes. It is a small internal compatibility fix that helps ensure logged updates continue to use the correct notification category.
Original PR description
Rename `_track_subtype` to `_track_log_get_default_subtype` to align with the updated mail tracking. Related Commit https://github.com/odoo/odoo/pull/248505/changes/9c1ce65cdd924b50df3eeef5c69cac110d1eb26b Forward-Port-Of: odoo/enterprise#125666
This fix prevents an intermittent error when the signing document preview is closed or removed while still loading. It improves stability in the Sign app and helps keep automated checks from failing unexpectedly.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
This update fixes an unstable automated test in Web Studio that could fail unpredictably. It helps keep the quality checks reliable so future changes can be validated with fewer false alarms.
Original PR description
runbot-error-940371 Forward-Port-Of: odoo/enterprise#125319
This fix ensures Belgian payroll structures keep their accounting journal settings when a new Belgian company or branch is created. It prevents missing payroll accounting configuration, reducing manual cleanup and helping payroll setup work correctly for new entities.
Original PR description
Steps to reproduce: 1. A structure related to BE, and set journal_id. 2. Create a new BE company or branche of the existing company. 3. Go to the created structure, the journal_id is empty. Root cause: After creating a company, _configure_payroll_account should be triggered to finish the configuration. Setting the journal_id for the existing structures (with the same company country) is part of that configuration. The method responsible to call the configuration, is _load_payroll_accounts in account_chart_template.py (hr_payroll_account), and it should call the following method: _configure_payroll_account_generic_coa. This method was deleted in master and that was the problem. task-6394082
AI chat now continues to suggest reopening the most relevant previous conversation even after the user reloads the page. This makes it easier for users to resume recent work while avoiding duplicate prompts when that chat is already open.
Original PR description
Purpose: -------- When launching an AI chat, users can be suggested to reopen the latest non-empty chat matching the same interface key and record. This suggestion used to rely on chats already present in the frontend store, so it was lost after a page reload. With this commit, the suggested channel is selected by the backend whenever the AI channel is added to the store and included in its channel data. This keeps the suggestion available after a page reload while hiding it when the previous chat is already open, but not when it is minimized. Task-6354153 Forward-Port-Of: odoo/enterprise#123044
Changing a pricelist on a subscription order now correctly refreshes the related pricing calculations. This helps prevent incorrect subscription prices or totals after sales teams update pricing terms.
This update fixes an unreliable automated test in Web Studio that could fail unpredictably. It helps keep validation runs stable so development teams can detect real issues faster and avoid delays caused by false test failures.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
Payroll module upgrades are now protected from a crash that could happen when optional payroll warning checks ran too early. This helps businesses complete payroll updates more reliably without being blocked by missing temporary setup data.
Original PR description
task-6345962 Forward-Port-Of: odoo/enterprise#122247
WhatsApp conversation headers now use the correspondent's uploaded photo instead of a generated initials icon when one is available. This makes the chat header match the member list and gives users a more consistent, recognizable experience in Discuss.
Original PR description
Unlike live chat, WhatsApp did not override channel avatar generation. The generic implementation therefore always generated an initials SVG for the channel. This gave the channel its own avatar cache key and prevented the client-side avatar URL from falling back to the correspondent's uploaded photo. As a result, the partner photo appeared in the member list but not in the Discuss header. Override WhatsApp avatar generation to return no channel avatar when the WhatsApp partner has an uploaded image. The existing client-side logic then falls back to the correspondent's avatar URL. Before: <img width="653" height="179" alt="image" src="https://github.com/user-attachments/assets/9ec5bf86-bce4-4c5b-b2ba-b09c9b6c8282" /> After: <img width="478" height="203" alt="image" src="https://github.com/user-attachments/assets/f3318257-113a-4652-9f76-522ed60e3b80" /> task-6425285
Code cleanup and technical improvements
This update simplifies how the Social app handles translated text in comment streams. It is an internal cleanup that keeps behavior the same while making the code easier to maintain.
Original PR description
This commit removes a `env._t`. `_t` is env independant.
The UrbanPiper point of sale integration was updated as part of Odoo's Owl 3 migration. This keeps the module aligned with the newer platform framework and helps preserve stability without changing business functionality.
Original PR description
As part of the Owl 3 migration, this pr aims to replace onWillUpdateProps hook with the appropriate Owl 3 alternatives.
This update modernizes internal grid and Gantt view code by replacing deprecated frontend tools and cleaning up related documentation. Users should not see functional changes, but the work helps keep timesheet, planning-style grid displays, and Gantt views easier to maintain and evolve.
Original PR description
See commit messages for details. Intended merge method: `rebase-ff`
This refactor updates several Enterprise modules to use the current web framework reference system after older compatibility mechanisms were removed. It helps keep AI, Knowledge, Planning, Spreadsheet, Stock Barcode, and Map features maintainable and aligned with the latest platform architecture, with no intended change to business workflows.
Original PR description
The `t-custom-ref` directive and the compat `useRef` / named-ref mechanism were removed from the web compatibility layer. Migrate the last enterprise usages to native Owl 3 `t-ref` + signals,…
The `t-custom-ref` directive and the compat `useRef` / named-ref mechanism were removed from the web compatibility layer. Migrate the last enterprise usages to native Owl 3 `t-ref` + signals, following the community removal patterns.
t-custom-ref -> native t-ref:
- ai: readonly_voice_transcription, voice_transcription
- knowledge: embedded_clipboard, readonly_foldable_section (editableDescendants -> `t-ref="this.editableDescendantRefs.<name>"`)
- web_map: map_popover (rootRef signal field)
- spreadsheet_edition: calendar_button (buttonRef signal + resolveRefEl)
- planning: planned_date_range_with_allocated_hours (xpath selector now matches the migrated `web.DateTimeField` root `t-ref`)
compat useRef -> signal refs:
- stock_barcode: StockBarcodeFormRenderer used `useRef("compiled_view_root")`; FormRenderer now owns `rootRef = signal.ref()` (bound by the form compiler), so use the inherited `this.rootRef` and read it through resolveRefEl.
- web_map: MapCard used `useRef("root")`; use the `this.rootRef` signal it inherits from Card (bound in Card's template).Miscellaneous changes
Forward-Port-Of: odoo/enterprise#124569 Forward-Port-Of: odoo/enterprise#124221
Original PR description
Forward-Port-Of: odoo/enterprise#124569 Forward-Port-Of: odoo/enterprise#124221
6 changes
Resolved issues and error corrections
This fixes FedEx label generation so regular outbound shipments are not incorrectly treated as return shipments when return labels are enabled. As a result, the shipment reference field appears correctly on outbound labels, improving label accuracy for shipping operations.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
Users can now duplicate several maintenance requests at once without the system showing an error. This removes a workflow interruption for teams managing maintenance activities in list view.
Original PR description
Currently, when a user attempts to duplicate multiple maintenance requests simultaneously, the system throws a ValueError (Expected singleton). This PR fixes that. ### How to reproduce the issue: - Install `mrp_maintenance` module; - Open maintenance request list view; - Select multiple records and try to duplicate them using the Action button; - It will throw a traceback stating a singleton error. ### Expected behavior after PR is merged: Now multiple maintenance requests will be copied without raising any errors.
Appointment cancellation emails are now sent in the language of the person who booked the appointment, matching the behavior of confirmation emails. This prevents customers from receiving cancellation notices in the staff member's language and improves clarity for multilingual customers.
Original PR description
**Problem:** When an appointment is cancelled, the cancellation email is always sent in the organizer's (staff member's) language, ignoring the booking customer's language. The booking confirmation,…
**Problem:**
When an appointment is cancelled, the cancellation email is always sent in the organizer's (staff member's) language, ignoring the booking customer's language. The booking confirmation, by contrast, is correctly localized.
**Steps to reproduce:**
1. Set a contact's language to a non-default one (e.g. Romanian).
2. Book an appointment for that contact (they are the booker/attendee).
3. Cancel the appointment.
4. The customer received the confirmation in Romanian but the cancellation email arrives in English.
**Current behavior:**
The cancellation email is rendered in the organizer's language.
**Expected behavior:**
The cancellation email is rendered in the booking customer's language, like the confirmation/invitation email.
**Cause of the issue:**
The cancellation uses `appointment_canceled_mail_template`, whose `lang` is `{{ object.partner_id.lang }}`. On `calendar.event`, `partner_id` is `related='user_id.partner_id'`, i.e. the organizer, not the customer. The template is posted once per event (via `_track_template`), so its single rendering language applies to every recipient, including attendees whose own language differs. The confirmation email is unaffected because it is the per-attendee `attendee_invitation_mail_template` (model `calendar.attendee`), rendered once per attendee in that attendee's language.
**Fix:**
Deriving the language from `appointment_booker_id` makes the cancellation consistent with the other appointment mails, which are meant for the person who booked the meeting. It falls back to `partner_id` when there is no booker (e.g. an event not created through the appointment flow), preserving the previous behavior in that case.
opw-6323179Windows nightly builds have been failing for several days with this obscure NSIS error message in Odoo 19.0: Internal compiler error #12345: error mmapping datablock to 30283637 Root cause: the accumulated size of `.po` files across all modules has grown past a threshold where the NSIS solid compressor tries to mmap a buffer larger than the ~2 GiB address space available to the 32-bit makensis running under Wine. Simply dropping the `/SOLID` option makes the build pass but nearly doubl
Original PR description
Windows nightly builds have been failing for several days with this obscure NSIS error message in Odoo 19.0: Internal compiler error #12345: error mmapping datablock to 30283637 Root cause: the…
Windows nightly builds have been failing for several days with this obscure NSIS error message in Odoo 19.0:
Internal compiler error #12345: error mmapping datablock to 30283637
Root cause: the accumulated size of `.po` files across all modules has grown past a threshold where the NSIS solid compressor tries to mmap a buffer larger than the ~2 GiB address space available to the 32-bit makensis running under Wine. Simply dropping the `/SOLID` option makes the build pass but nearly doubles the size of the final installer, which is not acceptable.
The chosen fix is to pre-bundle all `.po` files into a single solid 7z archive and extract it at install time using the `Nsis7z` plugin. This keeps the NSIS datablock well below the and yields comparable or better final installer size than the previous approach, along with faster build times.
While at it, this commit also modernizes the Windows build environment to unblock a separate wine-devel install regression that has been affecting Odoo 17.0 nightlies on Debian Bookworm.
Changes:
- Bundle `.po` files into `i18n_bundle.7z` inside the build container prior to invoking makensis; extract it at install time via the `Nsis7z` plugin.
- Bump the base image from Debian Bookworm to Trixie.
- Switch from `wine-devel` to `wine-stable`, which resolves the install regression on Bookworm-based builds.
- Upgrade NSIS to the latest release.
- Refactor the NSIS installation step to remove the hardcoded version from `package.py`.
This fix is made in Odoo 17.0 to unblock the wine-devel issue there and to benefit from the smaller installer size on supported stable branches.
Forward-Port-Of: odoo/odoo#278378## Issue The test `test_anglo_saxon_cogs_partial_down_payment_credit_note` from the `sale_stock` module is failing when the Kenyan localization is installed. This issue is similar to the one fixed by https://github.com/odoo/odoo/commit/b9e5807cd70d. ## Steps to reproduce 1. Install `sale_stock` and `l10n_ke_edi_oscu_stock` 2. Run the test `test_anglo_saxon_cogs_partial_down_payment_credit_note` 3. **The test fails with the following error:** ``` AssertionError: Lists differ: [{'deb
Original PR description
## Issue The test `test_anglo_saxon_cogs_partial_down_payment_credit_note` from the `sale_stock` module is failing when the Kenyan localization is installed. This issue is similar to the one fixed by…
## Issue
The test `test_anglo_saxon_cogs_partial_down_payment_credit_note` from the `sale_stock` module is failing when the Kenyan localization is installed.
This issue is similar to the one fixed by https://github.com/odoo/odoo/commit/b9e5807cd70d.
## Steps to reproduce
1. Install `sale_stock` and `l10n_ke_edi_oscu_stock`
2. Run the test `test_anglo_saxon_cogs_partial_down_payment_credit_note`
3. **The test fails with the following error:**
```
AssertionError: Lists differ: [{'debit': 0, 'credit': 40, 'account_id': 268}] != []
First list contains 2 additional elements.
First extra element 0:
{'debit': 0, 'credit': 40, 'account_id': 288}
+ []
- [{'account_id': 288, 'credit': 40, 'debit': 0},
- {'account_id': 268, 'credit': 0, 'debit': 40}]
```
## Cause
When `l10n_ke_edi_oscu_stock` is installed, the `invoice_policy` of Kenyan products (or products without a company set) is set to `"delivery"` by the `_compute_invoice_policy` method from that module:
https://github.com/odoo/enterprise/blob/f4cd9a38c699e8d8f17990a283793985bfc89948/l10n_ke_edi_oscu_stock/models/product.py#L16-L21
This impacts the `SaleOrder.qty_to_invoice` field, as we now use the `qty_delivered` (which is 0 here) instead of the `product_uom_qty`:
https://github.com/odoo/odoo/blob/d0ee4af1ddb969dfc9023c628f8b128f2b22e89d/addons/sale/models/sale_order_line.py#L1001-L1006
With a `qty_to_invoice` set to 0, the `SaleOrder._get_invoiceable_lines` doesn't add the product as an invoiceable line:
https://github.com/odoo/odoo/blob/d0ee4af1ddb969dfc9023c628f8b128f2b22e89d/addons/sale/models/sale_order.py#L1492-L1498
And finally, with the `'cogs'` invoice lines missing, the comparison with the expected values fail:
https://github.com/odoo/odoo/blob/d0ee4af1ddb969dfc9023c628f8b128f2b22e89d/addons/sale_stock/tests/test_anglo_saxon_valuation.py#L1879-L1887
## Fix
We manually set the `invoice_policy` of the test product to 'order' to keep the test configuration consistent regardless of the other modules installed.
runbot-242508Features or functions removed from Odoo
- Remove the unused quants_cache initialization, as the cached values are never accessed after this [PR](https://github.com/odoo/odoo/commit/de50d04a4db0df0b800ffcb516c2e933a35b50da). This commit removes the dead code to keep the codebase clean and maintainable.
Original PR description
- Remove the unused quants_cache initialization, as the cached values are never accessed after this [PR](https://github.com/odoo/odoo/commit/de50d04a4db0df0b800ffcb516c2e933a35b50da). This commit removes the dead code to keep the codebase clean and maintainable.
3 changes
Resolved issues and error corrections
Fixed an issue where FedEx outbound shipping labels could lose their reference field when return labels were enabled. This helps businesses keep shipment labels accurate while still supporting return label creation.
Original PR description
## Backport of #118659 Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. ----- Ticket: opw-6101620 Forward-Port-Of: odoo/enterprise#125629
This fix standardizes the XML encoding label used in SEPA and ISO 20022 payment files to uppercase. It helps avoid warnings or rejections from stricter banking providers, such as SIX in Switzerland, without changing payment workflows.
Original PR description
The W3C recommendations for XML state that the encoding defined for an XML document should not be case-sensitive. However, some banking providers (SIX for Switzerland) are stricter and may throw warnings or errors if upper-case is not used. https://www.w3.org/TR/2008/REC-xml-20081126/#NT-EncodingDecl opw-4948708
Features or functions removed from Odoo
- Remove the unused `quants_cache` initialization, as the cached values are never accessed after this [PR](https://github.com/odoo/odoo/commit/de50d04a4db0df0b800ffcb516c2e933a35b50da) - This commit removes the dead code to keep the codebase clean and maintainable.
Original PR description
- Remove the unused `quants_cache` initialization, as the cached values are never accessed after this [PR](https://github.com/odoo/odoo/commit/de50d04a4db0df0b800ffcb516c2e933a35b50da) - This commit removes the dead code to keep the codebase clean and maintainable.