Tuesday, August 18, 2026
5 changes · saas-19.1
Enhancements to existing features
The Dutch payroll module now includes the 2026 income tax rates for residents. This keeps payroll calculations aligned with the latest tax parameters and helps businesses prepare accurate payslips for the new year.
Original PR description
Added 2026 values for the residents' income tax rates rule parameter. task-6462877 Forward-Port-Of: odoo/enterprise#127556
Resolved issues and error corrections
Odoo now recognizes valid Brazilian electronic invoice XML files even when the main invoice tag has no extra attributes. This prevents eligible vendor bill files from being skipped during import, helping accounting teams process supplier invoices more consistently.
Original PR description
### Issue before this commit: Certain valid Brazilian NF-e (electronic invoice) XML files fail to import because the system silently ignores them during the initial EDI recognition phase. ### Steps to reproduce the issue: 1. Download Accounting and l10n_br_edi 2. Go to Vendor > Bills 3. Try to import both xmls in the ticket 4. One of the two will not be imported correctly ### Cause of the issue: https://github.com/odoo/enterprise/blob/3ed1721b702555e96c9774969927f6517e855704/l10n_br_edi/models/account_move.py#L819-L827 This function relies on a strict byte string search for b"<NFe " while it's also correct if the tag is only `<NFe>`. ### Reason to introduce the fix: To make the initial NF-e file recognition more robust and compliant with standard XML namespace rules, ensuring Odoo successfully processes all valid Brazilian invoices regardless of attribute formatting. opw-6402843 Forward-Port-Of: odoo/enterprise#127851 Forward-Port-Of: odoo/enterprise#126881
Swiss Payroll now uses the employee's requested time off dates when calculating absences, avoiding accidental extra absence days caused by timezone conversion. This prevents one-day accident leaves from being counted as two days for employees without a working schedule, helping keep regular wage and accident salary calculations accurate.
Original PR description
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating…
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating the accident salary. Steps to reproduce: * Install Swiss Payroll. * Configure a monthly employee without a working schedule. * Assign one day of accident time off. * Generate the payslip for that month. Cause: The Swiss wage computation derives absence boundaries from the date portion of the leave's UTC datetimes: https://github.com/odoo/enterprise/blob/16c29e1bab34b5bcb2b001477d928ec5eb294a97/l10n_ch_hr_payroll/models/hr_payslip.py#L313-L330 A fully flexible employee's full day leave starts at local midnight. In timezones ahead of UTC, that start is stored on the previous UTC date, so the inclusive calendar day computation adds an extra day. Solution: We need to use the requested time off dates for both payslip range filtering and absence proration. These fields preserve the calendar days selected by the user independently of timezone conversion, while leaving the UTC datetimes and half-day handling unchanged. opw-6435086 Forward-Port-Of: odoo/enterprise#127513
Salary package configuration now correctly offers all relevant contract benefit fields, including fields provided by country-specific payroll modules. This prevents setup errors and avoids a crash when saving a selected public benefit field.
Original PR description
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The…
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The advantage of the whitelist is that it factored in for the allowed countries, so instead of duplicating this logic to benefit fields and implementing it in every l10n, we can check which module the field comes from.
example:
The field [`company_car_total_depreciated_cost`](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_payroll_fleet/models/hr_version.py#L62) cannot be selected as `res_field_id` when it should be possible as we see in the [data](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_contract_salary/data/hr_contract_salary_benefit_data.xml#L6), it is not whitelisted because we dont want to copy its value from a template.
2- Another fix is the inverse of the public field, there's a traceback because the selection field is always converted to a string and cannot be used to browse as is.
```py
File "/data/build/enterprise/hr_contract_salary/models/hr_contract_salary_benefit.py", line 238, in _inverse_res_field_public
record.res_field_id = self.sudo().env['ir.model.fields'].browse(record.res_field_public)
^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields.py", line 1890, in __set__
write_value = self.convert_to_write(value, records)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_relational.py", line 387, in convert_to_write
return value.id
^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_misc.py", line 115, in __get__
raise ValueError("Expected singleton: %s" % record) from None
ValueError: Expected singleton: ir.model.fields('1', '7', '3', '8', '4')
```The salary calculator now keeps simulations separate from existing payroll documents. This prevents employees with draft payslips from seeing calculator fields cleared or missing-field errors, improving reliability during salary planning.
Original PR description
Steps:- 1. Navigate to Payroll->Employees menu->Salary Calculator 2. Select Employee who already have a draft payslip. 3. You will see all the fields will get emptied and give "Missing required fields". Root cause:- Opening the salary simulator temporarily writes the simulated values onto the employee's record. If that employee already had a draft payslip, this write also refreshed that payslip behind the scenes, even though the payslip had nothing to do with the simulation. Fix:- Mark the simulation clearly as a simulation so it no longer refreshes the employee's existing payslip. task-6392171