Wednesday, April 1, 2026
5 changes · saas-19.2
Enhancements to existing features
This update significantly speeds up stock availability calculations by optimizing how the system matches incoming and outgoing inventory moves. The change reduces processing time from 90 seconds to 10 seconds for large shipments, making inventory reports load much faster and improving overall system responsiveness.
Original PR description
Before this commit, computing `product_availability` and `product_availability_state` required calling the `get_report_lines` method from the `stock.forecasted_product_product` model. In pickings…
Before this commit, computing `product_availability` and `product_availability_state` required calling the `get_report_lines` method from the `stock.forecasted_product_product` model. In pickings containing moves linked to many incoming and outgoing moves, the `reconcile_out_with_ins` function caused performance issues. The reconciliation logic worked as follows: 1. For each `out_move`, attempt to match it with an `in_move` if the `in_move` references the `out_move` in its `move_dests`. 2. If the demand of the `out_move` is not fully satisfied, add it to `unreconciled_outs`. 3. Loop over `unreconciled_outs` (after attempting to reconcile them using the initial prodcedure) to reconcile against the remaining `in_moves`. The performance bottleneck was that even when an `in_move` directly referenced an `out_move`, the code would unnecessarily loop over **all** `in_moves` to filter out the `in_moves` that has the `out_move` in its `move_dest`. --- To improve performance, an **inverse mapping** from `out_move` IDs to their corresponding `in_moves` is introduced. - Reconciliation now starts by iterating only over the relevant `in_moves`. - If the demand is still unmet, the algorithm attempts reconciliation against the remaining `in_moves`. - This reduces the time complexity to **O(N + M)**, since `in_moves` with zero quantities are removed and never revisited. **Implementation details:** - An `OrderedSet` is used for the inverse mapping to preserve the original query order. - Benefits of `OrderedSet`: - **O(1)** removal (assuming no collisions) - Maintains insertion order, ensuring the same order as the query result. --- | Metric | Before PR | After PR | |---------------|-----------|----------| | Execution Time| ~90 sec | ~10 sec | The benchmark above is done on a `stock.picking` record that queried in the `_get_report_lines` method **5331** `out_moves` and **8922** `in_moves`. opw-4951469 Forward-Port-Of: odoo/odoo#235801 Forward-Port-Of: odoo/odoo#224002
Resolved issues and error corrections
This fix prevents the system from crashing during upgrades when predefined document folders (like Legal) have been deleted. The system now properly handles inactive folders instead of throwing an error, ensuring smooth upgrades to version 19.2 for users who have the Documents Sign module installed.
Original PR description
While embedding sign into predefined folders we need to consider if they are active or not. Otherwise during…
While embedding sign into predefined folders we need to consider if they are active or not. Otherwise during [upgrade](https://github.com/odoo/upgrade/blob/master/migrations/documents_sign/saas%7E19.2.1.0/post-migrate.py) to `saas~19.2` with module `documents_sign` installed, it will try to get document actions of predefined folder [here](https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1592), so if the folder is inactive it will not be able to read the folder [here](https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1494).
Steps to reproduce:
1/ Install `documents_sign` in 19.0
2/ Delete the folder `Legal` (documents.document_legal_folder)
3/ Upgrade to `saas~19.2`
As result we will get traceback similar to this:
```
2026-03-19 16:17:50,553 4059246 INFO test_documents_sign odoo.modules.migration: module documents_sign: Running migration [saas~19.2.1.0>] post-migrate
2026-03-19 16:17:50,593 4059246 WARNING test_documents_sign odoo.modules.loading: Transient module states were reset
2026-03-19 16:17:50,594 4059246 ERROR test_documents_sign odoo.registry: Failed to load registry
2026-03-19 16:17:50,594 4059246 CRITICAL test_documents_sign odoo.service.server: Failed to initialize database `test_documents_sign`.
Traceback (most recent call last):
File "/home/odoo/src/odoo/saas-19.2/odoo/service/server.py", line 1598, in preload_registries
registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update'], reinit_modules=config['reinit'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/tools/func.py", line 65, in locked
return func(inst, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/registry.py", line 202, in new
load_modules(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 465, in load_modules
load_module_graph(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 231, in load_module_graph
migrations.migrate_module(package, 'post')
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/migration.py", line 220, in migrate_module
exec_script(self.cr, installed_version, pyfile, pkg.name, stage, stageformat[stage] % version)
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/migration.py", line 257, in exec_script
mod.migrate(cr, installed_version)
File "/home/odoo/src/upgrade/migrations/documents_sign/saas~19.2.1.0/post-migrate.py", line 7, in migrate
_post_init_hook(util.env(cr))
File "/home/odoo/src/enterprise/saas-19.2/documents_sign/__init__.py", line 40, in _post_init_hook
folders_to_process._embed_action(sign_action.id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1621, in _embed_action
folder.action_folder_embed_action(folder.id, action_id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1592, in action_folder_embed_action
return self.get_documents_actions(folder_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1496, in get_documents_actions
raise UserError(_('This folder does not exist or is not accessible.'))
odoo.exceptions.UserError: This folder does not exist or is not accessible.
```
For fixing the issue we skip inactive folders.
tbg-2508Fixed a timezone issue that was causing the Inventory Valuation report to run significantly slower than necessary. When users in certain timezones viewed the report, the system was unnecessarily recalculating the entire inventory history instead of using a quick calculation for today's data. This fix ensures the system correctly identifies the current date based on the user's timezone, reducing report load time from over 40 seconds to just 3 seconds.
Original PR description
When accessing the Inventory Valuation report, we check if the selected date correspond to the current day:…
When accessing the Inventory Valuation report, we check if the selected date correspond to the current day: https://github.com/odoo/odoo/blob/3610d16ae47e53860e6e047b98de6a60733a5408/addons/stock_account/report/stock_valuation_report.py#L33-L34 If the date is today, the method _run_average_batch() simply computes the value as qty_available * standard_price. But if it is not, it will replay the whole AVCO history which can be heavy. https://github.com/odoo/odoo/blob/3610d16ae47e53860e6e047b98de6a60733a5408/addons/stock_account/models/product.py#L394-L397 The "date" variable used in the comparison is the local date obtained from the browser while fields.Date.today() returns the UTC date. In certain case, when the local timezone is not on the same day as UTC anymore, this causes the report to be very slow to load because it replays the full history when it should not. We propose to use the context_today() method instead to get the date from the user's timezone. Benchmark: | No AVCO Products | Before PR | After PR | |------------------|-----------|----------| | 12000 | > 40 s | 3 s | opw-6050007 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256727 Forward-Port-Of: odoo/odoo#255841
This fix corrects a bug where purchasing multiple units of a kit product resulted in incorrect cost calculations. When ordering 3 units at $10 each, the system was showing a cost of $3.33 instead of $10 per unit. The issue affected both AVCO and FIFO inventory valuation methods and has now been resolved to ensure accurate product costing.
Original PR description
**Issue**: A PO of several units of kit product can lead to a wrong BOM cost **Steps to reproduce**: - Create a kit product (by creating a BOM) with AVCO valuation - Create a purchase order with 3…
**Issue**: A PO of several units of kit product can lead to a wrong BOM cost **Steps to reproduce**: - Create a kit product (by creating a BOM) with AVCO valuation - Create a purchase order with 3 units and a unit price of 10 - Confirm it and confirm the associated receipt - Go to the BOM of the kit product and check BOM overview -> The cost is 3.33 instead of 10 This also works with FIFO valuation **Cause**: While computing the value of the move: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/stock_move.py#L282 https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/stock_move.py#L313-L314 It checks the value of the PO: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/stock_move.py#L371-L372 Which relies on the `cost_ratio`: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/purchase_stock/models/stock_move.py#L221-L222 Which is computed this way: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/purchase_mrp/models/stock_move.py#L17 And does not take the number of received units into account. This means that the value of the move is 10 instead of 30, which makes the valuation computation wrong: https://github.com/odoo/odoo/blob/2e4a4f2d063f9b09263e6c137e1c04358020c668/addons/stock_account/models/product.py#L393 opw-5924940 Forward-Port-Of: odoo/odoo#253439 Forward-Port-Of: odoo/odoo#249236
This fix corrects a typo in the Italian electronic invoice system that was causing debit notes to be rejected by the Italian tax authority (SDI). The field name 'Datifatturecollegate' has been corrected to 'DatiFattureCollegate' to match the required format, allowing debit notes to be successfully transmitted.
Original PR description
# Problem:
When sending debit notes to the SDI, they are rejected with the following error:
`File non conforme al formato : Invalid content was found starting with element 'Datifatturecollegate'. One of '{DatiOrdineAcquisto, DatiContratto, DatiConvenzione, DatiRicezione, DatiFattureCollegate, DatiSAL, DatiDDT, DatiTrasporto, FatturaPrincipale}' is expected.`
# Cause:
In the `account_invoice_it_FatturaPA_export_debit_note` there's a typo in 'Datifatturecollegate' as it should be 'DatiFattureCollegate'
https://github.com/odoo/odoo/blob/bc1c264b6232c78c33a96169110b37d9d4430243/addons/l10n_it_edi_ndd_account_dn/data/invoice_it_template.xml#L5-L8
opw-5930596
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#253905
Forward-Port-Of: odoo/odoo#249284