Daily updates from Odoo
Tuesday, November 18, 2025
13 changes · 17.0
Resolved issues and error corrections
This fix restores clickable tabs in module information pages, so users can move between sections in an index.html description just like they can in the Odoo Apps Store. It improves the browsing experience and removes a small but frustrating display issue.
Original PR description
* Before: if we have a block contain multiple tab in index.html file we can not click on it to switch between tab, unlike the behiviour in odoo apps store description * After: Make the nav tabs work as it should be Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix corrects how amounts are handled when converting an invoice to a credit note, or the other way around, when storno is enabled. It ensures the debit and credit placement stays consistent and only the sign changes, preventing incorrect accounting values.
Original PR description
This commit fixes the amounts of move lines when converting from invoice to credit note and vice versa when storno is enabled. Previously, when converting from invoice/credit note, the amounts remained negative and switches from debit/credit. The quantities should remain in same debit/credit position and only change sign as I switch from invoice/credit note. task-5226311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Purchase app’s Warnings filter now shows only requests for quotation that actually have warning-level activities. This fixes a mismatch that could previously include records with no activities, making the filter more reliable for users reviewing exceptions.
Original PR description
Steps to reproduce: - Purchases > Requests for Quotation - Ensure you have some POs with: - No activities - Only normal activities - At least one exception activity (type with Decoration Type = Alert…
Steps to reproduce:
- Purchases > Requests for Quotation
- Ensure you have some POs with:
- No activities
- Only normal activities
- At least one exception activity (type with Decoration Type = Alert or Error, unarchive “Exception” in Activity Types if needed)
- Apply the “Warnings” filter
- Before this change:
- POs with no activities incorrectly appear under “Warnings”
- Inverting the filter shows the expected POs with exception activities
Cause of the issue:
- The "Warnings" filter domain relied on a negative operator on the exception decoration field:
https://github.com/odoo/odoo/blob/cebc2acbd0e4d2373e0d1f96bcd291bf70be3a03/addons/purchase/views/purchase_views.xml#L459-L460
- `activity_exception_decoration` is a computed selection set to 'warning' or 'danger' when an exception activity exists:
https://github.com/odoo/odoo/blob/cebc2acbd0e4d2373e0d1f96bcd291bf70be3a03/addons/mail/models/mail_activity_mixin.py#L89-L91
- In 17.0, the search method simply forwards the operator to the decoration type of the linked activities:
https://github.com/odoo/odoo/blob/cebc2acbd0e4d2373e0d1f96bcd291bf70be3a03/addons/mail/models/mail_activity_mixin.py#L120-L121
With ('activity_exception_decoration', '!=', False) this becomes ('activity_ids.activity_type_id.decoration_type', '!=', False), i.e. it relies on a negative operator on the decoration type instead of explicitly matching the exception values. This makes the domain more fragile than an explicit condition on 'warning'/'danger', even though the UI semantics expect “Warning” only when activity_exception_decoration is set.
Why this was not intended:
- The field is truthy only when exception activities exist, a filter named “Warnings” should select exactly those records.
- The negative-operator domain includes records with no activities due to how `!=` works on relational fields, contradicting that semantics.
opw-5177277This update fixes an issue in Studio where adding a new selection option without entering a value could crash the interface. Users can now click Add Selection safely, even if the input is left empty, which makes field setup more reliable.
Original PR description
**Before this commit:** When a user added a new Selection field and clicked the “Add Selection” :white_check_mark: button without entering any value, a `Client Error: (Cannot read properties of undefined (reading 'trim'))` was raised, resulting in a crash of the Studio interface. **After this commit:** Clicking the “Add Selection” :white_check_mark: button with an empty input no longer triggers an error. task-5159376
This update prevents accounting reports from crashing when a saved report points to a handler model that is no longer available. Instead of failing, the system now safely ignores the missing handler and continues to open the report normally, which helps during upgrades or when related modules have been removed or renamed.
Original PR description
In some customer databases, the `custom_handler_model_name` or its fallback `root_report_id.custom_handler_model_name` may point to a model that no longer exists (e.g. `l10n_il.tax.report.handler`).…
In some customer databases, the `custom_handler_model_name` or its fallback `root_report_id.custom_handler_model_name` may point to a model that no longer exists (e.g. `l10n_il.tax.report.handler`). https://github.com/odoo/enterprise/blob/7410249cfdfaca19769e1c9aed813666af8eb19d/account_reports/models/account_report.py#L2578
The previous implementation returned this model name directly without checking if it was registered, which caused a KeyError during report access.
This fix validates the model presence in `self.env` before returning it, and falls back to None if missing. This ensures stable behavior when localization or custom modules are removed or renamed during upgrades.
```python3
Traceback (most recent call last):
File "/home/odoo/src/odoo/17.0/odoo/service/server.py", line 1374, in preload_registries
registry = Registry.new(dbname, update_module=update_module)
File "<decorator-gen-16>", line 2, in new
File "/home/odoo/src/odoo/17.0/odoo/tools/func.py", line 87, in locked
return func(inst, *args, **kwargs)
File "/home/odoo/src/odoo/17.0/odoo/modules/registry.py", line 110, in new
odoo.modules.load_modules(registry, force_demo, status, update_module)
File "/home/odoo/src/odoo/17.0/odoo/modules/loading.py", line 519, in load_modules
migrations.migrate_module(package, 'end')
File "/home/odoo/src/odoo/17.0/odoo/modules/migration.py", line 221, in migrate_module
exec_script(self.cr, installed_version, pyfile, pkg.name, stage, stageformat[stage] % version)
File "/home/odoo/src/odoo/17.0/odoo/modules/migration.py", line 239, in exec_script
migrate(cr, installed_version)
File "/home/odoo/src/odoo/17.0/addons/l10n_il/migrations/1.1/end-migrate_update_taxes.py", line 8, in migrate
env['account.chart.template'].try_loading('il', company)
File "/home/odoo/src/odoo/17.0/addons/account/models/chart_template.py", line 155, in try_loading
return self._load(template_code, company, install_demo)
File "/home/odoo/src/odoo/17.0/addons/account/models/chart_template.py", line 214, in _load
self._post_load_data(template_code, company, template_data)
File "/home/odoo/src/enterprise/17.0/account_reports/models/chart_template.py", line 31, in _post_load_data
company._get_and_update_tax_closing_moves(fields.Date.today(), include_domestic=True)
File "/home/odoo/src/enterprise/17.0/account_reports/models/res_company.py", line 163, in _get_and_update_tax_closing_moves
report, tax_closing_options = tax_closing_move._get_report_options_from_tax_closing_entry()
File "/home/odoo/src/enterprise/17.0/account_reports/models/account_move.py", line 272, in _get_report_options_from_tax_closing_entry
report_options = tax_report.with_context(allowed_company_ids=company_ids).get_options(previous_options=options)
File "/home/odoo/src/enterprise/17.0/account_reports/models/account_report.py", line 1670, in get_options
initializer(options, previous_options=previous_options)
File "/home/odoo/src/enterprise/17.0/account_reports/models/account_report.py", line 1619, in _init_options_custom
self.env[custom_handler_model]._custom_options_initializer(self, options, previous_options)
File "/home/odoo/src/odoo/17.0/odoo/api.py", line 550, in __getitem__
return self.registry[model_name](self, (), ())
File "/home/odoo/src/odoo/17.0/odoo/modules/registry.py", line 209, in __getitem__
return self.models[model_name]
KeyError: 'l10n_il.tax.report.handler'
select a.id,a.name,a.custom_handler_model_id,d.name,d.module,d.create_date,d.write_date from account_report a JOIN ir_model_data d on a.id = d.res_id where d.name = 'vat_report' and d.mod
el = 'account.report';
+----+----------------------------------+-------------------------+------------+---------+----------------------------+----------------------------+
| id | name | custom_handler_model_id | name | module | create_date | write_date |
|----+----------------------------------+-------------------------+------------+---------+----------------------------+----------------------------|
| 4 | {"en_US": "VAT Report (PCN874)"} | 770 | vat_report | l10n_il | 2023-02-05 09:42:05.581858 | 2025-06-25 09:19:46.431141 |
+----+----------------------------------+-------------------------+------------+---------+----------------------------+----------------------------+
SELECT 1
Time: 0.106s
select m.id,m.model,m.name,d.name,d.module from ir_model m JOIN ir_model_data d on m.id = d.res_id where d.res_id = 770 and d.model = 'ir.model';
+-----+----------------------------+------------------------------------------------+----------------------------------+-----------------+
| id | model | name | name | module |
|-----+----------------------------+------------------------------------------------+----------------------------------+-----------------|
| 770 | l10n_il.tax.report.handler | {"en_US": "Israely Tax Report Custom Handler"} | model_l10n_il_tax_report_handler | l10n_il_reports |
+-----+----------------------------+------------------------------------------------+----------------------------------+-----------------+
SELECT 1
Time: 0.009s
select id,name,author,latest_version,state,demo from ir_module_module where name='l10n_il_reports';
+-----+-----------------+-----------+----------------+-----------+-------+
| id | name | author | latest_version | state | demo |
|-----+-----------------+-----------+----------------+-----------+-------|
| 997 | l10n_il_reports | Odoo S.A. | 16.0.1.7.2 | installed | False |
+-----+-----------------+-----------+----------------+-----------+-------+
SELECT 1
Time: 0.009s
```
**### There are some upgrade-specific PR**
<img width="1230" height="64" alt="2025-11-12_17-47" src="https://github.com/user-attachments/assets/0f75d3e0-1c95-48bf-adb6-41473f3f1da2" />
opw-5229611
upg-3258991This change removes a unit test that depended on module-specific and Enterprise-only data, which was causing build failures. The test can be reintroduced later in the proper module if needed, but removing it now helps keep the test suite stable.
Original PR description
The unit test `test_can_reset_deferred_invoice()` has several issues. 1. It should be in the `account_audit_trail` module, as the test requires this module. [Unit test documentation: modules](https://www.odoo.com/documentation/19.0/developer/tutorials/unit_tests.html#modules). 2. The test references fields from the Enterprise module `account_accountant`, `account.move.line.deferred_start_date` and `account.move.line.deferred_end_date`. This causes build tests to fail. As such, the test should be removed now and replaced later if necessary. Fixes [PR 235223](https://github.com/odoo/odoo/pull/235223) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change reduces the amount of data loaded when validating tax-related information for multiple invoices at once. It helps avoid memory errors when registering batch payments, making the payment process more reliable for larger invoice sets.
Original PR description
### Description: When trying to register a payment for multiple invoices, it is possible to trigger an Out Of Memory error. This is caused by the constraint `_validate_taxes_country`, calling the compute `_compute_tax_country_id` on all of the moves. To avoid that, we just retrieve the field we need rather than fetching everything. ### Reference: opw-5152687
Odoo now sets the login session cookie to expire using the database’s session inactivity limit when that setting is available. This keeps browser sessions and server-side session cleanup aligned, reducing cases where users appear logged in longer than the stored session remains valid.
Original PR description
When adding the session_id cookie, we usually set it to expires after odoo.http.SESSION_LIFETIME seconds (at the moment: 7 days). At the same time the "sessions.max_inactivity_seconds" ir.config_paramater is used to remove old sessions from the session store. We suggest to better align the two options, to also use the "sessions.max_inactivity_seconds" ICP when we are in the context of a database and when the option is set to a valid value, and to only fallback on odoo.http.SESSION_LIFETIME otherwise. opw-3716924 opw-5237642 task-5263937 Backport-of: 99f96049a895e7336ab19356649a46db51c012ce
This fix prevents an error when refreshing OSS mapping while multiple companies are active. It ensures the action runs only on the intended company, avoiding a traceback and keeping the setup process smooth for users.
Original PR description
To reproduce: - Activate multiple companies in the selector - Enable OSS on the active company - Click the refresh mapping button ===> Traceback, because a function expects to be called on a single company and is instead called on all the active companies.
This fix stops users from creating or updating a Request for Quotation more than once from the same approval, which could happen when the record is open in multiple tabs or by multiple users. It helps avoid duplicate purchase quantities and keeps purchasing data accurate.
Original PR description
**Problem:** It's possible to click the "Create RFQ's" button more than once, as the user may have multiple tabs open or multiple users are viewing the same record. When this happens, the approval will create or add to an RFQ even if it already did, and this causes double the intended product quantities. **Solution:** The "Create RFQ's" button becomes hidden when purchase_order_count > 0 (i.e. there are linked POs) so we can perform this check within the button's method `action_create_purchase_orders` to prevent RFQ generation (or modification). opw-5227493
This fix removes empty space that appeared in Delivery and Batch Transfer lists and details. It makes the screens look cleaner and prevents unused columns from taking up room when their related information is hidden.
Original PR description
Issue: Blank, unused columns showed in Deliveries and Batch Transfers. Repro Steps: Open Deliveries and see a right-side gap . Open Batch Transfers list and see a right-side gap. Open a Batch Transfer details shows left-side gap. Cause: Rows were hidden, but their table columns stayed visible, so space was still reserved. Fix: Deliveries: hide the rescheduling popover column and the activity indicator column at the column level. Batch Transfers list: hide the activity indicator column at the column level. Batch Transfer Detailed: hide the three quality-check button columns at the column level when the batch has no checks to do (keep row-level visibility when shown). opw-5031933
This update prevents a spurious line from appearing in the Bank Reconciliation report when exchange difference entries cancel out fully. It helps keep reconciliation totals accurate and avoids confusing users with an amount that should not be shown.
Original PR description
*(Tested with the `l10n_be` localization)* 1. Enable multicurrency. Set the main currency to EUR and create the following USD exchange rates: - **01/01/2025**: 1.1 USD per EUR - **06/30/2025**: 1.2…
*(Tested with the `l10n_be` localization)* 1. Enable multicurrency. Set the main currency to EUR and create the following USD exchange rates: - **01/01/2025**: 1.1 USD per EUR - **06/30/2025**: 1.2 USD per EUR - **07/01/2025**: 1.3 USD per EUR 2. Create a new account in the Chart of Accounts: - **Code**: 550012 - **Name**: Bank USD - **Type**: Bank and Cash - **Account Currency**: USD 3. Create a journal: - **Name**: Bank USD - **Bank Account**: 550012 Bank USD - **Currency**: USD 4. From the Accounting dashboard, create a bank transaction in Bank USD: - **Date**: 04/09/2025 - **Amount**: 5000.0 5. Generate the adjustment entry in the *Unrealized Currency Gains/Losses* report: - **Journal**: Exchange Difference - **Expense Account**: 654000 Exchange Results - **Income Account**: 754000 Income Account --- In the *Bank Reconciliation* report for Bank USD, a line appears under *Misc. operations* for an amount of **37.87**. This line should not be there: clicking on it shows that it corresponds to exchange rate lines that fully cancel each other out and have a zero `amount_currency`. --- In `_report_custom_engine_misc_operations`, the amount of misc. operation lines is computed by summing their balances converted to the company currency. However, even when `amount_currency` is 0, a conversion still occurs. opw-4938249
This update fixes an issue that could block invoice creation for alternative sale orders generated from subscription upsells. It ensures the right billing date is carried over, so customers can be invoiced successfully after an upsell alternative is confirmed.
Original PR description
Version - 17.0 Issue: - When creating and confirming an alternative sale order (SO) from an upsell order, attempting to generate an invoice would raise a deferred end date error - As a result, the…
Version - 17.0 Issue: - When creating and confirming an alternative sale order (SO) from an upsell order, attempting to generate an invoice would raise a deferred end date error - As a result, the invoice was not created, and even though the customer's payment succeeded, no invoice was issued. Steps to reproduce: - Create an upsell order of a subscription. - Click Create Alternative to generate an alternative SO. - Confirm the SO and click on Create Invoice to make the invoice - This will throw an error of defferred end date Cause: - The `next_invoice_date` was not copied from the previous upsell order to the new alternative SO. - Without this value, the deferred end date was incorrectly computed as today’s date - 1, triggering the error. Fix: - Copy the `next_invoice_date` from the previous upsell order to the new alternative SO to ensure proper deferred date computation. Impact: Invoices for alternative upsell sale orders can now be created successfully without errors. task-5241150