Wednesday, September 23, 2026
12 changes · 19.0
Enhancements to existing features
The Argentine localization test setup now creates sample invoices more efficiently, reducing the time and database work needed to run related report tests. This improves developer and validation speed without changing the resulting report output or business behavior.
Original PR description
The use_current_date=False branch of _create_test_invoices_like_demo built 18 invoices through Form, which reruns the whole move onchange for every field of every line. It was two thirds of the l10n_ar_reports class setup. Create them with _create_invoice from the fields the Form set, like the other branch does. The accounting date is now the invoice date on every invoice, the report output is unchanged. With the l10n_ar_reports counterpart: | l10n_ar_reports, runbot 18.0 L10n | before (3 builds) | after | |------------------------------------|-------------------|-------| | TestArReports setUpClass | 78-103s | 31s | | module test time | 80-106s | 33s | | queries | 45.4k | 28.4k | Forward-Port-Of: odoo/odoo#290111
The Argentina reports test data setup now creates sample vendor bills more directly, avoiding unnecessary repeated processing. This reduces automated test time and database work while keeping report results unchanged.
Original PR description
Same as the l10n_ar fixture: the 10 demo vendor bills were built through Form, rerunning the whole move onchange for every field of every line. Create them with _create_invoice from the fields the Form set. The accounting date is now the invoice date on every bill, the report output is unchanged. With the l10n_ar counterpart: | l10n_ar_reports, runbot 18.0 L10n | before (3 builds) | after | |------------------------------------|-------------------|-------| | TestArReports setUpClass | 78-103s | 31s | | module test time | 80-106s | 33s | | queries | 45.4k | 28.4k | Forward-Port-Of: odoo/enterprise#132697
The Vietnam localization now includes dedicated accounts for revenue and costs from selling or liquidating investment property. This supports compliance with Circular 99/2025/TT-BTC and helps businesses report these gains or losses separately in Profit & Loss statements.
Original PR description
Circular 99/2025/TT-BTC adds a dedicated Profit & Loss line for gains/losses on the sale and liquidation of investment property, computed from dedicated sub-accounts rather than the main revenue and cost-of-goods-sold accounts. Add the two accounts to the chart of accounts: - 5117 Revenue from sale and liquidation of investment property - 6327 Cost of sale and liquidation of investment property Task-6518304 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287572
Resolved issues and error corrections
Fixed an issue where selecting an autocomplete suggestion could cause the dropdown to reopen and stay visible. This improves form reliability and prevents related automated checks from timing out.
Original PR description
Before this commit, the autocomplete dropdown of a many2one could open again right after a suggestion was picked, and stay open. The step of mail_template_dynamic_placeholder_tour waiting for it to…
Before this commit, the autocomplete dropdown of a many2one could open again right after a suggestion was picked, and stay open. The step of mail_template_dynamic_placeholder_tour waiting for it to close then times out:
FAILED: [8/36] Tour mail_template_dynamic_placeholder_tour
Step Wait for the drop down to disappear
(trigger: div[name="model_id"] .o-autocomplete:not(:has(.ui-autocomplete)))
TIMEOUT step failed to complete within 10000 ms.
This happens because the search filling the dropdown runs 250ms after the last keystroke, so a suggestion of the previous search can be picked while the next search is still scheduled. Picking a suggestion only closes the dropdown. The scheduled search then runs, opens the dropdown on the selected value, and nothing closes it after that.
This commit fixes the issue by discarding the scheduled search when the dropdown closes.
https://runbot.odoo.com/odoo/error/233574
https://runbot.odoo.com/odoo/error/237744
https://runbot.odoo.com/odoo/error/944454
https://runbot.odoo.com/odoo/error/945517
https://runbot.odoo.com/odoo/error/947141
Forward-Port-Of: odoo/odoo#290216
Forward-Port-Of: odoo/odoo#287888This fixes how Odoo handles non-stored related many-to-many fields so they no longer keep an unnecessary database relation. It prevents data from being mixed up between similar fields, reducing the risk of incorrect information appearing in records.
Original PR description
When we setup a many2many field which is not stored, it must not have a relation. This is already done for nonrelated fields, but we must do it also for related fields. Otherwise, we may have…
When we setup a many2many field which is not stored, it must not have a relation. This is already done for nonrelated fields, but we must do it also for related fields. Otherwise, we may have side-effects like finding sibling fields in 20.0: in the code below, reading categories would fill roles.
```py
model_id = self.env["ir.model"]._get("test_new_api.foo")
fields = [{
"name": "x_partner_id",
"ttype": "many2one",
"relation": "res.partner",
}, {
"name": "x_role_ids",
"ttype": "many2many",
"relation": "res.partner.category",
}, {
"name": "x_partner_category_ids",
"ttype": "many2many",
"relation": "res.partner.category",
"related": "x_partner_id.category_id",
"store": False,
"readonly": True
}]
for f in fields:
f["model_id"] = model_id.id
self.env["ir.model.fields"].create(fields)
env['test_new_api.foo']._fields['x_partner_category_ids'].relation # should be None
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#290067This update fixes a timing issue that could make the website editor think a page preview was ready before it actually was. It improves reliability when editing website menus, reducing intermittent failures during resizing or loading of the editor preview.
Original PR description
**PROBLEM** waitForIframeReady() returns when the iframe is not ready. This can cause a race condition in `test_17_website_edit_menus` when the website editor sidebar resizes the iframe of the webpage. **CAUSE** waitForIframeReady() check if there is a `is-ready` on the body attribute, instead of checking its value. This was fixed in the observer if condition by https://github.com/odoo/odoo/commit/89994eb7a54ca606bab26b6d579d03e86c11ba60 but this is not the case for the first check. runbot-939929
The website project form handling was cleaned up and reorganized to make it more reliable and easier to update in the future. This is a minor maintenance fix with no expected disruption for users, but it helps support smoother form processing going forward.
Original PR description
Clean up and move some of the form processing logic for future updates opw-6560036 Forward-Port-Of: odoo/odoo#287697
This fix ensures an automated employee registration test opens the correct starting menu in community editions. It prevents false test failures, helping keep quality checks reliable without changing end-user functionality.
Original PR description
**Trigger:** Running `test_onsite_employee_registration` in a community database starts in Discuss instead of enterprise's usual home menu which crashes the test on the first step. This commit adds the `showAppsMenuItems` util to the test. To ensure the test starts in the correct view. runbot-946289
Opening a previously sent Sign template with no fields no longer triggers an access error. The system now avoids adding a placeholder signer when the template is already tied to a sent request, so users can view these templates normally.
Original PR description
Version: 19.0 Steps to reproduce: - Create a sign template with no sign fields - Send a sign request using that template - Open that template from Templates Issue: After a sign request is sent, record rules make the template read only for sign items (create/write only when there are no sign requests). On open, if the template has no signers, the UI auto creates a dummy signer. For an empty sent template, that create is denied by those rules and raises an Access Error. Fix: Guard the auto create signer flow with a sign requests check so that a sent template does not try to create a new signer on open. Task: 6591146
Demo data for Belgian payroll-related modules now loads with the correct Belgian company context. This prevents errors when users install or load the demo data through the interface, improving setup reliability.
Original PR description
Before the fix, loading the module's demo data through the UI triggered an error. task-6581013 Forward-Port-Of: odoo/enterprise#132358
The Bulgarian SAF-T reporting feature will no longer be installed automatically unless the advanced accounting setup is explicitly present. This prevents businesses from seeing or activating a specialized accounting report in environments that may not support it properly.
Original PR description
As the Bulgarian SAF-T Report is destined for advanced accounting, it should only be available and auto-installed when the 'accountant' module is as well. As the 'accountant' module is not part of the dependencies yet (it is from 20.0 on), we cannot be sure that it is already installed. It is then better to stop the auto installation altogether.
This change removes unnecessary fallback logic in the accounting reports download flow. It makes the code clearer and helps avoid confusion around how closing behavior is handled after downloading a report.
Original PR description
`!something` is never nullish, so `?? true` is dead code. Probably the intention was `if (!(data.no_closing_after_download ?? true))`, but reviewer has the final say and I can change it.