Wednesday, September 2, 2026
10 changes · saas-19.1
Enhancements to existing features
Vendor bill field prediction has been optimized to run faster on databases with many accounting entries. This should reduce delays when processing Peppol documents and matching invoice lines to products, accounts, or taxes, especially for larger invoices.
Original PR description
### Description: Predicting fields can be slow when the database has a large amount of move lines (AML). This is caused by the fact that `_predicted_field` will search on all these AMLs to find the…
### Description: Predicting fields can be slow when the database has a large amount of move lines (AML). This is caused by the fact that `_predicted_field` will search on all these AMLs to find the ones related to the searched fields. It can be an issue when using Peppol since it is used a lot in most localizations to match each line to its product/account/tax. To speed up the queries, the move IDs have been inlined in `_build_predictive_query` to avoid suboptimal execution plans caused by LIMIT and ORDER BY clauses. Additionally, materialization of the `account_move_line` CTE has been removed so the planner can inline filters and stream rows directly, which improves performance in most use cases. ### Benchmark: **For a `history.limit`[^1] of 100:** | Nb of invoice line | Before | After | AMLs scanned | |--------------------|-----------|---------|--------------| | 33 | 7s | 4s | 232 | | 172 | 11.39min | 5min | 99859 | | 1934 | 3h+ [^2] | 1h40min | 102503 | **For a `history.limit`[^1] of 50:** | Nb of invoice line | Before | After | AMLs scanned | |--------------------|---------|---------|--------------| | 33 | 6s | 4s | 187 | | 172 | 2.52min | 1.27min | 21002 | | 1934 | 40min | 20min | 21002 | [^1]: System parameter `account.bill.predict.history.limit` [^2]: Stopped manually after 3h; full runtime not measured ### Reference: opw-5937519 Forward-Port-Of: odoo/enterprise#129895 Forward-Port-Of: odoo/enterprise#128172
Large Italian electronic invoices now import much faster by reducing repeated per-line processing and saving records in a more efficient batch. This helps businesses handle high-volume supplier bills with less waiting time and fewer delays in accounting workflows.
Original PR description
### Description: When importing a large invoice, the process can take a lot of time. This is caused by how `l10n_it_edi` handles the creation and writing of each line of the bill. To improve performance, most of the process is now performed in memory and record creation is deferred to a single batch at the end. Additionally, the check related to `account_accountant` is cached to avoid superfluous calls. ### Benchmark: **For `history.limit`[^1] of 50 (= 21002 `account.move.line`):** | Invoice lines | Before | After | Speedup | |---------------|----------|---------|---------| | 33 | 4.75s | 2.23s | 2.1× | | 172 | 2.3min | 45.1s | 3.1× | | 1,934 | 44.4min | 6.8min | 6.6× | [^1]: System parameter `account.bill.predict.history.limit` ### Reference: opw-5937519 Forward-Port-Of: odoo/odoo#285723 Forward-Port-Of: odoo/odoo#282880
Ecuadorian electronic invoicing now lets companies record their software provider's RUC and automatically include it on electronic documents and printed reports. This helps businesses comply with the latest SRI reporting requirements for third-party billing software, including delivery guides.
Original PR description
Purpose: SRI Resolution requires taxpayers using 3rd-party billing software in Ecuador to report the software provider's RUC on all electronic documents and printed representations (RIDE). A new system parameter is introduced and displayed in Invoicing > Setting > Ecuadorian Localization > Electronic Invoicing, so users can add their software provider's RUC. This value will be automatically sent to the EDI and displayed on the report. task-6432810 Forward-Port-Of: odoo/enterprise#129456
Resolved issues and error corrections
Italian withholding tax returns submitted in quarter-end months no longer trigger the periodic VAT return export by mistake. This prevents crashes and avoids attaching an incorrect VAT file to the wrong return.
Original PR description
In Italy the periodic VAT return (LIPE) is filed quarterly, so `is_quarter_month` gates the XML export wizard on March, June, September and December. That field only looks at the date, never at the…
In Italy the periodic VAT return (LIPE) is filed quarterly, so `is_quarter_month` gates the XML export wizard on March, June, September and December. That field only looks at the date, never at the kind of return, so every Italian return locked on a quarter month was treated as a LIPE. Submitting the withholding tax return therefore opened the LIPE export wizard. Depending on the record the wizard receives, it either crashes while reading the VP lines missing from the withholding report, or silently generates a LIPE file and attaches it to another return. Add an `is_lipe_return` field telling whether the return actually produces the LIPE. Steps to reproduce: - Install `l10n_it_xml_export` and `l10n_it_edi_withholding_reports` on an Italian company with monthly returns - Open Accounting > Reporting > Tax Return - Review and submit the withholding returns up to February - Review then submit the March withholding return --> The LIPE export wizard opens, and the export fails on the withholding report. opw-6255016 Forward-Port-Of: odoo/enterprise#126676 Forward-Port-Of: odoo/enterprise#125263
Weekly overtime in My Timesheets now uses the employee schedule's Total hours instead of the Full Time Equivalent value. This makes overtime figures consistent for flexible schedules and aligns My Timesheets with Planning and All Timesheets.
Original PR description
# How to reproduce - Set the current employee's schedule to one with : - Schedule Type : Flexible - Total : a different amount than "Full Time Equivalent" - Go to My Timesheets - Add a new line with…
# How to reproduce
- Set the current employee's schedule to one with :
- Schedule Type : Flexible
- Total : a different amount than "Full Time Equivalent"
- Go to My Timesheets
- Add a new line with some Time Spent > 0
- Hover the bottom right cell of the grid (this is the total overtime for the week)
# The issue
The computation of the overtime for the week is based on "Full Time Equivalent" instead of "Total". This is inconsistent with the Planning app and the All Timesheets view.
# Cause
This [PR] introduced the usage of `full_time_required_hours` to compute the total overtime. This field was used because `hours_per_week` ("Total") was thought to be computed using `resource.calendar.attendance`. However, that is not the case when the schedule is flexible : https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/resource/models/resource_calendar.py#L220 https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/resource/models/resource_calendar.py#L163-L166
[PR]: https://github.com/odoo/enterprise/pull/81057
opw-6303520
Forward-Port-Of: odoo/enterprise#125510This fixes an error that could appear when users reordered a long list of order lines spanning multiple pages and then tried to discard their changes. Users can now safely cancel those edits without the screen failing, improving reliability when working with large quotations or similar records.
Original PR description
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to…
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to reorder them - Discard all changes (X shaped button) You will have an evaluation error **Behavior:** When loading a list of records exceeding the limit, only parts of the records are saved in `_cache`. When triggering a reordering of said list, all records need to be loaded including the ones on other pages: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/static_list.js#L1139-L1149 `_getResIdsToLoad()` gets all Ids missing from the cache, these are then passed through `._createRecordDatapoint` and will then be stored in `_cache`. The issue is that the Datapoints are getting created with only `activeFields` as data, which in our case are `id` and `sequence` When discarding the changes `._checkValidity()`is called on each Datapoint: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/record.js#L423-L429 And then `._isInvisible()` is called. This is where the issue happens, since only `sequence` and `id` are stored, when we try evaluate `combo_item_id`, which is the condition to see if sequence is invisible, `combo_item_id` is not found and we get an Evaluation Error. This commit prevents going into `._checkValidity()` by adding `this.isInEdition` to the check leading to it, requiring that the record is in 'edit' mode which is not the case for records created with `_createRecordDatapoint()` opw-6399024 Forward-Port-Of: odoo/odoo#281018
French e-invoicing now ignores PDP response entries that do not include a valid message identifier. This prevents scheduled status updates from failing and helps keep invoice and vendor bill e-invoicing processing reliable.
Original PR description
Steps to reproduce: - Install `l10n_fr_pdp` and `l10n_be` module - Activate `French e-invoicing` (you need to put your DB in test mode) (i.e: `account_peppol.edi.mode = 'test'` in system parameter)…
Steps to reproduce:
- Install `l10n_fr_pdp` and `l10n_be` module
- Activate `French e-invoicing` (you need to put your DB in test mode)
(i.e: `account_peppol.edi.mode = 'test'` in system parameter) Refer this Documentation https://www.odoo.com/documentation/19.0/applications/finance/fiscal_localizations/france.html?highlight=e%20invoicing#localizations-france-e-invoicing-fac-elec-config
- Create a Invoice and Sent with `E-invoicing`
- Run `PEPPOL: retrieve new documents` Cron
- In Invoice Other Info > `E-Invoicing Status` should be in `Done` state
- Now Vendor Bill is created for that invoice > Cancel that bill with reason > Check `E-Invoicing Status` response for bill(one response will be without UUID)
- Go to schedule actions > `PEPPOL: update message status`
- Run it and get the traceback: `KeyError: 'false'`
Issue:
When sending a lifecycle response to the French PDP, `_pdp_send_response` calls the `/api/pdp/1/send_response` endpoint and expects IAP to return a `message_uuid` for each response.
However, IAP return a response without a message UUID, for example: ` {'messages': [{'message_uuid': False}]}` `_pdp_send_response` currently assumes that every returned message has a valid UUID and creates an `account.peppol.response` with:
```
'peppol_message_uuid': False
'peppol_state': 'processing'
```
This leaves an `account.peppol.response` in `processing` state without a UUID that can be used to track it.
During the next execution of `_cron_peppol_get_message_status`, `_peppol_get_message_status` retrieves this response through `_peppol_get_documents_for_status` and builds `uuid_to_record` using `peppol_message_uuid` as the key. The resulting mapping contains the Python value `False` as a key.
The cron then calls the PDP `1/get_document` endpoint with this invalid UUID. IAP returns it as the string `'false'`, which is passed to `_peppol_process_messages_status`. The French PDP implementation tries to retrieve the corresponding record with: `uuid_to_record[uid]`
Since the mapping contains `False` while `uid` is `'false'`, this raises: `KeyError: 'false'`
This failure prevents the status cron from completing the processing of the messages.
Solution:
Avoid creating the `account.peppol.response` when IAP does not return a `message_uuid`. A response without a UUID cannot be tracked through the PDP status flow, so creating it in `processing` state only leaves an
invalid record that will later cause the status processing to fail.
opw-6453133
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281691Purchase orders for products billed on ordered quantities now correctly generate accrued expense entries even before goods are received. This ensures expected purchase costs are reflected in accounting at the right time and avoids missing or understated accruals.
Original PR description
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `stock`, `purchase`, and `accountant` - Create a storable product with: - Tracking Inventory enabled - Control Policy set…
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `stock`, `purchase`, and `accountant` - Create a storable product with: - Tracking Inventory enabled - Control Policy set to **Ordered Quantities** - Create and confirm a Purchase Order with some unit price - Do not receive or invoice the order - From the Purchase Order gear menu, click **Accrued Expense Entry** Issue: ------ The Accrued Expense Entry wizard opens, but no accounting lines are generated. For products invoiced on **Ordered Quantities**, the ordered quantity should already be accrued even though nothing has been received. Cause: ------ This issue was introduced after this changes [commit](https://github.com/odoo-dev/odoo/commit/81f25bc57b8433a65bf33950c64dc7582240a229) Previously, the accrual wizard relied on the stored `qty_to_invoice` field, whose computation already respected the product's Control Policy. For products invoiced on **Ordered Quantities**, `_compute_qty_invoiced()` computes the quantity to invoice from the ordered quantity: https://github.com/odoo/odoo/blob/810a02a577c2811dc5c12f0abf45eebb9cf96d00/addons/purchase/models/purchase_order_line.py#L147-L152 The refactoring replaced this logic with the new `amount_to_invoice_at_date` field, which always computes the invoicable quantity as: `qty_received_at_date - qty_invoiced_at_date` https://github.com/odoo/odoo/blob/65dbcabcd243abf24d6d3c3788d2caff66485790/addons/purchase/models/purchase_order_line.py#L282-L285 This formula ignores the product's Control Policy. For products invoiced on Ordered Quantities, before any receipt: `qty_received_at_date` = 0 `qty_invoiced_at_date` = 0 therefore: `amount_to_invoice_at_date` = 0 The Accrued Expense wizard filters out lines whose `amount_to_invoice_at_date` is zero: https://github.com/odoo/odoo/blob/65dbcabcd243abf24d6d3c3788d2caff66485790/addons/account/wizard/accrued_orders.py#L168-L178 As a result, the purchase order line is excluded entirely and the wizard produces no accounting entries. The same assumption is also used later in `account.accrued.orders.wizard._compute_move_vals()` when computing tax-included amounts, causing incorrect accrual values for Ordered Quantities products whenever receipts and invoices differ. Fix: ---- Introduce `_get_qty_to_invoice_at_date()`, mirroring the existing purchase_method logic used by _compute_qty_invoiced(). The helper returns: product_qty - qty_invoiced_at_date for Ordered Quantities products; `qty_received_at_date` - `qty_invoiced_at_date` for Received Quantities products. Now products invoiced on `Ordered Quantities` become accruable as soon as the Purchase Order is confirmed; --- opw-6290782 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276435
The website and HTML builders now format entered links consistently with the editor. This prevents web addresses, email addresses, and phone numbers from being saved with the wrong prefix, helping visitors reach the intended destination.
Original PR description
Steps to reproduce: - Add an image and add a link on that image. - Set the URL input to "odoo.com". - Click outside the image and click on the image again. => The "http" protocol was added instead of "https". - Set the URL input to "test@test.com". - Click outside the image and click on the image again. => The "http" protocol was added instead of "mailto". The issue also occurs for phone numbers. The builder URL picker did not normalize entered URL values like the editor link popover does. Actions using the picker could therefore receive raw values and would need to normalized the URL in a different way. This commit reuses the editor link input normalization helper in the builder URL picker so committed and previewed URL values are handled consistently. task-6384411 Forward-Port-Of: odoo/odoo#283358 Forward-Port-Of: odoo/odoo#275936
This fixes restaurant order printing so staff can reprint only newly added order lines instead of accidentally printing the full order again. It restores the previous behavior to avoid kitchen confusion, duplicate preparation, and wasted paper.
Original PR description
This reverts commit a1ee5faa141af45e38879a448ce6bbd5ed58cc54 (https://github.com/odoo/odoo/pull/266070) which is causing issues (reprint whole order when I only want to print newly added order lines). task-id: 6230594 FW of https://github.com/odoo/odoo/pull/285993 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr