Daily updates from Odoo
Monday, August 17, 2026
8 changes · master
Enhancements to existing features
Spreadsheet pivot tables can now include calculated fields based on SQL data, expanding what users can analyze directly in spreadsheets. This improves reporting flexibility for teams that rely on pivot views to explore business data without leaving Odoo.
Original PR description
Task: 6442237 Forward-Port-Of: odoo/enterprise#126645
Belgian payroll meal voucher reports now calculate the total value correctly when vouchers are postponed. This helps payroll teams rely on more accurate reporting for employee benefits and related follow-up.
Original PR description
-Adjust the total value for meal voucher report in case of postponed meal vouchers. Forward-Port-Of: odoo/enterprise#127941
Subscription and rental portal pages now use the refreshed sale order layout, making key details such as rental dates, subscription plans, periods, and invoices easier to find in the sidebar. The update also improves status labels and action placement, creating a clearer and more consistent customer experience across related portal pages.
Original PR description
*: sale_renting, helpdesk, planning_field_service, sign Before this commit, subscription and rental portal pages still relied on the previous sale order layout, with key info (rental dates, plan, start/period, invoices,.) living in the main view as table-based blocks. This commit aligns subscriptions and rentals with the upcoming sale order portal design: rental dates, subscription plan/period and invoices are moved from the main view to the sidebar, the intro row is reworked with restyled status badges and inline metadata, sidebar actions are re-hierarchized.. requires: https://github.com/odoo/odoo/pull/264918 task-5404797
Bank statement reconciliation can now match invoices even when payment references are written with minor formatting differences, such as missing slashes. This helps reduce manual reconciliation work and improves automatic matching accuracy.
Original PR description
Before this commit, the "try_auto_reconcile" algorithm was finding moves when there was a perfect match with either the ref of a move line, the move name, the payment reference and now a sanitize version of the payment ref. For example if an invoice had SO12/1234 as the payment reference, if the statement line has a label SO121234 nothing was found. This commit will then add a new non stored computed field to sanitize the payment ref on the invoice level to help those cases task-6119841
Resolved issues and error corrections
Belgian payroll reporting now allocates severance-related periods using the employee's actual departure date through the theoretical notice end date. Seniority is also calculated without including the notice period, helping produce more consistent payroll declarations across quarters.
Original PR description
- previously, the termination period was split from notice period start to actual departure date, ignoring the theoretical notice duration. Now, it correctly splits from actual departure date to theoretical end date, ensuring proper multi-quarter severance (Code 003) allocation. - Seniority calculation no longer includes the notice period, ensuring consistent results regardless of notice duration Task: 5407737
This fixes an appraisal campaign issue where managers without HR permissions could not start campaigns for employees reporting to them. It also prevents campaigns from accidentally applying to all employees when the selected employee list could not be read.
Original PR description
**Issue**: -User without hr rights is not allowed to launch campaigns for employees under him in the hierarchy. -This issue appears only in master, but it discovered another issue from 19.3, where the value for `employee_ids` was not accessed by the normal user. Thus, appraisals are created for all employees in the list, because not selecting an employee means selecting "All Employees". **Solution**: -SUDOing the read to allow the compute to see what the user has selected. Forward-Port-Of: odoo/enterprise#127391
Annotated Deferred Revenue Reports can now be exported to XLSX without triggering a server error. This prevents interruptions for accounting users who rely on spreadsheet exports for review and reporting workflows.
Original PR description
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to…
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to **Accounting → Reports → Deferred Revenue Report**. * Add an annotation to a deferred revenue line by clicking the **annotate** from three dots next to the account. * Export the report in **XLSX** format. **Observed behavior:** * The export fails with a server error: `UnboundLocalError: cannot access local variable 'annotations_x_offset' where it is not associated with a value` **Cause:** * The variable `annotations_x_offset` is assigned inside the `for header_level_index, header_level in enumerate(options['column_headers'])` loop, which writes the "Annotations" column header for each header level. * The Deferred Revenue Report produces an empty `column_headers` list, so the loop body never executes and `annotations_x_offset` is never assigned. * When the code later tries to write annotation data for each report line, it references the unassigned variable, causing Python to raise `UnboundLocalError`. **Fix:** * Introduce a boolean flag `annotations_header_written = False` before the header loop to explicitly track whether the "Annotations" column header has already been written. * Inside the header loop, set `annotations_header_written = True` after writing the header. * After writing all individual column headers (where `x_offset` already points to the first free column after all data columns), add a fallback: if `report_annotations` is set but `annotations_header_written` is still `False`, assign `annotations_x_offset` from the current `x_offset` and write the "Annotations" header. opw-6354473 Forward-Port-Of: odoo/enterprise#127840 Forward-Port-Of: odoo/enterprise#122768
Fixed an issue where switching to a pivot view through the AI agent could cause the view to crash or open without selected measures. The AI adjustments now wait until the pivot view is ready, preserving default measures when none are specifically requested.
Original PR description
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving…
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving the `APPLY_AI_ADJUST_MODEL` bus event. However, the event could be processed while the pivot model was still executing `_loadData()`. In that case, the following sequence occurred: * `_loadData()` started and awaited. * The controller patch was executed. * The patch called `toggleMeasures()`. * `toggleMeasures()` waited for `_loadData()` to complete. * `_loadData()` finished and updated the metadata with the available measures. * `toggleMeasures()` resumed and wrote back the metadata snapshot it had taken before waiting. Since `toggleMeasures()` operates on a snapshot of the metadata, the measures populated by `_loadData()` were lost when the snapshot replaced the current metadata, leaving the pivot model without its `measures` metadata and causing the view to crash. Prevent this race condition by waiting for the pivot model initialization to complete before applying the AI adjustments. Also preserve the default active measures when the AI agent does not explicitly request any measures instead of clearing them and opening an empty pivot view. task-6384368