Daily updates from Odoo
Sunday, July 19, 2026
21 changes
1 change
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
3 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
`_send_void_request` voided the transaction using `self.provider_reference`, but voiding creates a new child transaction to carry out the request, and that child never has its own provider reference set. Authorize.Net was therefore called with an empty `refTransId` and rejected the request with "A valid referenced transaction ID is required", making the "Void Transaction" button unusable from the invoice, payment, and sale order. Use `self.source_transaction_id.provider_reference` instead, ma
Original PR description
`_send_void_request` voided the transaction using `self.provider_reference`, but voiding creates a new child transaction to carry out the request, and that child never has its own provider reference set. Authorize.Net was therefore called with an empty `refTransId` and rejected the request with "A valid referenced transaction ID is required", making the "Void Transaction" button unusable from the invoice, payment, and sale order. Use `self.source_transaction_id.provider_reference` instead, matching the pattern already used by `_send_capture_request` and `_send_refund_request`. opw-6311779 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277182
Steps to reproduce: ------------------- - Install `mrp` and `sale_management` modules - Enable Units of Measure from settings - Create a storable product configured as a Kit: - Set UoM to Units - Add component and it's UoM in Kg in Product form. - Create and confirm a Sales Order with the kit product - Validate the generated delivery order - Print the delivery slip Issue: ------ The delivery slip correctly displays component quantities in Kg, but also shows an additional conve
Original PR description
Steps to reproduce: ------------------- - Install `mrp` and `sale_management` modules - Enable Units of Measure from settings - Create a storable product configured as a Kit: - Set UoM to Units - Add…
Steps to reproduce:
-------------------
- Install `mrp` and `sale_management` modules
- Enable Units of Measure from settings
- Create a storable product configured as a Kit:
- Set UoM to Units
- Add component and it's UoM in Kg in Product form.
- Create and confirm a Sales Order with the kit product
- Validate the generated delivery order
- Print the delivery slip
Issue:
------
The delivery slip correctly displays component quantities in Kg,
but also shows an additional converted quantity in Units (e.g., 1000 Units),
which is incorrect and misleading.
Cause:
------
During sale order confirmation, the following flow is executed:
`action_confirm → _action_confirm → _action_launch_stock_rule → _prepare_procurement_values`
In `_prepare_procurement_values`, the `packaging_uom_id` is set from the
sale order line UoM (Units) and propagated to the generated stock move:
https://github.com/odoo/odoo/blob/647febbf46160c000bf11af8325cc80d0916eb67/addons/sale_stock/models/sale_order_line.py#L296
When the delivery (picking) is created, kit components generate stock moves where:
- `product_uom` is defined in the component’s UoM (e.g., Kg)
- `packaging_uom_id` remains in Units (inherited from the sale order line)
While generating the delivery slip, `_get_aggregated_product_quantities`
computes `packaging_quantity` using `packaging_uom_id`:
https://github.com/odoo/odoo/blob/647febbf46160c000bf11af8325cc80d0916eb67/addons/stock/models/stock_move_line.py#L888
In Mrp this calls the template:
`stock_report_delivery_aggregated_move_lines`
https://github.com/odoo/odoo/blob/647febbf46160c000bf11af8325cc80d0916eb67/addons/mrp/report/report_deliveryslip.xml#L60
In this template, a condition renders packaging quantities when
`packaging_uom_id` differs from `product_uom`. As a result, quantities are
converted from the component UoM (Kg) into the packaging UoM (Units).
https://github.com/odoo/odoo/blob/647febbf46160c000bf11af8325cc80d0916eb67/addons/stock/report/report_deliveryslip.xml#L261
For kit components, this conversion is not meaningful and leads to incorrect
values (e.g., Kg → Units resulting in 1000 Units), causing misleading output
in the delivery slip.
Fix:
----
Add a `_compute_packaging_uom_id` override in `sale_mrp` and
`purchase_mrp` that resets `packaging_uom_id` back to
the component's own `product_uom` whenever the move originates from a
phantom BoM line, without touching `sale_line_id`/`purchase_line_id`
themselves.
<details>
<summary>Click here to see the results:</summary>
<p><strong>Before:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/5d8b2154-d794-4ce4-90a6-1a0aeaca8604" />
</div>
<p><strong>After:</strong></p>
<div class="image-row">
<img src="https://github.com/user-attachments/assets/79d708de-19e3-452d-9033-322a297c38e9" />
</div>
</details>
---
opw-6136928
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#277015
Forward-Port-Of: odoo/odoo#2627054 changes
Resolved issues and error corrections
Steps to produce: --- - Install the `Sales` module. - Go to Invoicing > Configuration > Accounting > Taxes. - Open the 0% Exports tax and set a value in the `Label on Invoices.` Field under the Advanced Options tab. - Create a sale order with multiple sections, apply the 0% Exports tax to the order lines, and enable `Hide Composition` on one of the sections. - Preview the sale order. Issue: --- - The tax displayed in a collapsed section summary differs from the tax shown on regular or
Original PR description
Steps to produce: --- - Install the `Sales` module. - Go to Invoicing > Configuration > Accounting > Taxes. - Open the 0% Exports tax and set a value in the `Label on Invoices.` Field under the…
Steps to produce: --- - Install the `Sales` module. - Go to Invoicing > Configuration > Accounting > Taxes. - Open the 0% Exports tax and set a value in the `Label on Invoices.` Field under the Advanced Options tab. - Create a sale order with multiple sections, apply the 0% Exports tax to the order lines, and enable `Hide Composition` on one of the sections. - Preview the sale order. Issue: --- - The tax displayed in a collapsed section summary differs from the tax shown on regular order lines for the same tax. Root cause: --- - At [1], `_get_grouped_section_summary()` only returns `tax_labels`, which are then used when rendering the collapsed section summary. As a result, the invoice label is displayed instead of the actual tax name. Solution: --- - Add `tax_names` to the values returned by `_get_grouped_section_summary()` and use them when rendering the collapsed section summary, ensuring consistent tax information across the preview. - Also removed the unnecessary fallback in the return statement, as `res` is always populated. [1]https://github.com/odoo/odoo/blob/be0bf1365e054521ece224f5e3a4b7cbce402315/addons/sale/models/sale_order_line.py#L1572-L1604 Before: --- <img width="1068" height="156" alt="image" src="https://github.com/user-attachments/assets/8030c35e-5c73-4fed-9feb-c4729add7894" /> After: --- <img width="1057" height="143" alt="image" src="https://github.com/user-attachments/assets/336030ed-68b2-4d14-b26f-ff391257d6d4" /> opw-6294141 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270544
Steps to reproduce: - Open tasks from any project or open a task form, go to the Blocked By tab, and click Add a line to open the task selection view. - Apply the `Templates` filter - Observe that non-template tasks and tasks from template projects are also shown. Cause: - The domain condition checks for `default_project_id` and falls back to `Domain.TRUE`, allowing non-template tasks and tasks from template projects to bypass template-specific filtering. Fix: - Remove the `default_p
Original PR description
Steps to reproduce: - Open tasks from any project or open a task form, go to the Blocked By tab, and click Add a line to open the task selection view. - Apply the `Templates` filter - Observe that non-template tasks and tasks from template projects are also shown. Cause: - The domain condition checks for `default_project_id` and falls back to `Domain.TRUE`, allowing non-template tasks and tasks from template projects to bypass template-specific filtering. Fix: - Remove the `default_project_id` condition and enforce only `has_template_ancestor = True` in the domain, ensuring that only actual template tasks are shown. task-5966601 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260624
`_send_void_request` voided the transaction using `self.provider_reference`, but voiding creates a new child transaction to carry out the request, and that child never has its own provider reference set. Authorize.Net was therefore called with an empty `refTransId` and rejected the request with "A valid referenced transaction ID is required", making the "Void Transaction" button unusable from the invoice, payment, and sale order. Use `self.source_transaction_id.provider_reference` instead, ma
Original PR description
`_send_void_request` voided the transaction using `self.provider_reference`, but voiding creates a new child transaction to carry out the request, and that child never has its own provider reference set. Authorize.Net was therefore called with an empty `refTransId` and rejected the request with "A valid referenced transaction ID is required", making the "Void Transaction" button unusable from the invoice, payment, and sale order. Use `self.source_transaction_id.provider_reference` instead, matching the pattern already used by `_send_capture_request` and `_send_refund_request`. opw-6311779 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277182
Miscellaneous changes
When an incoming move of an AVCO product is validated with outgoing moves in the same batch, `_set_value()` falls back to a full standard price recomputation through `_run_average_batch(force_recompute=True)`, which searches every valued move of the products since the beginning of the history (or since their last manual valuation). In that method, the line dropship_moves = moves.filtered(lambda m: m.is_dropship) reads `is_dropship` on the whole recordset. Each read prefetches *all*
Original PR description
When an incoming move of an AVCO product is validated with outgoing moves in the same batch, `_set_value()` falls back to a full standard price recomputation through `_run_average_batch(force_recompute=True)`, which searches every valued move of the products since the beginning of the history (or since their last manual valuation).
In that method, the line
dropship_moves = moves.filtered(lambda m: m.is_dropship)
reads `is_dropship` on the whole recordset. Each read prefetches *all* stored fields of `stock.move` for the records, and nothing invalidates the cache between batches. With a large history, this materializes the entire stock.move table slice in memory before ever reaching the carefully batched loop below ("PERF avoid memoryerror").
opw-6393223
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#2768841 change
Miscellaneous changes
When an incoming move of an AVCO product is validated with outgoing moves in the same batch, `_set_value()` falls back to a full standard price recomputation through `_run_average_batch(force_recompute=True)`, which searches every valued move of the products since the beginning of the history (or since their last manual valuation). In that method, the line dropship_moves = moves.filtered(lambda m: m.is_dropship) reads `is_dropship` on the whole recordset. Each read prefetches *all*
Original PR description
When an incoming move of an AVCO product is validated with outgoing moves in the same batch, `_set_value()` falls back to a full standard price recomputation through `_run_average_batch(force_recompute=True)`, which searches every valued move of the products since the beginning of the history (or since their last manual valuation).
In that method, the line
dropship_moves = moves.filtered(lambda m: m.is_dropship)
reads `is_dropship` on the whole recordset. Each read prefetches *all* stored fields of `stock.move` for the records, and nothing invalidates the cache between batches. With a large history, this materializes the entire stock.move table slice in memory before ever reaching the carefully batched loop below ("PERF avoid memoryerror").
opw-6393223
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#2768841 change
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
11 changes
Resolved issues and error corrections
Belgian payroll salary simulations now ignore earlier payslips from the same month when calculating amounts such as the employment bonus. This prevents past payroll data from skewing simulated results, giving HR teams a clearer estimate before running payroll.
Original PR description
Some computations such as the employment bonus rely on the previous payslips of the month. In case of salary simulation, we shouldn't take these into account to have an accurate result. task-6385091 Forward-Port-Of: odoo/enterprise#124314 Forward-Port-Of: odoo/enterprise#124081
This fixes an issue in the Sign app where signing requests could fail in debug mode when extra page comments were present. Users and testers should experience a more reliable signing flow without unexpected errors.
Original PR description
Use lastElementChild when retrieving the sign item from the target element. In debug mode, inherited templates may introduce HTML comments into the DOM. Since lastChild return a comment node, accessing classList on the returned node raises an error. Using lastElementChild ensures that the last HTML element is always retrieved, regardless of comment nodes in the DOM. Forward-Port-Of: odoo/enterprise#123991 Forward-Port-Of: odoo/enterprise#122106
Payroll frequency labels such as monthly or weekly are now marked for translation across core payroll and multiple country-specific payroll modules. This ensures employees and payroll users see these options in their selected language, improving clarity in localized employee forms.
Original PR description
Issue: ---------------------------------------- The values of the field `schedule_pay` aren't translated. Steps to reproduce: ---------------------------------------- - Switch the language to French - Open an employee form, "Paie" tab - The selection in the "Salaire" tab is not translated to French Cause: ---------------------------------------- When the selection values were moved to a method in 7a123d71925b25f26ba0a8abff0c4a159147bdd0. The strings were not declared as translatable. opw-6359395 Forward-Port-Of: odoo/enterprise#124661 Forward-Port-Of: odoo/enterprise#123718
The Rental Kanban view now correctly shows the New button alongside the custom dashboard. This removes a conflict that could prevent users from creating new rental records from that view, improving day-to-day usability.
Original PR description
The code that adds the custom dashboard conflicted with the code that adds the New button. The fix was already implemented for the list view but not for the Kanban view. This commit applies the same solution used for the list view to the Kanban view. original-task-6088445 Forward-Port-Of: odoo/enterprise#124625
Payroll processes now explicitly use only active employee-related versions when looking up records. This avoids incorrect results if inactive records are included by default, helping payroll and paid time off allocation stay accurate.
Original PR description
We cannot assume in methods that the active_test is set. Therefore, we should always add active=True in search domains. Forward-Port-Of: odoo/enterprise#124542 Forward-Port-Of: odoo/enterprise#124459
Users opening the template picker from an audit report article without a parent article will no longer see an error. Instead, the picker now opens normally and shows that no article template is available, keeping the audit report workflow usable.
Original PR description
Currently, users encounter a traceback when clicking the "Load a Template" button in the WYSIWYG article helper if the article is linked to an audit report and has no parent article. Steps to…
Currently, users encounter a traceback when clicking the "Load a Template" button in the WYSIWYG article helper if the article is linked to an audit report and has no parent article. Steps to reproduce: 1. Install `accountant_knowledge`. 2. Create and open a new audit report. 3. Delete all content from article (the root). 4. Click the "Load a Template" button in the helper. => Crash with `AssertionError: Invalid falsy real id.` The issue occurs because the method responsible for loading the annex to display (see: `get_suggested_templates`) expects at least one record in the recordset. When the article has no parent, the recordset is empty, causing the method to fail. Before attempting to load a template, we will check whether the article has a parent article. If no parent exists, no template will be provided to the template picker. In that case, the picker will display a helper message indicating that no article template is available to load. Task [link](https://www.odoo.com/odoo/project.task/6333859) Task-6333859 Forward-Port-Of: odoo/enterprise#121807
This fixes how salary contract updates choose the right template. When updating a contract, the system now uses the current contract version's template when available, or falls back to the offer's contract template, helping avoid incorrect document setup during HR contract changes.
Original PR description
contract update template should come from current version if any or from the offer's contract template. Task-6094733 Forward-Port-Of: odoo/enterprise#124638 Forward-Port-Of: odoo/enterprise#123450
Fixed a display issue where numeric column headers in financial reports had incorrect padding. This improves readability and keeps report columns visually aligned for users reviewing statements such as the Balance Sheet.
Original PR description
Due to `padding: 0.25rem 0.75rem !important;` To reproduce: - Open Balance Sheet - Check the Balance column numeric-header Forward-Port-Of: odoo/enterprise#124615
Refreshing an accounting report now clears any previous search stored in the session, so exported XLSX files match what users see on screen. This prevents confusion where a report appears to show all partners but the downloaded file still contains only results from an earlier search.
Original PR description
**Steps to reproduce:** - Install account_reports - Open "Partner Ledger" (make sure there are several partners) - Make a search to only display 1 partner - Download XLSX - Without changing the search text, refresh the page - Download XLSX again **Issue:** After refresh, the search text is empty and all the partners are displayed in the report. However, in the XLSX file, only the partner from the previous search is present. **Cause:** The current search is kept in the session and used when getting the XLSX. When refreshing or leaving the page, it's still kept in the session even if the search bar has been reset. opw-6333212 Forward-Port-Of: odoo/enterprise#124685
Code cleanup and technical improvements
This update removes duplicate leave-handling logic from Planning because the same behavior is already provided by a dependency. It reduces maintenance risk without changing expected user behavior.
Original PR description
After commit https://github.com/odoo/enterprise/commit/e0b126cb1ec80743ef06784e230320a1c50041e9, `_handle_flexible_leave_interval` is already implemented in `hr_holidays_gantt` and covers the same case previously handled in `planning_holidays`. https://github.com/odoo/enterprise/blob/7ed917c1de11e29257a726efd4dafe403b9efba1/hr_holidays_gantt/models/resource_calendar.py#L17-L20 Since `planning_holidays` depends on `hr_holidays_gantt`, the duplicate implementation in `planning_holidays` is no longer necessary. **opw-6243778** Forward-Port-Of: odoo/enterprise#124477 Forward-Port-Of: odoo/enterprise#119229
This update modernizes internal user interface references across Enterprise apps so they work with the newer Owl 3 framework. It is mainly a technical cleanup that helps keep accounting, banking, reporting, and related screens stable and maintainable, with no intended functional change for end users.
Original PR description
Enterprise counterpart of the community `master-tref-pr-3-nby` migration.
Convert bridged Owl-2 refs to native Owl 3 signals across the enterprise addons:
- `useRef("x")` -> `const xRef = signal(null)`
- `t-custom-ref="x"` -> `t-ref="this.xRef"` (expression)
- `this.xRef.el` -> `this.xRef()`
Enterprise call sites of the signal-aware community shared hooks (useAutofocus,
useDateTimePicker, useStudioRef, usePosition/useSortable, useVisible,
useActiveElement, …) now pass signals; files consuming inherited/forwarded
community signals read them via `()` instead of `.el`.
Left on the bridge to match community's PR-3 residuals (not migrated in
community either):
- ai/*, knowledge/* embedded components using `useEditableDescendants`
- planning `PlannedDateRangeWithAllocatedHours` xpath into `web.DateTimeField`
- `compiled_view_root` `useRef` in stock_barcode and web_studio form renderer
related-pr: https://github.com/odoo/odoo/pull/274706