Friday, August 14, 2026
14 changes · saas-19.3
Enhancements to existing features
Belgian payroll calculations now include upcoming fiscal employment bonus rate changes starting in August 2026 and 2028. This helps payroll teams apply the correct tax reductions for low-wage workers and general employment bonus cases as legal rates change.
Original PR description
Starting from August 2026: - The increased fiscal rate for low-wage workers (Volet B) rises from 52.54% to 63% (and to 72% in 2028). - The general fiscal rate (Volet A) rises from 33.14% to 35% starting in 2028. This adds new rule parameters for the fiscal rates and updates computation logic to apply these rates Task-6438319 Forward-Port-Of: odoo/enterprise#126713
Meal voucher reports now calculate the total voucher value correctly when vouchers are postponed. This helps Belgian payroll teams produce more accurate reporting and reduces the risk of incorrect employee benefit amounts.
Original PR description
-Adjust the total value for meal voucher report in case of postponed meal vouchers.
Spreadsheet pivot tables can now include calculated fields based on SQL data, making reports more flexible and useful for analysis. This improves spreadsheet reporting by allowing users to work with more derived business metrics directly in pivot views.
Original PR description
Task: 6442237 Forward-Port-Of: odoo/enterprise#126645
Only the person who created a signature request can now change a signer’s email address. This helps prevent unauthorized or accidental recipient changes, improving trust and control in the signing process.
Original PR description
Forward-Port-Of: odoo/enterprise#127582 Forward-Port-Of: odoo/enterprise#126675
Resolved issues and error corrections
Weekly rentals selected for exactly one week were sometimes counted as two weeks because default pickup and return times made the period slightly longer than seven days. The fix aligns those default times for weekly rentals so customers see the correct rental duration and price.
Original PR description
A product with a weekly rental periodicity is booked for 2 weeks when we actually book it for a single week Steps to reproduce: 1. Install Rental and eCommerce 2. Go to Rental > Products and create a new product 'test', in the Sales tab, set the rental periodicity to 'Weeks' 3. Click on the smart button 'Go to Website' 4. Change the rental period so that it exactly covers a week (e.g. from Monday to Monday) 5. The website shows that you're booking for 2 weeks Issue: The default pickup time is 9h and the default return time is 18h. When we select exactly one week for the rental duration, the true duration of the rental is greater than 1 week (because of the pickup and return time) so it is rounded as 2 weeks. Solution: Also swap `pickup_time` and `return_time` when swapping from weeks periodicity. opw-6397786
Fixes an issue that could prevent users from exporting audit report articles as PDFs in environments using the newer PDF processing backend. This restores reliable PDF export behavior and avoids server errors during a business reporting workflow.
Original PR description
…ern pypdf backend `export_article_to_pdf` calls `writer.setPageMode("/UseOutlines")` on the `PdfFileWriter` instance to make the outline/bookmarks panel visible by default when the generated PDF is…
…ern pypdf backend
`export_article_to_pdf` calls `writer.setPageMode("/UseOutlines")` on the `PdfFileWriter` instance to make the outline/bookmarks panel visible by default when the generated PDF is opened. the old PyPDF2
`odoo.tools.pdf` picks its backend dynamically it first tries to import PyPDF2==2.12.1 and only falls back to the modern `pypdf` library if PyPDF2 is not importable, which is the case on Python 3.13 per requirements.txt, or on any worker where PyPDF2 failed to install.
The PyPDF2-based writer still exposes `setPageMode`, so the bug was never seen on backends using it. The modern pypdf-based writer replaced that method with a `page_mode` property (getter/setter) and never kept a camelCase alias for it
As a result, any request hitting this code got a beautiful HTTP 500
`AttributeError: 'BrandedFileWriter' object has no attribute 'setPageMode'`
`setPageMode` is not called anywhere else so
this fixes the call site directly instead of adding a new alias to the shared _pypdf.py
opw-6382905Belgian point-of-sale self-orders are now signed using the designated self-ordering user, so mobile orders can be validated even when no cashier is logged in. This prevents fiscal device rejections and keeps self-order sales compliant while printing remains handled separately.
Original PR description
In this PR (github.com/odoo/enterprise/pull/126611) we removed the blackbox printingQueue, cause the pritning is now handled via Obox. - This commit reintroduce a signingQueue, but only for self-orders, as the printing is now handled via Obox. - It also fix the issue where signing a mobile self-order while no cashier is connected (login screen) was rejected by the FDM: signExternalOrder took the INSZ number from getCashier(), so signSale was sent without its required employeeId. - Self-orders are now signed with the INSZ number of the self-ordering default user, like the kiosk already does. FW of : https://github.com/odoo/enterprise/pull/126695
Spanish VAT record book exports now work for accounting users even when the report includes Point of Sale data. This prevents access errors during tax reporting while keeping the POS data use limited to building the report.
Original PR description
Steps to reproduce:
- With an ES Company
- Open a POS session, add product with tax and pay
- As a user with only accounting access
- Go to Accouting > Reporting > Tax report
- Select Generic Tax report
- Print "VAT record Books"
Issue:
An AccessError will raise
```
Access Error
You are not allowed to access 'Point of Sale Session' (pos.session) records.
This operation is allowed for the following groups:
- Point of Sale/User
Contact your administrator to request access if necessary.
```
Analysis:
Vat Record Books handler for POS needs to read pos.session and pos.order records. Currently, the action is performed with the rights of the user running the report, so accounting-only user face an error.
As POS records are only read internally to build the report, we add sudo call to get the data.
opw-5862529
Forward-Port-Of: odoo/enterprise#126590
Forward-Port-Of: odoo/enterprise#125980Managers without HR permissions can now launch appraisal campaigns for employees they manage. The fix also prevents campaigns from accidentally applying to all employees when selected employee records were not readable by the user.
Original PR description
**Issue**: -User without hr rights is not allowed to launch campaigns for employees under him in the hierarchy. -This issue appears only in master, but it discovered another issue from 19.3, where the value for `employee_ids` was not accessed by the normal user. Thus, appraisals are created for all employees in the list, because not selecting an employee means selecting "All Employees". **Solution**: -SUDOing the read to allow the compute to see what the user has selected.
This fixes an issue where users without Accounting permissions could be blocked from confirming sales orders when a Studio approval rule used certain customer follow-up fields. Approval checks now run with the right elevated access so normal business workflows are not interrupted by unrelated permission limits.
Original PR description
continuation of [PR](https://github.com/odoo/enterprise/pull/121856) Issue: Inside _get_approval_spec filtered_domain is called a few times and due to a related field that calls an access rights group that the user who used the action isnt apart of is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5)create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Solution: Go one up the stack where _get_approval_spec is called and add a syudo for those calls opw-6316069 Forward-Port-Of: odoo/enterprise#127412
Recruitment officers without payroll permissions can now generate and open Belgian salary offers without running into an access error. This fixes a workflow blocker caused by a payroll-related warning check that used information recruiters are not allowed to read directly.
Original PR description
The field `hr.contract.salary.offer.l10n_be_is_below_scale_warning` is accessible to users outside of the payroll groups but its computation requires a read access to payroll only fields on the related `hr.version`. Steps to reproduce: 1- log in with a user that has the group Recruitment/ Officer, and no payroll privileges. 2- go to an applicant and click generate offer 3- The offer will be created but the user will not have access to it and the redirection will fail reported by our recruitment officers
Submitting Australian Single Touch Payroll records without payslips or employees now shows a clear validation message instead of causing an unexpected error. This helps payroll users understand what information is missing before sending data to the ATO.
Original PR description
When submitting payroll data to the ATO from an STP record without any payslips or employees, a traceback is raised. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module -…
When submitting payroll data to the ATO from an STP record without any payslips or employees, a traceback is raised. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module - Switch to ``My australian Company`` - Go to Payroll > Configuration > Settings > In Australian Localization, Set BMS ID > Set STP Responsible and his date of birth - Go to Payroll > Reporting > Single Touch Payroll > Create a new record > Set Payment Date > Submit to ATO > Sign & Submit to ATO Traceback: ```py IndexError: tuple index out of range ``` https://github.com/odoo/enterprise/blob/b0e48baaf99bdc4faefd2ffdd3bd5637fb548593/l10n_au_hr_payroll_account/models/l10n_au_stp.py#L228-L233 The traceback occurs because ``_get_fiscal_year_start()`` assumes that the STP record always contains at least one payslip or one employee. When these recordsets are empty, indexing the first element raises an IndexError. Solution: This commit validates that the required payslips or employees are present before the submission and raises a validation error instead of a traceback. Forward-Port-Of: odoo/enterprise#127733 Forward-Port-Of: odoo/enterprise#124096
WhatsApp channel members can once again access Advanced Settings to manage membership. This fixes a regression in version 19.3 where the option was hidden, preserving a familiar and more suitable workflow for WhatsApp channels.
Original PR description
Show the advanced-settings thread action for WhatsApp channel members, since channel_role is only supported on channel/group types which controls this button. Advanced Settings have long been used to manage channel membership. Their removal in 19.3+ introduced a regression, while channel roles are more cumbersome and do not integrate well with WhatsApp concern similarly to livechat: https://github.com/odoo/enterprise/pull/112959#discussion_r3593831089. so keeping Advanced Settings for WhatsApp for now.
This fix prevents batch invoice sending to SUNAT from being blocked when some Peruvian invoices contain lines without taxes. Instead of a generic technical failure, the system handles the issue consistently with single-invoice sending so other invoices can continue processing.
Original PR description
In l10n_pe_edi, invoices containing lines without tax can't be submitted to SUNAT.
When sending a single invoice, an error message is displayed. However, sending multiple invoices processes them in the background by a cron job. In this case, EDI document creation fails without error handling, raising a generic parsing error and blocking the cron from processing other invoices.
Steps to reproduce:
1. Create and post two invoices with no tax on some lines.
2. From the list view, select both invoices and click "Send" and mark "SUNAT".
3. An exception is raised: `ValueError: XMLSyntaxError("Start tag expected, '<' not found, line 1, column 1")`.
opw-6390480
Forward-Port-Of: odoo/enterprise#125143