Friday, February 20, 2026
8 changes · 19.0
Resolved issues and error corrections
This update corrects a transmission issue related to the 13th month salary payment in Switzerland's LPP (Lohnsteuerhilfeverein) reporting. The change ensures that the 13th month is correctly included in the data sent for tax calculations, aligning with Swiss regulations. This improves accuracy and compliance for businesses using the Odoo Enterprise module in Switzerland.
Original PR description
Forward-Port-Of: odoo/enterprise#107908
This update fixes a potential issue in Australian payroll calculations by ensuring tax information is retrieved from the employee's historical pay period version instead of their current settings. This guarantees accurate withholding, Medicare, and other tax deductions, especially when employee details change over time, leading to more reliable payslips.
Original PR description
Since the introduction of the employee versioning system, using `employee.field_name` in salary rules is no longer accurate for computations involving historical or specific periods. Accessing fields…
Since the introduction of the employee versioning system, using `employee.field_name` in salary rules is no longer accurate for computations involving historical or specific periods. Accessing fields directly on the `employee` record returns the current values. This creates an issue when a future version exists. For example, if a new version is created for February 2026 with an updated Child Support amount, generating a delayed payslip for January 2026 would incorrectly use the February value (current state) instead of the January value (historical state). This commit updates the Python compute logic in the Australian salary rules to use `version.field_name` instead of `employee.field_name`. The `version` object ensures the data used corresponds strictly to the payslip's period. The following rules/fields are updated to use the version object: - Tax Treatment Category - Additional Withholding Amount - Extra Pay - TFN Declaration - Medicare (Reduction, Exemption, and Levy) - Training Loans - NAT 3093 Amount (Tax Offset) - Child Support (Garnishee and Deduction) A test case is added to verify that a payslip correctly retrieves the child support amount from the version valid during the payslip period, ignoring future updates. Task-5002697 Forward-Port-Of: odoo/enterprise#106550
A technical error was preventing users from submitting their CIS monthly reports to HMRC. This fix addresses a problem where the system was incorrectly handling date formatting, causing a traceback. The update now correctly processes dates without timezone information, ensuring reliable report submissions.
Original PR description
Steps to Reproduce: Video Link - https://www.awesomescreenshot.com/video/48861703?key=b2eb19752b965cb72ad3e8a9215631ac - Install l10n_uk_reports_cis module - Enter HMRC credentials & Contractor…
Steps to Reproduce:
Video Link - https://www.awesomescreenshot.com/video/48861703?key=b2eb19752b965cb72ad3e8a9215631ac
- Install l10n_uk_reports_cis module
- Enter HMRC credentials & Contractor details in the HMRC tab in the UK Company
record
- Go to CIS Deduction (GB) report under the Reporting menu
- Select the Return Period already given in the report options
- Click on the Send to HMRC button
- Fill in the necessary details in the CIS monthly return wizard
- After that, click on the Send button on the appeared on the wizard
- Traceback will appear
<details><summary>Exact Traceback</summary>
<p>
```
RPC_ERROR
Odoo Server Error
Occured on 100019718-19-0-all.runbot216.odoo.com on model cis.monthly.return.wizard on 2026-02-04 07:21:51 GMT
Traceback (most recent call last):
File "/data/build/odoo/odoo/orm/domains.py", line 1492, in _value_to_date
value = parse_iso_date(value)
^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/tools/date_utils.py", line 104, in parse_iso_date
raise ValueError(f"expecting only datetimes with no timezone: {value!r}")
ValueError: expecting only datetimes with no timezone: '2026-01-05T00:00:00.000+05:30'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/data/build/odoo/odoo/http.py", line 2275, in _serve_db
return service_model.retrying(serve_func, env=self.env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/service/model.py", line 184, in retrying
result = func()
^^^^^^
File "/data/build/odoo/odoo/http.py", line 2330, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/http.py", line 2545, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/addons/base/models/ir_http.py", line 355, in _dispatch
result = endpoint(**request.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/http.py", line 788, in route_wrapper
result = endpoint(self, *args, **params_ok)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/addons/web/controllers/dataset.py", line 32, in call_kw
return call_kw(request.env[model], method, args, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/service/model.py", line 93, in call_kw
result = method(recs, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/l10n_uk_reports_cis/wizard/monthly_return_wizard.py", line 75, in action_send_montlhy_return
lines = cis_report._get_lines(options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_report.py", line 2678, in _get_lines
all_column_groups_expression_totals = self._compute_expression_totals_for_each_column_group(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_report.py", line 3327, in _compute_expression_totals_for_each_column_group
current_group_expression_totals = self._compute_expression_totals_for_single_column_group(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_report.py", line 3495, in _compute_expression_totals_for_single_column_group
formula_results = self._compute_formula_batch(column_group_options, engine, date_scope, formulas_dict, current_groupby, next_groupby,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_report.py", line 3853, in _compute_formula_batch
return getattr(self, engine_function_name)(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_report.py", line 4010, in _compute_formula_batch_with_engine_domain
query = self._get_report_query(options, date_scope, domain=aml_domain)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports_cash_basis/models/account_report.py", line 227, in _get_report_query
return super(AccountReport, context_self)._get_report_query(options, date_scope, domain=domain)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_analytic_report.py", line 154, in _get_report_query
query = super(AccountReport, context_self)._get_report_query(options, date_scope, domain)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_report.py", line 2249, in _get_report_query
query = self.env['account.move.line']._search(domain)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports_cash_basis/models/account_move_line.py", line 15, in _search
query = super()._search(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_analytic_report.py", line 239, in _search
query = super()._search(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/models.py", line 5364, in _search
domain = domain.optimize_full(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 445, in optimize_full
return self._optimize(model, OptimizationLevel.FULL)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 459, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 653, in _optimize_step
children = self._flatten(child._optimize(model, level) for child in self.children)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 608, in _flatten
for child in children:
File "/data/build/odoo/odoo/orm/domains.py", line 653, in <genexpr>
children = self._flatten(child._optimize(model, level) for child in self.children)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 459, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 971, in _optimize_step
domain = opt(self, model)
^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 1517, in _optimize_type_date
value = _value_to_date(condition.value, model.env, iso_only=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/domains.py", line 1495, in _value_to_date
parse_date(value, env)
File "/data/build/odoo/odoo/tools/date_utils.py", line 146, in parse_date
return parse_iso_date(value)
^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/tools/date_utils.py", line 104, in parse_iso_date
raise ValueError(f"expecting only datetimes with no timezone: {value!r}")
ValueError: expecting only datetimes with no timezone: '2026-01-05T00:00:00.000+05:30'
The above server error caused the following client error:
RPC_ERROR: Odoo Server Error
RPC_ERROR
at makeErrorFromResponse (https://100019718-19-0-all.runbot216.odoo.com/web/assets/109aabb/web.assets_web.min.js:3190:165)
at XMLHttpRequest.<anonymous> (https://100019718-19-0-all.runbot216.odoo.com/web/assets/109aabb/web.assets_web.min.js:3196:13)
```
</p>
</details>
Reason:
- Action on the Send button in the CIS monthly return wizard is passing a string with DateTime + TimeZone info into the date_from and date_to, which is raising an error during domain optimization, stating that expecting only datetimes with no timezone.
Solution:
- We are now passing the parsed date with only Date info in the string to options.
Task-5865605This update fixes a bug where clicking the header of a manufacturing order (MO) removed the filter applied in the shopfloor search bar. The fix ensures that the filter remains active after interacting with the MO, improving usability and allowing users to efficiently locate work orders.
Original PR description
### Steps to reproduce: - Download MRP app. - Create a product and its corresponding BOM (including at least a single operation) - Create and confirm a manufacturing order for 1 unit of that product…
### Steps to reproduce: - Download MRP app. - Create a product and its corresponding BOM (including at least a single operation) - Create and confirm a manufacturing order for 1 unit of that product - Click on the Shop Floor smart button > Click on the header of the MO - The MO filter applied on the shopfloor search bar is removed ### Issue: The MO search filter is removed after you click the header of the workorder order. This bug was introduced by another commit https://github.com/odoo/enterprise/pull/94584/changes/c83ab24a8d037a339db8067c7e9794cba5c16eab to remove the filter when a workorder's barcode is scanned. Hence, https://github.com/odoo/enterprise/blob/67ff37a830202afb8c8914da6f7bc8d4972eefd4/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L289-L292 the change resulted in the filter being removed every time the header is clicked. In the case where a user clicks to start the workorder, we need to keep the filter. ### Fix: Based on https://github.com/odoo/enterprise/blob/67ff37a830202afb8c8914da6f7bc8d4972eefd4/mrp_workorder/static/src/mrp_display/mrp_display_record.xml#L6-L8 `onClickHeader()` is called every time a shopfloor record is clicked, which (based on the reference in the previous section) removes the filter, then calls `startWorking()`. By removing `this.env.searchModel.removeMOFilter()` from this method, it's ensured that clicks preserve the user's current search context. For https://github.com/odoo/enterprise/blob/67ff37a830202afb8c8914da6f7bc8d4972eefd4/mrp_workorder/static/src/mrp_display/mrp_display.js#L248-L250 since the original workflow of removing the filter in case of a barcode scan should be kept, moving `removeMOFilter()` call here with the appropriate reference of `workorder.component.env.searchModel`matches the expected behaviour. opw-5877418
This update resolves an issue where CABA taxes were incorrectly included in tax reports when part of a tax group. The fix ensures that CABA taxes are excluded from reports, preventing duplicated amounts after reconciliation and improving the accuracy of tax reporting. This impacts invoice reporting and financial reconciliation.
Original PR description
How to reproduce: - Create one CABA tax and one normal tax. - Create a tax group containing both taxes. - Create an invoice using this tax group. - In the tax report, the CABA tax appears even when the invoice is unpaid. - After reconciliation, the CABA tax amount is duplicated in the report. When the CABA tax is part of a tax group, it is selected in _read_generic_tax_report_amounts_no_tax_details. Since the tax group has tax_exigibility = 'on_invoice', the CABA tax inside the group is incorrectly included by the query. opw-5468074
This update fixes an issue where OCR-extracted expense amounts weren't correctly converting to the company's standard currency (USD). The change ensures that the 'Total' amount accurately reflects the receipt's original currency value, improving the reliability of expense reporting. This prevents inaccurate financial data.
Original PR description
Steps to reproduce: 1. Initialize an expense with a foreign currency (e.g., EUR). 2. Trigger OCR extraction on a receipt with a specific total. 3. Observe that both 'Total In Currency' and 'Total' (USD) are set to the same value. 4. The exchange rate is forced to 1.0, ignoring the system's exchange rate. Cause: The _fill_document_with_results method assigned the OCR total to both 'total_amount_currency' and 'total_amount' as a placeholder. This triggered the field's inverse logic during the write() call, causing Odoo to treat the input as a manual exchange rate override of 1:1. Solution: Remove the 1:1 placeholder assignment. The method now explicitly calculates 'total_amount' using the _convert() helper once the currency is identified, ensuring the company currency total reflects the actual system exchange rate. opw-5437611 Forward-Port-Of: odoo/enterprise#107862 Forward-Port-Of: odoo/enterprise#107534
This update resolves a problem where CFDI-compliant invoices generated for Mexican companies were producing PDF reports with incorrectly sized section lines. The fix ensures that all invoice details are accurately displayed in the CFDI document, meeting regulatory requirements. This prevents potential issues with invoice acceptance by tax authorities.
Original PR description
**STEP TO REPRODUCE** 1. Select a MX company. 2. Create an invoice for a MX company with a section. 3. Send the invoice via CFDI. 4. Notice the section line in the section pdf is no long enough and does not cover the lines below. opw-5501379
This update resolves a previous issue where multi-action sequences involving document movement often failed due to security restrictions. Now, users can reliably create automation flows that move documents and then trigger subsequent actions, regardless of the final folder location. This enhances the flexibility and usability of Odoo's document management features.
Original PR description
Prior to this commit, creating a multi-action that moved a document to a new folder and immediately triggered another action (e.g., "Create Invoice") often failed. This occurred because the security…
Prior to this commit, creating a multi-action that moved a document to a new folder and immediately triggered another action (e.g., "Create Invoice") often failed. This occurred because the security check required the sub-action to be explicitly embedded (pinned) on the *destination* folder. Since the record was moved during the process, the subsequent action failed the security check on the new folder where it wasn't pinned. This limitation caused confusion for users setting up automation flows, as the intent of the sequence (Move -> Action) was clear and initiated from a valid context (the source folder), but strict per-action security rules blocked execution. This commit improves the `ir.actions.server` execution logic to support this pattern by introducing a context-based security sentinel: 1. Entry Point Validation: When a Documents action (root) is triggered, the system enforces strict security: the action must be explicitly embedded on the record's current folder. 2. Context Inheritance: Once the root action is authorized and begins execution, it sets a secure sentinel in the context. 3. Trusted Execution: Any subsequent sub-actions (children) detect this sentinel and are allowed to run, regardless of the record's current folder location. This ensures that if a user has the right to start the process (the root action), they have the right to complete the defined sequence, even if intermediate steps move the record to a folder where the sub-actions are not explicitly pinned. As a result, the `_can_execute_action_on_records` override in `documents_account` is no longer necessary and has been removed. Tests have been extended in the `documents` and `documents_account` modules to cover these scenarios (using Tags in the `documents` module instead of Accounting-specific models to make the tests generic). A new test file `test_documents_ir_actions_server.py` was created to maintain a clean testing environment, covering nesting, move sequences, and RPC spoofing attempts. Task-5916630