Daily updates from Odoo
Wednesday, July 22, 2026
159 changes
19 changes
Enhancements to existing features
No task ID Forward-Port-Of: odoo/odoo#277308 Forward-Port-Of: odoo/odoo#276936
Original PR description
No task ID Forward-Port-Of: odoo/odoo#277308 Forward-Port-Of: odoo/odoo#276936
#### [IMP] l10n_lv: add tax report attachment tags Add tags for the tax report attachments added in the related enterprise PR and tag all existing taxes. They determine the transaction type. It also adds the special tag `Rep` that is irrelevant for the transaction type. From a base amount line tagged with `Rep` we only put 40% of the amount for the attachments. #### [IMP] l10n_lv: add a car and a representation purchase tax This commit adds 2 new taxes - "car tax": 50% of the VAT
Original PR description
#### [IMP] l10n_lv: add tax report attachment tags Add tags for the tax report attachments added in the related enterprise PR and tag all existing taxes. They determine the transaction type. It also adds the special tag `Rep` that is irrelevant for the transaction type. From a base amount line tagged with `Rep` we only put 40% of the amount for the attachments. #### [IMP] l10n_lv: add a car and a representation purchase tax This commit adds 2 new taxes - "car tax": 50% of the VAT is deductible - "representation tax": 40% of the VAT is deductible #### references task-4251184 Forward-Port-Of: odoo/odoo#272050 Forward-Port-Of: odoo/odoo#212698
Resolved issues and error corrections
This update fixes an internal payroll attendance test that was failing because it looked for fields in the wrong place and used outdated options. It helps keep automated checks reliable when validating overtime rule workflows, reducing the risk of payroll attendance issues reaching users.
Original PR description
backward port of this PR https://github.com/odoo/enterprise/pull/122284 merge upto saas-19.4 Issue: The `test_overtime_ruleset_flow` tour test was failing because the `amount_rate` field could not be found. Reason: - Couldn't find the amount_rate field as it was located in the Payroll tab and the tour did not navigate to that tab before interacting with the field. - The tour also used some selectors and values that were no longer valid, causing some steps to fail. Fix: - Open the Payroll tab before interacting with the `amount_rate` field. - Set the overtime leave request duration type to "Custom Hours". - Replace the unavailable "Salary-exempt" employee type with "Employee". - Use the checkbox input selector to interact with the attendance_based field. - Explicitly open the dropdown before clicking on `action_continue` button. - Remove the unnecessary final `action_continue` step.
This update registers the WhatsApp Identifiers translation template so it is included in the translation workflow. It helps ensure future text in this module can be translated consistently 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
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
Steps to reproduce: ================== 1. Add a Donation snippet on a page 2. Click "Donate Now" 3. Switch the website language on the payment page => Configured amounts/descriptions disappear Cause: ====== The donation snippet posts its configuration (prefilled amounts, display options, descriptions) in the request body. If the user switches the website language on the payment page, it triggers a page reload via a GET request which drops the original form body (this also applies to
Original PR description
Steps to reproduce: ================== 1. Add a Donation snippet on a page 2. Click "Donate Now" 3. Switch the website language on the payment page => Configured amounts/descriptions disappear Cause:…
Steps to reproduce: ================== 1. Add a Donation snippet on a page 2. Click "Donate Now" 3. Switch the website language on the payment page => Configured amounts/descriptions disappear Cause: ====== The donation snippet posts its configuration (prefilled amounts, display options, descriptions) in the request body. If the user switches the website language on the payment page, it triggers a page reload via a GET request which drops the original form body (this also applies to a simple page refresh). As a result, the kwargs were empty and the page fell back to the default free-amount input, losing the configured options. Solution: ========= Implement Post/Redirect/Get: on POST, redirect to /donation/pay with the options in the query string so any later GET (language switch, refresh, iframe src reload) re-renders a fully configured page without losing data. Alternative Solution: ===================== We could also store the options in the session, but the current solution is much simpler and avoids session pollution. opw-6282391 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271460
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing t
Original PR description
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ###…
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing technical name and message as the traceback when `stack` is absent. A focused regression test covers an `AbortError`-like object without `stack`. ### Tests - `git diff --check` - `node --check addons/web/static/src/core/errors/error_utils.js` - `node --check addons/web/static/tests/core/errors/error_service.test.js` - `@web/core/errors` HOOT suite: 24 tests, 107 assertions passed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr. Forward-Port-Of: odoo/odoo#276864
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
Original PR description
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
Backport the changes from `b9370ea6b70ca3020c73a6940d70ff0cf954f69f` into `mail/convert_inline` to ensure Outlook-compatible image rendering. opw-3776054 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276071 Forward-Port-Of: odoo/odoo#269436
Original PR description
Backport the changes from `b9370ea6b70ca3020c73a6940d70ff0cf954f69f` into `mail/convert_inline` to ensure Outlook-compatible image rendering. opw-3776054 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276071 Forward-Port-Of: odoo/odoo#269436
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References:
Original PR description
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References: opw-6085893 [^1]: https://lxml.de/6.0/FAQ.html#is-lxml-vulnerable-to-xml-bombs Forward-Port-Of: odoo/odoo#275893 Forward-Port-Of: odoo/odoo#275367
Before this commit When a website user had an active cart, opening the pickup location selector from a backend sale order could use the cart's delivery method instead of the one configured on the sale order. Steps to reproduce: 0. Switch to the debug mode 1. Configure 2 delivery methods (A and B) with pickup locations 2. On eCommerce add storable products to the cart and choose the delivery method A 3. In the backend, create a sale order and set the delivery method B 4. Try to set picku
Original PR description
Before this commit When a website user had an active cart, opening the pickup location selector from a backend sale order could use the cart's delivery method instead of the one configured on the sale order. Steps to reproduce: 0. Switch to the debug mode 1. Configure 2 delivery methods (A and B) with pickup locations 2. On eCommerce add storable products to the cart and choose the delivery method A 3. In the backend, create a sale order and set the delivery method B 4. Try to set pickup location and see the traceback This is caused by wrong location selector props validation and by the wrong locations fetching. This commit fixes the props of location selector to match the given ones and get the correct locations for the given delivery method. opw-6267741 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267936
Fix a series of service fee defects and add the missing coverage. Discounts: - stop duplicating the service fee line every time a global discount is (re)applied: reconciliation is keyed on tax_ids alone, so the discount line's computation_key is stripped to keep products and discount in one tax group; - recompute a post_discount fee after a 100% discount deletes the now-zero discount line (which emits no event, leaving a stale fee) (pos_discount); - keep a single fee line when a gift card
Original PR description
Fix a series of service fee defects and add the missing coverage. Discounts: - stop duplicating the service fee line every time a global discount is (re)applied: reconciliation is keyed on tax_ids…
Fix a series of service fee defects and add the missing coverage. Discounts: - stop duplicating the service fee line every time a global discount is (re)applied: reconciliation is keyed on tax_ids alone, so the discount line's computation_key is stripped to keep products and discount in one tax group; - recompute a post_discount fee after a 100% discount deletes the now-zero discount line (which emits no event, leaving a stale fee) (pos_discount); - keep a single fee line when a gift card / eWallet program is used (pos_loyalty). Fixed fee: - scale a fixed fee exactly with its quantity (5 x $2 = $10.00, not 9.99 from per-unit tax rounding); - fix the fixed fee being off by one cent on recompute. Refunds: - a refund order has no preset of its own, so recomputeServiceFees falls back to the refunded order's preset and mirrors the fee proportionally: a percentage fee is correctly signed from the (negative) refund basket, a fixed fee is scaled by the refunded fraction; - the fee must not also be refunded as an individual line (which would subtract it twice): it is excluded from auto-selection and a manual click is rejected with a warning. Restaurant: - keep the fee pinned to the bottom of the order (the last course) as courses are added. task-6372687
Multiple fixes needed to be fixed in the configurator: - Wrong static theme images in the previews ✅ - Optimization of the loading time for the static theme images ✅ - On multi language website, first editor opening shouldn't be in translate mode ✅ - Automatic module installation based on selected website type ✅ - Use theme description instead of summary in the AI prompt for the theme recommendation ✅ - Fix test tour errors ✅ - Update images used in the Configurator first Step ✅ - Upda
Original PR description
Multiple fixes needed to be fixed in the configurator: - Wrong static theme images in the previews ✅ - Optimization of the loading time for the static theme images ✅ - On multi language website, first editor opening shouldn't be in translate mode ✅ - Automatic module installation based on selected website type ✅ - Use theme description instead of summary in the AI prompt for the theme recommendation ✅ - Fix test tour errors ✅ - Update images used in the Configurator first Step ✅ - Update Fallback themes selection ✅ - Brutalist theme title doesn't change ✅ - Enforce the text length for generating snippet texts ✅ - Display synonyms instead of label when needed ✅ - highlight unknown industry terms ✅ - open configurator logo picker only once when replacing ✅ task-6325919
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#277185Issue: 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
17 changes
Resolved issues and error corrections
The WhatsApp identifiers module is now properly registered in the translation management configuration. This helps ensure translation files are picked up correctly, supporting consistent localization for users in different languages.
Original PR description
pot files must be registered there. See 9966b160972a053e051f2213846acc64d133f2a3 Forward-Port-Of: odoo/enterprise#124076 Forward-Port-Of: odoo/enterprise#124026
Bank reconciliation now shows the same supporting attachments in the list view as users already see in the kanban view. This avoids missing or inconsistent document visibility when reviewing and reconciling bank statement lines.
Original PR description
The aim of this commit is showing the same attachment in the bank reconciliation list view than in the kanban view. Before this commit, the field used to display the attachments was attachment_ids, this field were a related on the attachment_ids from account.move. This fix, removes the related to only keep a domain on the One2Many field. Thanks to the relational database, Odoo is giving us the right attachments when we want to display the field. task-6153002 Forward-Port-Of: odoo/enterprise#117245
Appraisals now use the template assigned to an employee's department instead of keeping a generic default. This helps HR teams apply the right review forms automatically while preserving appropriate manual choices.
Original PR description
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create…
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create an appraisal template and restrict it to a department. 2. Make sure at least one global (no department) template also exists. 3. Open a new appraisal and select an employee of that department. 4. Observe the appraisal template stays on the global one. **Current behavior:** The global template that was auto-selected before an employee was chosen is kept, ignoring the department-restricted template. **Expected behavior:** The template restricted to the employee's department is selected. **Cause of the issue:** On a new appraisal the template is computed before an employee (and therefore a department) is set, so a global template is pre-selected. When the employee is then chosen, `_compute_appraisal_template` reruns but the `appraisal.appraisal_template_id or ...` clause short-circuits on the already set global template and never falls through to the department's template. **Fix:** Evaluating the department's template before the existing value ensures a department-restricted template takes precedence over a template that was only auto-selected as a default. The existing value is still preserved when the department has no template of its own, so deliberate choices are untouched. opw-6293936 Forward-Port-Of: odoo/enterprise#121377
The point of sale barcode lookup flow now checks product creation permissions in a more consistent way. This helps ensure users only see or use product creation options when their access rights allow it, reducing inconsistent behavior at checkout.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#125096 Forward-Port-Of: odoo/enterprise#123073
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
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#270529Before 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
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing t
Original PR description
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ###…
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing technical name and message as the traceback when `stack` is absent. A focused regression test covers an `AbortError`-like object without `stack`. ### Tests - `git diff --check` - `node --check addons/web/static/src/core/errors/error_utils.js` - `node --check addons/web/static/tests/core/errors/error_service.test.js` - `@web/core/errors` HOOT suite: 24 tests, 107 assertions passed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr. Forward-Port-Of: odoo/odoo#276864
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
Original PR description
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
Selecting an online media-library illustration for a product image (or any field using the media dialog) saved the wrong image, or failed with "Please try to reupload this image" or a "raw is undefined" crash. Steps to reproduce ================== 1. Open a product and edit its image 2. In "Select a media", search a term (e.g. "new") 3. Click one of the online library illustrations => The wrong image is saved, or an error notification is shown Root cause ========== Library media r
Original PR description
Selecting an online media-library illustration for a product image (or any field using the media dialog) saved the wrong image, or failed with "Please try to reupload this image" or a "raw is…
Selecting an online media-library illustration for a product image (or any field using the media dialog) saved the wrong image, or failed with "Please try to reupload this image" or a "raw is undefined" crash. Steps to reproduce ================== 1. Open a product and edit its image 2. In "Select a media", search a term (e.g. "new") 3. Click one of the online library illustrations => The wrong image is saved, or an error notification is shown Root cause ========== Library media results carry a media-library id, not a local ir.attachment id. imageSave persists them as real attachments (save_library_media, run inside super.save) but then reads them back using the original media-library id. That id either collides with an unrelated local attachment, e.g. a type='url' demo record with no raw, hence the wrong image and the "reupload" warning or matches no record at all, so the read returns undefined and accessing .raw throws. Fix === Use the ids of the attachments actually created by the render step, carried on the rendered <img> elements (dataset.attachmentId), instead of the media-library ids. opw-6353273 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References:
Original PR description
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References: opw-6085893 [^1]: https://lxml.de/6.0/FAQ.html#is-lxml-vulnerable-to-xml-bombs Forward-Port-Of: odoo/odoo#275893 Forward-Port-Of: odoo/odoo#275367
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/o
Original PR description
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277347 Forward-Port-Of: odoo/odoo#273958
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#276356 Forward-Port-Of: odoo/odoo#273905
Original PR description
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#276356 Forward-Port-Of: odoo/odoo#273905
This PR adapts the code to call printEventBadge method in pos_event_iot to print the corresponding badge See https://github.com/odoo/enterprise/pull/123478 Forward-Port-Of: odoo/odoo#275021
Original PR description
This PR adapts the code to call printEventBadge method in pos_event_iot to print the corresponding badge See https://github.com/odoo/enterprise/pull/123478 Forward-Port-Of: odoo/odoo#275021
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when
Original PR description
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the event. This occurs because the record `event.registration` has no website_id field and the base url is taken from the company default website (website A) opw-4146760 opw-4336369 Forward-Port-Of: odoo/odoo#276984 Forward-Port-Of: odoo/odoo#274051
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
This reverts commit 787223c. In the point of sale, concurrent sales of the same product can happen, e.g. if several physical points of sales are open at the same time, each with their own session. In the case where the underlying product's valuation is tracked automatically and perpetually, the creation of the pos order leads to the creation of the stock picking, which in turn leads to a search for the next available svl. Because of the flush_all, this can cause lots of retry failures and ass
Original PR description
This reverts commit 787223c. In the point of sale, concurrent sales of the same product can happen, e.g. if several physical points of sales are open at the same time, each with their own session. In the case where the underlying product's valuation is tracked automatically and perpetually, the creation of the pos order leads to the creation of the stock picking, which in turn leads to a search for the next available svl. Because of the flush_all, this can cause lots of retry failures and associated delay/latency/overall perceived slowness for the end user. opw-6206709 Forward-Port-Of: odoo/odoo#275264
22 changes
Enhancements to existing features
The Nilvera client returns base64-encoded PDF content from the GET pdf endpoint. A previous change https://github.com/odoo-dev/odoo/commit/d2c2dc0bc33c369369ba748a513fad0c6edcaf6a incorrectly stored this base64 string directly into the `ir.attachment.raw` field without decoding. Because the field is binary, the base64 ASCII text was UTF-8 encoded on the disk, leaving the files unreadable in browsers. This commit introduces a migration script to fix this. For newly downloaded attachment
Original PR description
The Nilvera client returns base64-encoded PDF content from the GET pdf endpoint. A previous change https://github.com/odoo-dev/odoo/commit/d2c2dc0bc33c369369ba748a513fad0c6edcaf6a incorrectly stored this base64 string directly into the `ir.attachment.raw` field without decoding. Because the field is binary, the base64 ASCII text was UTF-8 encoded on the disk, leaving the files unreadable in browsers. This commit introduces a migration script to fix this. For newly downloaded attachments, 35fd6ce handles the decoding. task-6377121 Forward-Port-Of: odoo/odoo#275376
Resolved issues and error corrections
This update registers the WhatsApp Identifiers translation template so translation tools can process it correctly. It helps ensure labels and messages from this area can be translated consistently across languages.
Original PR description
pot files must be registered there. See 9966b160972a053e051f2213846acc64d133f2a3 Forward-Port-Of: odoo/enterprise#124076 Forward-Port-Of: odoo/enterprise#124026
The appointment link copy confirmation now appears only after the clipboard action is actually completed. This prevents automated appointment CRM checks from moving too early, making the feature more reliable across browsers and system load conditions.
Original PR description
Prior to this commit, the success notification for copying an appointment link to the clipboard was triggered synchronously, while the actual `navigator.clipboard.writeText` execution was deferred inside a `setTimeout`. This caused a race condition (depending on the browser's cpu load) during tours (e.g., `appointment_crm_meeting_tour`). The tour would proceed and restore the mocked clipboard object (`oldWriteText`) before the deferred `setTimeout` block had a chance to execute. This commit fixes the issue by moving the notification logic inside the `setTimeout` callback. The tour is also updated to wait explicitly for the success notification before cleaning up the clipboard mock and proceeding to discard the slots. runbot-241004
The point of sale barcode lookup flow now checks product creation permissions in a more reliable way. This helps ensure users only see or use product creation options when they have the right access, avoiding inconsistent behavior at checkout.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#125036 Forward-Port-Of: odoo/enterprise#123073
Bank reconciliation now shows the same supporting attachments in the list view as in the kanban view. This prevents users from missing documents when reviewing or matching bank transactions, making reconciliation more consistent.
Original PR description
The aim of this commit is showing the same attachment in the bank reconciliation list view than in the kanban view. Before this commit, the field used to display the attachments was attachment_ids, this field were a related on the attachment_ids from account.move. This fix, removes the related to only keep a domain on the One2Many field. Thanks to the relational database, Odoo is giving us the right attachments when we want to display the field. task-6153002 Forward-Port-Of: odoo/enterprise#117245
Sales commission achievement records with very large identifiers can now be opened without triggering a misleading “record does not exist” message. This ensures users can reliably access commission achievement details even when record numbers exceed browser number limits.
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#113701
This update removes an outdated customization that referenced a receipt section no longer present in Point of Sale. It helps keep Belgian certified POS receipts working correctly after the standard tax summary layout was restored.
Original PR description
In the community point_of_sale module, the `<t id="tax_base">` element was removed from the order receipt template in order to restore the 19.0 tax summary design (always displaying the tax base). Remove the xpath in pos_blackbox_be that was targeting this deleted element. task-id: 6296906 Forward-Port-Of: odoo/enterprise#120972
Appraisals now prioritize the template assigned to an employee's department instead of keeping a generic default. This helps HR teams use the right review form automatically while preserving valid manual template choices.
Original PR description
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create…
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create an appraisal template and restrict it to a department. 2. Make sure at least one global (no department) template also exists. 3. Open a new appraisal and select an employee of that department. 4. Observe the appraisal template stays on the global one. **Current behavior:** The global template that was auto-selected before an employee was chosen is kept, ignoring the department-restricted template. **Expected behavior:** The template restricted to the employee's department is selected. **Cause of the issue:** On a new appraisal the template is computed before an employee (and therefore a department) is set, so a global template is pre-selected. When the employee is then chosen, `_compute_appraisal_template` reruns but the `appraisal.appraisal_template_id or ...` clause short-circuits on the already set global template and never falls through to the department's template. **Fix:** Evaluating the department's template before the existing value ensures a department-restricted template takes precedence over a template that was only auto-selected as a default. The existing value is still preserved when the department has no template of its own, so deliberate choices are untouched. opw-6293936 Forward-Port-Of: odoo/enterprise#121377
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
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://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
Purpose: For credit time Employees, similar configurations of calendar lead to different duration counts Cause: leave duration is dependant on average hours per day of the calendar (which changes with configuration as credit time is considered as absense) to decide if the duration is half or full day - added a context flag `compute_leave_duration` to be accessed in `_work_intervals_batch` so we consider credit time intervals for leave duration computation - extracted some logic from `_get
Original PR description
Purpose: For credit time Employees, similar configurations of calendar lead to different duration counts Cause: leave duration is dependant on average hours per day of the calendar (which changes with configuration as credit time is considered as absense) to decide if the duration is half or full day - added a context flag `compute_leave_duration` to be accessed in `_work_intervals_batch` so we consider credit time intervals for leave duration computation - extracted some logic from `_get_durations`to `_get_worked_days_and_hours` to be overriden in be localization for credit time attendances task-id: 6212942 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/o
Original PR description
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277347 Forward-Port-Of: odoo/odoo#273958
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing t
Original PR description
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ###…
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing technical name and message as the traceback when `stack` is absent. A focused regression test covers an `AbortError`-like object without `stack`. ### Tests - `git diff --check` - `node --check addons/web/static/src/core/errors/error_utils.js` - `node --check addons/web/static/tests/core/errors/error_service.test.js` - `@web/core/errors` HOOT suite: 24 tests, 107 assertions passed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr. Forward-Port-Of: odoo/odoo#276864
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
Original PR description
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References:
Original PR description
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References: opw-6085893 [^1]: https://lxml.de/6.0/FAQ.html#is-lxml-vulnerable-to-xml-bombs Forward-Port-Of: odoo/odoo#275893 Forward-Port-Of: odoo/odoo#275367
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#276356 Forward-Port-Of: odoo/odoo#273905
Original PR description
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#276356 Forward-Port-Of: odoo/odoo#273905
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynch
Original PR description
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynchronous permission check with a getter that evaluates product creation rights. - Cache the group access information in `posService` and let the hr override use the getter. Task-6361787 Related PR: https://github.com/odoo/enterprise/pull/123073 Forward-Port-Of: odoo/odoo#277578 Forward-Port-Of: odoo/odoo#274420
Steps to reproduce: 1. Drop the Website Form snippet. 2. Add a checkbox field. 3. Change the label position to Top. > The Default Value option disappears. Cause: The `applyTo` selector relied on the `.col-sm` wrapper, which is only present for left/right label positions. As a result, it did not match checkbox fields with Top or None labels. This commit fix the applyTo selector so the Default Value option is displayed for checkbox fields regardless of the selected label position.
Original PR description
Steps to reproduce: 1. Drop the Website Form snippet. 2. Add a checkbox field. 3. Change the label position to Top. > The Default Value option disappears. Cause: The `applyTo` selector relied on the `.col-sm` wrapper, which is only present for left/right label positions. As a result, it did not match checkbox fields with Top or None labels. This commit fix the applyTo selector so the Default Value option is displayed for checkbox fields regardless of the selected label position. task-6373796 Forward-Port-Of: odoo/odoo#277380 Forward-Port-Of: odoo/odoo#275823
v19 WIoT Boxes will be listening on localhost when updating to v19.1+, we need to ensure they use `http_interface = 0.0.0.0` after the update. Forward-Port-Of: odoo/odoo#272063
Original PR description
v19 WIoT Boxes will be listening on localhost when updating to v19.1+, we need to ensure they use `http_interface = 0.0.0.0` after the update. Forward-Port-Of: odoo/odoo#272063
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are expressed per reference unit. The same checks on sale orders already use the quantity in the reference unit. Steps to reproduce: - create a delivery method with a maximum weight of 10 kg - create a product in Units weighing 1 kg with Dozens in its allowed units - create a delivery transfer of 2
Original PR description
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are…
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are expressed per reference unit. The same checks on sale orders already use the quantity in the reference unit. Steps to reproduce: - create a delivery method with a maximum weight of 10 kg - create a product in Units weighing 1 kg with Dozens in its allowed units - create a delivery transfer of 2 Dozen of the product and select the carrier on the transfer The 24 kg shipment is weighed as 2 kg, so the carrier is proposed on the transfer although it exceeds its maximum weight, and it is correctly refused on a sale order for the same quantity. With a unit smaller than the reference one, valid carriers are hidden instead. Solution: Use the quantity in the reference unit of the product, as done for sale orders and everywhere else the shipment weight is computed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277425
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when
Original PR description
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the event. This occurs because the record `event.registration` has no website_id field and the base url is taken from the company default website (website A) opw-4146760 opw-4336369 Forward-Port-Of: odoo/odoo#276984 Forward-Port-Of: odoo/odoo#274051
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
10 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
Resolved issues and error corrections
The WhatsApp identifiers component is now properly registered for translation updates. This helps ensure its text can be translated and maintained consistently 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
Point of Sale now works more reliably with newer IoT Boxes that no longer provide certain device details. The update prevents searches from relying on missing information, helping printers and payment terminals remain easier to configure and detect.
Original PR description
Newer IoT Boxes don't share device subtype or manufacturer. We then adapt the domains to avoid searching on fields that aren't filled. task-6388669 task-6388733 Forward-Port-Of: odoo/enterprise#124487 Forward-Port-Of: odoo/enterprise#124306
The update fixes where the express filing note is placed in French VAT report submissions sent to AspOne. This helps ensure the generated filing format is accepted by the receiving service and avoids preventable submission issues.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745 Forward-Port-Of: odoo/enterprise#123235
The Profit and Loss report now continues to open even if a configurable summary line, such as Gross Profit, has been removed. This prevents an error from blocking users who customize accounting reports.
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
The timesheet progress percentage now updates immediately when timesheets are added, changed, or removed. This keeps project and service tracking accurate on screen without requiring users to refresh the page.
Original PR description
Issue: The percentage is only updated after reloading the page. Cause: The percentage computation is performed inside `loadTimesheets`, which is only called when the timesheets are loaded. Fix: Move the percentage computation into a helper function and invoke it whenever a timesheet is added, updated, or removed. task-6401186
A failing AI test was corrected by ensuring test data does not accidentally include unrelated demo sources that use a different embedding provider. This helps keep automated validation reliable without changing user-facing behavior.
Original PR description
_cron_generate_embedding retrieves all the sources that don't have an embedding and generate embeddings for those using the model from the provider of the agent configured on the source. The agent configured on the demo sources has OpenAI as the provider and these sources don't have embeddings. When _cron_generate_embedding runs in the test case, it retrieves these demo sources + the source defined in the test case (Which relies on embeddings from Google) and generates the embeddings but then fails. This happens because the _request method is mocked to return the response in Google's format as the test case is specific to Gemini models. runbot.build.error-944173 Forward-Port-Of: odoo/enterprise#124977
Backport of : https://github.com/odoo/odoo/pull/269057 to V18 When an international customer selects an in-store pickup location, the order's fiscal position changes to the fiscal position matching the pickup warehouse. However, the order-line taxes and checkout summary are not recomputed immediately. **Steps to reproduce:** 1. Configure a French company and website. 2. Configure a product priced at 100 ( just an example , any price will do ) EUR excluding 20% French VAT. 3. Con
Original PR description
Backport of : https://github.com/odoo/odoo/pull/269057 to V18 When an international customer selects an in-store pickup location, the order's fiscal position changes to the fiscal position matching…
Backport of : https://github.com/odoo/odoo/pull/269057 to V18 When an international customer selects an in-store pickup location, the order's fiscal position changes to the fiscal position matching the pickup warehouse. However, the order-line taxes and checkout summary are not recomputed immediately. **Steps to reproduce:** 1. Configure a French company and website. 2. Configure a product priced at 100 ( just an example , any price will do ) EUR excluding 20% French VAT. 3. Configure an export fiscal position removing VAT for Japan. 4. Configure an international delivery method. 5. Configure an in-store pickup method with a warehouse located in France. 6. Checkout using a Japanese delivery address. 7. Select the international delivery method. 8. Switch to pickup in store. **Current behavior:** - The order fiscal position changes to the French fiscal position. - Product-line taxes and the checkout summary remain based on the export fiscal position. - French VAT only appears later on the payment step. - Switching back to international delivery can similarly leave stale totals. **Expected behavior:** - Selecting the French pickup location immediately applies French VAT. - Switching back to international delivery immediately removes French VAT. - Totals displayed during delivery selection match the payment-step totals. **Cause:** The Click & Collect flow explicitly recomputes `fiscal_position_id` when selecting or leaving an in-store pickup location, but it does not recompute the order-line taxes and prices. Additionally, the pickup-location route does not return updated order-summary values, so the checkout page cannot refresh its displayed totals. **Solution:** - Recompute taxes and prices when the in-store fiscal position changes. - Restrict the recomputation to draft website orders. - Return the updated order summary after selecting a pickup location. - Refresh the checkout summary using the returned values. **Tests cover:** - Japanese delivery with export fiscal position and no VAT. - Switching to a French pickup location immediately applying 20% VAT. - Switching back to international delivery removing VAT. - Delivery-step totals matching payment-step recomputation. - Pickup-location route returning updated summary values. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276201 Forward-Port-Of: odoo/odoo#269086
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/o
Original PR description
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277347 Forward-Port-Of: odoo/odoo#273958
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
1 change
Resolved issues and error corrections
The WhatsApp identifiers module is now properly registered for translation file handling. This helps ensure its text can be included in the standard translation workflow, reducing the risk of missing translated labels 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
2 changes
Enhancements to existing features
Before this commit, when an authentication process was ongoing it was not very clear to the user This commit adds a banner to warn the user to not cancel the ongoing process or it will be aborted. task-6372665 Forward-Port-Of: odoo/odoo#275230
Original PR description
Before this commit, when an authentication process was ongoing it was not very clear to the user This commit adds a banner to warn the user to not cancel the ongoing process or it will be aborted. task-6372665 Forward-Port-Of: odoo/odoo#275230
Resolved issues and error corrections
The WhatsApp Identifiers app is now correctly included in the translation registration settings. This helps ensure its text can be translated consistently for users in different languages.
Original PR description
pot files must be registered there. See 9966b160972a053e051f2213846acc64d133f2a3 Forward-Port-Of: odoo/enterprise#124076 Forward-Port-Of: odoo/enterprise#124026
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
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
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.
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
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
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
12 changes
Enhancements to existing features
When the customer is located in Canary Islands, Ceuta or Melilla, the invoice falls under a different tax territory and the ClaveRegimenEspecialOTrascendencia should be 08. Previously this case was not checked and invoices were reported with the generic refime code. task-6372837 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
When the customer is located in Canary Islands, Ceuta or Melilla, the invoice falls under a different tax territory and the ClaveRegimenEspecialOTrascendencia should be 08. Previously this case was not checked and invoices were reported with the generic refime code. task-6372837 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This fixes an issue where accounting reports could fail to recognize that no report section had been opened yet. The change helps the report interface behave correctly when deciding whether saved section state is empty.
Original PR description
**Root Cause:**
At [1], the condition `this.lastOpenedSectionByReport === {}` always
return `false` because JavaScript compares objects by reference
rather than by value. As a result, the code never detects when
`lastOpenedSectionByReport` is empty.
**Fix:**
This commit ensures the code correctly detects an empty
`lastOpenedSectionByReport` object.
[1]:
https://github.com/odoo/enterprise/blob/ae4b461edb1d6b49c25d4e264380e7ae4b67f10c/account_reports/static/src/components/account_report/controller.js#L50
**No task ID**This fix makes the automated barcode picking test wait until the transfer is actually valid before trying to validate it. It reduces random test failures, helping keep inventory-related releases and updates more dependable.
Original PR description
Make sure the validate button has the 'primary-btn' class as it means that the transfer is valid before clicking on it. runbot-939917
Fixes a navigation issue where opening Helpdesk tickets from an email alias could cause an error instead of showing the ticket list. The change helps users reach the expected Helpdesk view reliably, especially when using alias-related shortcuts in debug workflows.
Original PR description
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe…
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe error ### Description of the issue/feature this PR addresses: **Issue:** When navigating from an email alias to its parent document (e.g., a Helpdesk Team), the web client keeps the `active_id` and `active_model` of the alias in the context. The "Tickets" smart button action maps this incorrect `active_id` to `default_team_id`. **Solution:** Update `get_empty_list_help` in `helpdesk.ticket` to validate the context. We can check if the `active_model` is actually `helpdesk.team`. If it's not, we can safely ignore the invalid `default_team_id`. ### Current behavior before PR: The system blindly trusts the polluted `default_team_id` and attempts to look up a Helpdesk Team using the Alias's ID to generate the empty list help message. Because a team with that ID does not exist, it throws a MissingError. ### Desired behavior after PR: The system should be able to detect when there is incorrect context and clear the invalid ID before attempting the database lookup. Therefore, the empty tickets view will load correctly without crashing. opw-6395638
**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
**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
Note: In odoo all date/datetime fields are stored and computed by default as UTC Before this commit, dates were called using local timezone getters. This caused the time returned from web to be shifted by the timezone as the dates returned would be treated as UTC. After this commit, dates are now called using UTC timzone getters. Now all web times are retrived as UTC and in sync with the rest of the odoo fields and computations. task-6271421 Forward-Port-Of: odoo/odoo#265250
Original PR description
Note: In odoo all date/datetime fields are stored and computed by default as UTC Before this commit, dates were called using local timezone getters. This caused the time returned from web to be shifted by the timezone as the dates returned would be treated as UTC. After this commit, dates are now called using UTC timzone getters. Now all web times are retrived as UTC and in sync with the rest of the odoo fields and computations. task-6271421 Forward-Port-Of: odoo/odoo#265250
**Steps to produce:** - Install the `sale_stock` and `sale_management` modules. - Create a product with the Invoicing Policy set to `Delivered quantities`. - Create a Sales Order for 5 units of the product, confirm it, and validate the delivery. - Create and post the customer invoice for the 5 units (SO status is now Fully Invoiced). - Return 3 units from the validated delivery, click on the `Return for Exchange` option, and validate the transfer. - Observe the Sales Order's invoice status
Original PR description
**Steps to produce:** - Install the `sale_stock` and `sale_management` modules. - Create a product with the Invoicing Policy set to `Delivered quantities`. - Create a Sales Order for 5 units of the…
**Steps to produce:** - Install the `sale_stock` and `sale_management` modules. - Create a product with the Invoicing Policy set to `Delivered quantities`. - Create a Sales Order for 5 units of the product, confirm it, and validate the delivery. - Create and post the customer invoice for the 5 units (SO status is now Fully Invoiced). - Return 3 units from the validated delivery, click on the `Return for Exchange` option, and validate the transfer. - Observe the Sales Order's invoice status from the list view. **Issue:** - The Sales Order status erroneously switches to `To Invoice` instead of remaining `Fully Invoiced`. **Root cause:** - When a return picking is validated with return exchange, the `qty_delivered` on the `sale.order.line` drops immediately. This causes `qty_to_invoice` (`qty_delivered - qty_invoiced`) to become negative from [1]. - And then from [2], the invoice status is set as `To invoice`. **Solution:** - Adjust the existing `_compute_invoice_status` override in `sale_stock` to account for pending replacement moves generated during exchange returns. If the replacement quantity offsets the negative `qty_to_invoice`, keep the order `Fully Invoiced` instead of marking it `To Invoice`. [1]https://github.com/odoo/odoo/blob/b0fc5668990c42f129432dd7eeeb24a042d4b153/addons/sale/models/sale_order_line.py#L1006 [2]https://github.com/odoo/odoo/blob/b0fc5668990c42f129432dd7eeeb24a042d4b153/addons/sale/models/sale_order_line.py#L1041 **opw-6299909** --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Before this commit, the journal and the memo of a payment linked to a company-paid expense report could be modified although such payments must be kept consistent with their expense report: a missing comma in the set of protected fields merged 'journal_id' and 'ref' into a single meaningless entry. The memo was also left editable because the set still referred to 'ref', which was renamed to 'memo'. Steps to reproduce: - submit, approve and post an expense paid by company - open the payment
Original PR description
Before this commit, the journal and the memo of a payment linked to a company-paid expense report could be modified although such payments must be kept consistent with their expense report: a missing comma in the set of protected fields merged 'journal_id' and 'ref' into a single meaningless entry. The memo was also left editable because the set still referred to 'ref', which was renamed to 'memo'. Steps to reproduce: - submit, approve and post an expense paid by company - open the payment created for the expense report - edit the memo or the journal and save, then try to edit the date Editing the date is refused with "You cannot do this modification since the payment is linked to an expense report", while the memo and journal changes are silently accepted. Solution: Restore the missing comma and protect the renamed memo field. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Clicking the translate button saves the form's root record before opening the translation dialog, since https://github.com/odoo/odoo/commit/9da52919a03dbcee5209430918195158c0652099. A record opened in an x2many form dialog keeps its changes for itself until the dialog is saved, see https://github.com/odoo/odoo/blob/242f6d3cf7288853f163ac6986a3b7aa4279efaf/addons/web/static/src/model/relational_model/static_list.js#L193. Its pending changes are not part of the root record changes, so saving the
Original PR description
Clicking the translate button saves the form's root record before opening the translation dialog, since https://github.com/odoo/odoo/commit/9da52919a03dbcee5209430918195158c0652099. A record opened…
Clicking the translate button saves the form's root record before opening the translation dialog, since https://github.com/odoo/odoo/commit/9da52919a03dbcee5209430918195158c0652099. A record opened in an x2many form dialog keeps its changes for itself until the dialog is saved, see https://github.com/odoo/odoo/blob/242f6d3cf7288853f163ac6986a3b7aa4279efaf/addons/web/static/src/model/relational_model/static_list.js#L193. Its pending changes are not part of the root record changes, so saving the root sends nothing to the server, and the translation dialog then shows the stored terms instead of the current content, or no terms at all when the stored value is empty. The fix changes openTranslationDialog in translation_button.js, the place that decides which record to save. When the record keeps its changes for itself (record._noUpdateParent), the record is saved directly, like the button did before the commit above. The root record is still saved in the other cases, so the editable list case that commit fixed keeps working. Steps to reproduce: 1. Activate a second language in Settings > Translations > Languages 2. Open the Surveys app, open a survey and click a question in the Questions tab 3. In the Description tab, change the description 4. Click the EN button on the description field => the translation dialog shows the terms of the previous description, not the current one Ticket [link](https://www.odoo.com/odoo/project.task/6237291) opw-6237291
## Steps to Reproduce: _(cryptography version > 43.0.0)_ 1. Install the `l10n_sa_edi` module. 2. Switch to SA Company. 3. Set the company name to an Arabic string between 32 and 64 characters. (e.g; `مجموعة النخبة العالمية للاستشارات الفنية`) 5. Accounting > Configuration > Journals. 6. Open a Sales type journal. 7. Click "Re-onboard" in the ZATCA tab. 8. Enter an OTP and click "Request". ## Error: `ValueError: Attribute's length must be >= 1 and <= 64, but it was 98` ## Caus
Original PR description
## Steps to Reproduce: _(cryptography version > 43.0.0)_ 1. Install the `l10n_sa_edi` module. 2. Switch to SA Company. 3. Set the company name to an Arabic string between 32 and 64 characters. (e.g;…
## Steps to Reproduce: _(cryptography version > 43.0.0)_
1. Install the `l10n_sa_edi` module.
2. Switch to SA Company.
3. Set the company name to an Arabic string between 32 and 64 characters.
(e.g; `مجموعة النخبة العالمية للاستشارات الفنية`)
5. Accounting > Configuration > Journals.
6. Open a Sales type journal.
7. Click "Re-onboard" in the ZATCA tab.
8. Enter an OTP and click "Request".
## Error:
`ValueError: Attribute's length must be >= 1 and <= 64, but it was 98`
## Cause:
The CSR validation checks the length of characters, if combined common_name (or other fields) are less than 64 characters, it passes the condition. - [1] But the cryptography library validates UTF-8 byte length for string values. Arabic characters take 2 bytes in UTF-8, causing the byte length to exceed the 64-byte limit enforced by the cryptography.
**Note:**
Starting with cryptography version 43.0.0, the library enforces the UTF-8 byte length limit for CSR string values during certificate creation. (Ref: https://github.com/pyca/cryptography/pull/11201)
## Fix:
Validate the UTF-8 encoded byte length instead of the character length.
[1] - https://github.com/odoo/odoo/blob/a66fedcaf555660e484a2becc49a9b7e602f5924/addons/l10n_sa_edi/models/certificate.py#L92
sentry-7608376856Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired Connection
Original PR description
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired ConnectionToken. Move reader discovery to `connectReader()` so Odoo connects using fresh discovery results, and stop discovering readers eagerly when creating the Stripe Terminal instance. opw-6311626 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move unit and the line unit converted a value to its own unit, hence did nothing. Steps to reproduce: - create a product in Units with available stock - create a delivery for 2 Dozen of it and mark it as todo - in the detailed operations, change the unit of the move line to Units (24) - lower the
Original PR description
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move…
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move unit and the line unit converted a value to its own unit, hence did nothing. Steps to reproduce: - create a product in Units with available stock - create a delivery for 2 Dozen of it and mark it as todo - in the detailed operations, change the unit of the move line to Units (24) - lower the move quantity from 2 to 1 Dozen The move line ends up with 23 Units instead of 12: the decrease of 1 Dozen is applied as 1 Unit on the line and considered fully processed. The remaining 11 units stay reserved and counted on the transfer. Convert the remaining decrease from the move unit to the line unit when taking it from a line, and the taken quantity back to the move unit when updating the remaining decrease. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276774
6 changes
Resolved issues and error corrections
The Spanish Mod 347 tax report now avoids counting real estate partners twice. This improves the accuracy of reported totals when real estate transactions are included.
Original PR description
The domain used for the Total number of persons and entities is using != None. However, another invoice type is added in l10n_es_real_estates which is already accompted for in another line. This means the partner could have been added twice (once in the real_estate invoice type and once in the all type). To reproduce: - Install l10n_es_real_estates - Create an invoice with l10n_es_reports_mod347_invoice_type set to real estate - Go to the Tax report: mod 347 - The partner would appear under the all operation and real estate.
There 2 problems fixed here: - First we can always attach at least once document by clicking on the paperclip icon or using the dropzone - It's not possible to add more attachment when we have read permission even if `_mail_post_access` is set to `read` Step to reproduce: - Have a model with `_mail_post_access` set to `read` - Have a user with read only access to the record - The user can upload a document by clicking on the paper-clip but the Attach files button is grayed out so he cant
Original PR description
There 2 problems fixed here: - First we can always attach at least once document by clicking on the paperclip icon or using the dropzone - It's not possible to add more attachment when we have read permission even if `_mail_post_access` is set to `read` Step to reproduce: - Have a model with `_mail_post_access` set to `read` - Have a user with read only access to the record - The user can upload a document by clicking on the paper-clip but the Attach files button is grayed out so he cant afterward - If `_mail_post_access` is set to `write` - The user can still upload a document with the paper-clip even through he only has read access We are also fixing the deletion of attachments, where it wasn't possible for someone with read access on a record where the model `_mail_post_access` is set to "read" to delete his own attachments. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Issue: --- Adding a rating with a message on website is causing TB as the portal user doesn't have the access to send rating message. opw-6316142 Forward-Port-Of: odoo/odoo#271833
Original PR description
Issue: --- Adding a rating with a message on website is causing TB as the portal user doesn't have the access to send rating message. opw-6316142 Forward-Port-Of: odoo/odoo#271833
The character-by-character HTML assertion in mass mailing tests fails on modern platforms using libxml2 >= 2.14/2.15 due to upstream updates that align HTML serialization, attribute quote management, and escaping rules more closely with the HTML5 specification. See upstream changes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.14.0 (Attribute escaping optimization) - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.15.0 (HTML5 spec compliant serialization) This commit fixes
Original PR description
The character-by-character HTML assertion in mass mailing tests fails on modern platforms using libxml2 >= 2.14/2.15 due to upstream updates that align HTML serialization, attribute quote management, and escaping rules more closely with the HTML5 specification. See upstream changes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.14.0 (Attribute escaping optimization) - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.15.0 (HTML5 spec compliant serialization) This commit fixes this by refactoring the assertions to treat the output HTML structure as a "black box", verifying data integrity and expected content conversions rather than brittle structural layout. runbot-938228
The amount in words split the total with int(decimal * 100), which truncates. 3989.33 is held in binary as 3989.3299..., so the kuruş/cents came out one short (32 instead of 33). The written amount then disagreed with the numeric total on the same invoice and Nilvera rejects it. Round to the currency precision and round the subunit instead. Task-6383690 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: ---
Original PR description
The amount in words split the total with int(decimal * 100), which truncates. 3989.33 is held in binary as 3989.3299..., so the kuruş/cents came out one short (32 instead of 33). The written amount then disagreed with the numeric total on the same invoice and Nilvera rejects it. Round to the currency precision and round the subunit instead. Task-6383690 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
### Issue before the commit: During the import of Italian e-invoices, Pension Fund taxes (Cassa Previdenziale) linked to a 0% VAT rate with a specific exemption reason (Natura, e.g., N2.2) are ignored and not applied to the invoice lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to vendor -> bills and import the bill in the ticket 3. Check that taxes are not imported as expected ### Cause of the issue: The system incorrectly used the Natura to search
Original PR description
### Issue before the commit: During the import of Italian e-invoices, Pension Fund taxes (Cassa Previdenziale) linked to a 0% VAT rate with a specific exemption reason (Natura, e.g., N2.2) are ignored and not applied to the invoice lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to vendor -> bills and import the bill in the ticket 3. Check that taxes are not imported as expected ### Cause of the issue: The system incorrectly used the Natura to search for the Pension Fund tax itself. Fiscally, the Natura belongs to the related VAT, not the Pension Fund. This incorrect domain caused the tax search to fail. The Pension Fund tax should not have a Natura setted. ### Reason to introduce the fix: To correctly apply Pension Fund taxes to exempt invoice lines. Ticket [link](https://www.odoo.com/odoo/project.task/6357133) opw-6357133