Daily updates from Odoo
Friday, August 14, 2026
64 changes
11 changes
Enhancements to existing features
Belgian payroll is updated to apply new fiscal employment bonus rates starting in August 2026 and future rate changes in 2028. This helps ensure payroll calculations remain aligned with upcoming Belgian tax rules for low-wage workers and general fiscal reductions.
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
Timesheet Assistant suggestions are now easier to select in bulk by dragging across them with the mouse button held down. Ctrl-click no longer opens an unwanted new Odoo page, reducing accidental navigation and making batch actions faster.
Original PR description
Currently when the user uses ctrl + click on a suggestion, a new odoo page is opened. This is an undesirable side effect and it is removed in this commit. Also, users have to manually click on each suggestion when they want to remove them in batch, or create one timesheet for a bunch of suggestion. This commit lets user hover over suggestion with the mouse button pressed to select them. task-6385047 Forward-Port-Of: odoo/enterprise#124642
Only the person who created a signature request can now change a signer's email address. This helps prevent unintended or unauthorized recipient changes and improves trust in the signing process.
Original PR description
Forward-Port-Of: odoo/enterprise#127582 Forward-Port-Of: odoo/enterprise#126675
Spreadsheet pivots can now include SQL-based computed fields, giving users more flexible ways to analyze business data directly in spreadsheets. This improves reporting capabilities while keeping the change focused on the spreadsheet experience.
Original PR description
Task: 6442237 Forward-Port-Of: odoo/enterprise#126645
Resolved issues and error corrections
Fixes an issue that prevented users from downloading the General Ledger report as a CSV when using French. The export now uses the correct translation context, so localized accounting reports download reliably instead of failing with an error.
Original PR description
Currently an exception is generated when the user tries to export (downlaod) a `CSV` file of the `General Ledger` report as the below step: - Install the `accountant` module with demo data - Enable…
Currently an exception is generated when the user tries to export (downlaod) a `CSV` file of the `General Ledger` report as the below step: - Install the `accountant` module with demo data - Enable and change to the `French` language - Go to `Comptabilité` > `Analyse` > `General Ledger` - Click the cog icon in the menu > Click on `CSV` - An error occurs in the log, and nothing is downloaded Error: `TypeError: 'NoneType' object is not subscriptable` This issue occurs after the recent refactoring changes in [1]. When `_generate_csv_lazy_export` is called, it uses the `_()` method for translation, which accesses `self.env`. However, at this point, the cursor is already closed. As a result, when the code at [2] is reached from `ormcache`, it raises the above error because `model.env.transaction.ormcaches__` is `None` (code ref [3]). This commit fixes the above issue by performing the translation using the existing `handler` variable, which contains an environment with the new cursor (see code ref [4]). [1]: https://github.com/odoo/odoo/commit/13c3adf3a8b5ba6325190d6b9aea45fb8a6a8b2f [2]: https://github.com/odoo/odoo/blob/5ef7829895b2e05650da394c1e35dfdc3a23c066/odoo/orm/cache.py#L111 [3]: https://github.com/odoo/odoo/blob/5ef7829895b2e05650da394c1e35dfdc3a23c066/odoo/orm/environments.py#L1012 [4]: https://github.com/odoo/enterprise/blob/912a47b8f0828ef8316b7e4ecdabf8a2f305b313/account_reports/models/account_general_ledger.py#L524 Sentry-7608119520
Fixed an issue that caused audit report PDF exports from Accountant Knowledge to fail on systems using the newer PDF engine. Users can now generate these PDFs reliably, including on newer Python environments.
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-6382905
Forward-Port-Of: odoo/enterprise#124480Fixes an issue where users without certain accounting permissions could be blocked from confirming sales orders when a Studio approval rule used a related accounting field. Approval checks now run with the necessary access so valid 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
Managers without full HR access can now launch appraisal campaigns for employees they oversee. The fix ensures selected employees are read correctly, preventing appraisals from being accidentally created for everyone when access rules hide the selection.
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. Forward-Port-Of: odoo/enterprise#127391
When projects and tasks are created from templates, archived users are now excluded from task assignments linked to project roles. This prevents inactive employees or former team members from being assigned work through sales-created projects.
Original PR description
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created…
Steps to reproduce:
-------------------------------------------------
1. Install the `sale_project` module
2. Create a test user with Project User rights
3. Create a Project Role with the Created User as a Team Member
4. Create a Template Project as follows:
* Add one task to the template project
* Add the created Project role to the Task
5. Create a Service Type Product with:
* Create on order: Project
* Project Template: Created Template
6. Archive the Created User
7. Create and Confirm the Sale Order with the Created Product
Observation:
-------------------------------------------------
The generated task is assigned to the archived user, although the archived user is no longer part of the Project Role.
Issue:
-------------------------------------------------
While creating Project and Tasks from template, the context disable active record filtering (e.g., `active_test=False`), causing the assignment logic to fetch both active and inactive/archived users linked to the role. https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/odoo/orm/models.py#L4868
After that, during the `copy_data` method, It takes all the users from the roles without checking weather user is active or not
https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/addons/project/models/project_task.py#L890-L904
And even if we pass only Active users from this method, on moving further, it reassigns the users from roles without checking the Active field of the user
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L501-L503
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L544-L553
Due to this, the Archived User is also assigned to the tasks from the project roles
Solution:
-------------------------------------------------
Apply a `filtered('active')` check directly on the project role's users `(role.user_ids)` within the core task-copying logic in both `project` and `project_enterprise` modules. This ensures archived users are universally excluded from task assignments during template copying, regardless of what triggers the template instantiation.
Related Community PR: https://github.com/odoo/odoo/pull/274426
opw-6350841
Forward-Port-Of: odoo/enterprise#125637Planning managers without HR access can now change the resource on a planning slot without accidentally publishing it. The fix uses public employee information for the permission check, keeping planning updates aligned with the user's intended action.
Original PR description
For planning manager without HR access, if the user change the resource of the planning slot it will publish it automatically as the employee_ids field cannot be used without HR access. Prefer to use public employee to have better condition without using explicit sudo Caused-by: https://github.com/odoo/enterprise/commit/e88dcd0e545183b3f03e06b62158c52a1e6d2103 Forward-Port-Of: odoo/enterprise#127503
This fix ensures signature fields stay in the correct visible position when signing PDFs that were created with unusual page origins. It prevents users from downloading signed documents where signatures or fields appear missing, improving reliability of the Sign workflow.
Original PR description
Steps to reproduce (version 16+): 1) Obtain a pdf with a negative origin point: This can occur when a customer exports a pdf from another software, or it can be made manually using a python script 2) In the sign app, upload the pdf and create a new template, add a signature field to the document. 3) Sign the document. The preview will load correctly and the signature will be visible 4) Download and open the signed pdf. The signature is not on the document Notes: Issue occurs because the signature was added to the pdf outside of the visible area. The preview works because the signature is rendered on top of the unsigned document in the correct location. The issue can be fixed applying a translation to the canvas. Ticket: [6317223](https://www.odoo.com/odoo/project/49/tasks/6317223?debug=assets) Forward-Port-Of: odoo/enterprise#127302 Forward-Port-Of: odoo/enterprise#121960
14 changes
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#1251436 changes
Resolved issues and error corrections
Barcode receipts now keep the putaway destination when users scan multiple lots for the same product. This prevents items from being split between the intended shelf and the default stock location, reducing warehouse confusion and manual corrections.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2…
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2 units of that product; putaway sets the reserved move line destination to WH/Stock/Shelf 1. 4. In the Barcode app, scan a first lot, then a second lot. The second lot lands on a separate line at WH/Stock instead of WH/Stock/Shelf 1. Issue --- The first lot reuses the reserved line and keeps its Shelf 1 destination. The second lot cannot reuse it because its tracking number differs, so `_findLine` returns nothing and `_getNewLineDefaultValues` builds a new line with `location_dest_id` set to `_defaultDestLocation()`, the picking's default destination (WH/Stock). https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L1591-L1601 Putaway relocates the destination on the move line at reservation, never on the picking, so only the reserved line carries Shelf 1. Since `groupKey` includes `location_dest_id`, the new line does not group with the first lot and shows separately at WH/Stock. This is not a regression: new lines have always defaulted to the operation destination. https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L239-L241 The new line now inherits the selected line's `location_dest_id`, already relocated by putaway, instead of the default. opw-6317077 Forward-Port-Of: odoo/enterprise#125309
This fixes an issue where financial reports could show incorrect date ranges after switching between companies with different fiscal year setups. The report now selects the correct fiscal year based on the chosen end date, helping keep period-based reporting accurate.
Original PR description
Fix year-mode date filter when switching between companies with different fiscal years With two companies configured: one using a standard fiscal year and one using an offset fiscal year, switching between them could produce incorrect date ranges. This happened because the previous company’s `date_to` value was reused to compute the current period for the newly selected company, and vice versa. The fix is to use the `date_to` year instead and select the latest fiscal year ending in that same year.
Invoices in Peru that include lines without taxes now fail with a clear, handled message during batch sending instead of causing a generic system error. This prevents the background sending process from getting blocked and allows other invoices to continue being processed.
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-6390480Fixed an issue that caused Deferred Revenue Report exports to fail when the report included annotations. Business users can now export annotated accounting reports to Excel without encountering a server error.
Original PR description
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to…
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to **Accounting → Reports → Deferred Revenue Report**. * Add an annotation to a deferred revenue line by clicking the **annotate** from three dots next to the account. * Export the report in **XLSX** format. **Observed behavior:** * The export fails with a server error: `UnboundLocalError: cannot access local variable 'annotations_x_offset' where it is not associated with a value` **Cause:** * The variable `annotations_x_offset` is assigned inside the `for header_level_index, header_level in enumerate(options['column_headers'])` loop, which writes the "Annotations" column header for each header level. * The Deferred Revenue Report produces an empty `column_headers` list, so the loop body never executes and `annotations_x_offset` is never assigned. * When the code later tries to write annotation data for each report line, it references the unassigned variable, causing Python to raise `UnboundLocalError`. **Fix:** * Introduce a boolean flag `annotations_header_written = False` before the header loop to explicitly track whether the "Annotations" column header has already been written. * Inside the header loop, set `annotations_header_written = True` after writing the header. * After writing all individual column headers (where `x_offset` already points to the first free column after all data columns), add a fallback: if `report_annotations` is set but `annotations_header_written` is still `False`, assign `annotations_x_offset` from the current `x_offset` and write the "Annotations" header. opw-6354473 Forward-Port-Of: odoo/enterprise#127726 Forward-Port-Of: odoo/enterprise#122768
Accounting users can now export Spanish VAT record books even when the report includes Point of Sale transactions. The report safely reads the needed POS data internally, preventing access errors while keeping normal user permissions unchanged.
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#125980Australian payroll submissions now check that required payslip or employee information exists before sending data to the ATO. Instead of an unexpected system error, users receive a clear validation message, helping payroll teams correct incomplete STP records more easily.
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
5 changes
Enhancements to existing features
Spreadsheet pivot tables can now include SQL-based computed fields, giving users more ways to build custom analyses directly in spreadsheets. This improves reporting flexibility and helps teams extract more tailored insights without leaving the spreadsheet workflow.
Original PR description
Task: 6442237
Odoo Sign now limits changes to a signer's email address to the person who created the signing request. This helps prevent unintended or unauthorized recipient changes, improving control over who receives and signs documents.
Original PR description
Forward-Port-Of: odoo/enterprise#127582 Forward-Port-Of: odoo/enterprise#126675
Resolved issues and error corrections
Australian payroll submissions to the ATO now check that required payslip or employee data is present before submission. Instead of an unexpected system error, users receive a clear validation message, helping payroll teams correct the issue and continue safely.
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
Historical Luxembourg payslips now use the wage index that was valid at the end of the payslip period, rather than today's index. This helps ensure past payroll calculations remain accurate and consistent with the period being processed.
Original PR description
Historical payslips incorrectly used today's wage index instead of the index active during the payslip period. Now, salary rules evaluate the indexed wage using `payslip.date_to` via the new `_get_l10n_lu_indexed_wage(date)` contract method. Task: 6395557 Forward-Port-Of: odoo/enterprise#125861
Large accounting reports now render fewer hidden rows, reducing page weight and improving responsiveness when users fold sections or search. This helps reports with thousands of lines feel faster and easier to navigate until the newer virtual grid solution is available.
Original PR description
When a report has 1 000+ lines, the DOM gets quite heavy which make DOM operation very slow. To help reduce this, we now will minimize the number of components rendered by removing components that previous were just hidden using "d-none" on the line. This will require more creation and suppression of components but it should make the DOM size smaller so it should help on larger reports where a lot of lines are hidden (by folding back a line, or by using the search bar). opw-6427411 opw-6442756 PR Note: this is only required until saas-19.5/20.0 since the virtual grids are added then which will resolve this issue since the virtual grids only render what's in the view of the user with long paddings on top and bottom so only ~70-80 lines are actually rendered. Forward-Port-Of: odoo/enterprise#127516
3 changes
Enhancements to existing features
Only the person who created a signature request can now change a signer’s email address. This helps prevent unintended or unauthorized recipient changes, improving control and trust in the signing process.
Original PR description
Forward-Port-Of: odoo/enterprise#127582 Forward-Port-Of: odoo/enterprise#126675
Resolved issues and error corrections
Historical Luxembourg payslips now use the wage index that was active at the end of the payslip period, instead of using the current index. This helps ensure older payroll calculations remain accurate when wage index values change over time.
Original PR description
Historical payslips incorrectly used today's wage index instead of the index active during the payslip period. Now, salary rules evaluate the indexed wage using `payslip.date_to` via the new `_get_l10n_lu_indexed_wage(date)` contract method. Task: 6395557 Forward-Port-Of: odoo/enterprise#125861
Odoo now recognizes valid Brazilian electronic invoice XML files even when the invoice tag has no extra attributes. This prevents some vendor bills from being skipped during import, helping accounting teams process compliant invoices 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#126881
3 changes
Enhancements to existing features
Signer email addresses on signature requests can now only be changed by the person who created the request. This helps prevent unauthorized or unintended changes to recipients, improving trust and control in the signing process.
Original PR description
Forward-Port-Of: odoo/enterprise#126675
Resolved issues and error corrections
Odoo now correctly recognizes Brazilian electronic invoice XML files even when the main invoice tag has no extra attributes. This prevents valid vendor bills from being skipped during import, reducing manual handling and import failures for Brazilian accounting teams.
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#126881
Luxembourg payroll now calculates indexed wages using the wage index that was active at the payslip period end date, rather than today's index. This helps ensure historical payslips and payroll records remain accurate when wage indexes change over time.
Original PR description
Historical payslips incorrectly used today's wage index instead of the index active during the payslip period. Now, salary rules evaluate the indexed wage using `payslip.date_to` via the new `_get_l10n_lu_indexed_wage(date)` contract method. Task: 6395557 Forward-Port-Of: odoo/enterprise#125861
21 changes
New functionality added to Odoo
Belgian payroll now supports the withholding tax exemption for qualifying investments in aid zones. This helps employers apply the temporary 25% reduction for eligible newly created jobs and include the required 274.81 reporting in payroll declarations and reports.
Original PR description
Implement support for the Belgian withholding tax exemption regarding investments in aid zones. Employers benefit from a temporary 25% reduction in withholding tax remittance on eligible remunerations for newly created jobs. Changes: - Add `l10n_be_is_aid_zone` flag on employee,version models. - Update 274.XX calculation logic to isolate Nature 81 bases and apply the flat 25% rate. - Add "Aid Zone (274.81)" tab in the UI and include its totals in the main Exempted Amounts summary. - Update (XML payload and XLSX report) to include the new 81 code block. Task: 6352132
Enhancements to existing features
Spreadsheet dashboards across several business areas have been visually standardized so figures display with consistent sizing, spacing, and backgrounds. A new Employee appraisal dashboard has also been added, and translated dashboard text now displays correctly without being compressed.
Belgian payroll now alerts users when an employee's bank account is invalid. This helps payroll teams catch payment issues before processing salary payments, reducing failed transfers and manual follow-up.
Original PR description
This commit adds a warning message in the Belgian payroll module when an employee's bank account is invalid. task-6458596
Calendar events are now matched to projects or tasks using their direct “linked to” relationship before falling back to customer history. This makes suggested timesheets more accurate, especially when calendar meetings are tied to specific project or helpdesk work.
Original PR description
…ojects via the 'linked to' field Before this commit: - Calendar events are matched based on the most timesheet project of the partners. After this commit: - Calendar events are matched to projects/tasks via the "linked to field" before looking to partners projects. task-6238332
The timesheet Timeline view now displays assistant suggestions in true chronological order instead of sorting them by title. Users can also see each suggestion's start time, making it easier to review and enter work accurately.
Original PR description
Forward-Port-Of: odoo/enterprise#126238 Forward-Port-Of: odoo/enterprise#122862
Standard VAT checks are now available from the start across Odoo, reducing inconsistent behavior between setups. EU online VIES VAT checks are separated into an optional accounting-related module, making configuration cleaner for companies that need them.
Original PR description
Previously, both standard offline VAT validation and VIES VAT validation were implemented within a single module, `base_vat`. This led to several issues: 1. Since VIES depended on `account`, it made…
Previously, both standard offline VAT validation and VIES VAT validation were implemented within a single module, `base_vat`. This led to several issues: 1. Since VIES depended on `account`, it made it difficult to use even the standard VAT validation independently. 2. `base_vat` had to be explicitly added as a dependency in all localization modules (l10n), which was redundant because a single dependent module would install it globally anyway. 3. Standard VAT validation was not available from the start at a global level, leading to inconsistencies in validation behavior before and after module installation. With this PR: 1. The standard offline VAT validation is moved to `base`, making it available globally from the beginning. 2. The VIES VAT validation is separated into a new module, `l10n_eu_account_vies`. This module can be enabled via the `vat_check_vies` option in settings. task-5428948 Community PR - https://github.com/odoo/odoo/pull/259784 Upgrade PR - https://github.com/odoo/upgrade/pull/10014 IAP PR - https://github.com/odoo/iap-apps/pull/1609
The light user role now automatically includes a standard set of permissions for employees, including access to Planning, Appointments, and Referral features. This helps ensure employees receive consistent baseline access without extra manual setup.
Original PR description
Since there is a new light user role (and group) that will be set for each employee, this role must come with a package of privileges. Additional default groups are added to the light user: - Planning: User - Appointment: User - Refferal: User: Referral only See related Community PR for more details. Task-6112938
Payroll dashboard warnings now load through a single continuous request instead of many separate requests. This keeps warnings appearing as they are ready while reducing repeated server work, improving responsiveness and efficiency for users.
Original PR description
The dashboard warnings were loaded with multiple RPC calls (one per warning). The main issue with this behavior is the cache that stays cold => more queries are done for the same result at the end. Here we keep this behavior: see all warnings as soon as they are computed, on the dashboard, without blocking the user. But instead of the N rpc, there is one request, to get a stream of warnings. task-6422228
The time off Gantt view now keeps the full month visible for employees with flexible working schedules, making planning more stable and easier to read. New time off entries also avoid applying default hours that could overwrite an employee’s actual schedule.
Original PR description
- Display the full month for employees with flexible schedules to keep the month view stable. - Remove default hours from the creation payload to avoid overriding the employee's actual schedule. Task: 6346363
AI agents now use Odoo's website scraping service to collect content from URL sources instead of relying on basic local page parsing. This should make URL-based knowledge more reliable, avoid duplicate fetching across agents, and better organize how different source types are indexed.
Original PR description
Move URL source content extraction to use the IAP website scraper instead of fetching and parsing pages naively. Introduce two new models to support this: `ai.web.page`, which stores the scraped content of a URL and is shared by every AI agent source pointing to that URL so a given URL is only ever fetched and stored once regardless of how many agents source it, and `ai.web.scraper.batch`, which submits URL batches to the scraper, polls for their results, and dispatches them back to the model that requested them once they reach a terminal state. The change also removes the local HTML extractor, adds the required cron and access rules, and adapts source creation/reprocessing so binary, knowledge, and URL sources each follow their own indexing flow. Knowledge sources' content extraction is now using html2plaintext. task-id-6052079
Financial reports now present company information more clearly, reduce clutter in report headers, and format negative currency amounts correctly. The depreciation schedule and multi-ledger PDF filters were also adjusted so reports are easier to read and avoid duplicate "Local GAAP" labels.
Original PR description
Before this commit: - The depreciation schedule report displayed the currency symbol. - Company details were positioned below the company logo. - Unit options (e.g., Thousands, Millions) were displayed in the top-right options header. - Selecting only "Local GAAP" in the multi-ledger filters caused it to appear twice in the generated PDF. - Negative amounts for currencies with a 'before' position (e.g., '$') were formatted incorrectly as "$ (1)". After this commit: - Removed the currency symbol from the depreciation schedule. - Relocated company details to the right side of the logo. - Removed unit options from the top-right header - Fixed the multi-ledger filter to ensure "Local GAAP" appears only once in the PDF. - corrected the negative amount formatting for 'before' position currencies to "($ 1)". Community PR: odoo/odoo#281909 Task-6113583
The Call Debrief view now makes better use of larger displays by showing video and transcription side by side when both are available. It also adjusts more smoothly in full-screen mode, making call review easier and more comfortable across devices.
Original PR description
This PR improves the Call Debrief experience across screen sizes and adapts the UI by: - Use a two-column layout on larger screens when both video and transcription are available. - Make the layout adapt correctly in full-screen mode. task-6328684 Requires: - https://github.com/odoo/odoo/pull/272719 Forward-Port-Of: odoo/enterprise#122029
Resolved issues and error corrections
This fixes an accounting transfer issue where journal entries could be off by one cent when transferring a percentage to a destination account. The destination line now uses the exact amount removed from source accounts, helping ensure generated entries stay balanced.
Original PR description
Before this commit, _get_transfer_move_lines_values computed the amount for the last destination line from the global transferred balance, instead of reusing the amount already removed from the source accounts. The two values are rounded independently and can differ by a cent whenever the removed amount comes from more than one rounded source, producing an unbalanced journal entry. Removing that condition the last destination line always absorbs the remainder fixes it. Steps to reproduce: 1. Transfer model with 2 source accounts and 1 destination line at 15%. 2. Post moves for the period: account A balance 395.88, account B balance 252.16 (total 648.04). 3. Run `action_perform_auto_transfer()`. Before: source lines -59.38 (395.88 * 15%) and -37.82 (252.16 * 15%), destination line +97.21 (648.04*15% rounded) -> entry off by 0.01. After: destination line takes the exact remainder, 97.20 -> balanced. OPW-6443928 Forward-Port-Of: odoo/enterprise#126877
Subscription product tiles in the online shop now calculate discounted recurring prices from the correct subscription plan price, not the one-time sale price. This prevents customers from seeing misleading monthly prices when a pricelist discount applies to a recurring plan.
Original PR description
Steps to reproduce: =================== 1. Create a subscription product, allow one-time sale, sale price 5 2. Add a recurring price 10/month 3. On the pricelist, add an advanced rule: -10% for the…
Steps to reproduce: =================== 1. Create a subscription product, allow one-time sale, sale price 5 2. Add a recurring price 10/month 3. On the pricelist, add an advanced rule: -10% for the monthly plan 4. Open the shop page and look at the product tile Cause: ======= On the /shop page, the subscription price displayed on a product tile is computed by `_get_sales_prices`. The cart has no plan selected yet at that point, so `request.cart.plan_id.id` is empty and was passed as `plan_id` to `_compute_price`. In `product.pricelist.item._compute_base_price`, the recurring base price is only looked up when a `plan_id` is given: if rule_base == 'list_price' and product.recurring_invoice and plan_id: ... # find the recurring rule -> base = recurring price With `plan_id` empty, that branch is skipped and the percentage rule falls back on the product's one-time `list_price` instead of the recurring price. Example: one-time price 5, recurring price 10/month, pricelist rule -10% on the monthly plan. => Tile showed 4.5/month (5 * 0.9) instead of 9/month (10 * 0.9). Solution: ========= The chosen pricing already targets a plan, so pass `pricing.plan_id.id` to `_compute_price`, matching what the product page does in `_get_additionnal_combination_info`. opw-6307398 Forward-Port-Of: odoo/enterprise#126259 Forward-Port-Of: odoo/enterprise#120872
Fixed an issue where Australian payroll could skip unused leave balances when processing multiple employees at once. Each payslip now checks leave allocations for the correct employee, helping ensure termination or final pay calculations include the right leave amounts.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480 Forward-Port-Of: odoo/enterprise#127330
VoIP contact searches now recognize phone numbers even when users type or receive an automatically added country code. This makes keypad suggestions and contact lookup more reliable and shows matched numbers in a clearer, user-friendly format.
Original PR description
Before this fix, the keypad's callee suggestions only matched the search term against the raw `phone` field of contacts. When the user input was automatically prefixed with a country code (e.g. +86), the match could fail if the stored phone number lacked the international prefix. Now `phone_sanitized` is also sent to the frontend via the Store, and the callee suggestion matching falls back to the E164 sanitized number when the raw phone field does not match. Task-6290760 compr https://github.com/odoo/odoo/pull/278018 Forward-Port-Of: odoo/enterprise#127553 Forward-Port-Of: odoo/enterprise#124797
When payroll users include additional unpaid payslips in a SEPA payment file, those payslips are now correctly marked as paid after using the payment confirmation action. This prevents payroll records from incorrectly remaining in a validated but unpaid state after payments are generated.
Original PR description
Steps to reproduce: - Open the payment report wizard on a payslip or a pay run - Tick "Include Unpaid" and keep the extra payslips selected - Generate the SEPA file, then click "Mark as Paid" Issue: the extra payslips listed in the file stay in state "validated". Cause: mark_as_paid() paid payslip_ids, while the file is built from unpaid_payslips. Fix: pay the payslips that are actually listed in the file. Task 6428919
Customers can now use Order Again for rental products even when their cart already has a changed rental period. The system reuses the cart's existing rental dates, preventing a false conflict that previously stopped the item from being added.
Original PR description
Steps to reproduce: --- - Install the `website_sale_renting` module. - Create a rental product, place an order for it with customer as `Administrator`, and confirm the order. - Open the order preview…
Steps to reproduce: --- - Install the `website_sale_renting` module. - Create a rental product, place an order for it with customer as `Administrator`, and confirm the order. - Open the order preview and click `Order Again`. - In the cart, modify the rental period. - Go to My Account > Your Orders, open the sales order, and click `Order Again` again. Issue: --- - Clicking Order Again a second time does nothing and - The following error is logged in the terminal: `You cannot mix different rental periods in the same order.` Root cause: --- - When the user clicks `Order Again`, the `/my/orders/reorder` route calls `add_to_cart`[1], which in turn invokes `_cart_add`[2]. If no rental dates are provided, `_cart_add` computes default rental dates based on the product's rental periodicity [3]. - However, when the current cart already has a rental period set, these computed dates differ from the cart's existing rental period. As a result, the rental consistency check detects the mismatch and prevents the product from being added to the cart. Solution: --- - When the current sale order already has a rental period set, reuse those dates instead of computing default ones. This ensures the product is added using the existing cart rental period and avoids the false conflict. [1]: https://github.com/odoo/odoo/blob/bb9fcbb062887ab6b1c4c17870201d789afa9dbc/addons/website_sale/controllers/reorder.py#L63-L76 [2]: https://github.com/odoo/odoo/blob/bb9fcbb062887ab6b1c4c17870201d789afa9dbc/addons/website_sale/controllers/cart.py#L134-L141 [3]: https://github.com/odoo/enterprise/blob/a39da12a4a85d749235d59a05ebd67b91f9867b0/website_sale_renting/models/sale_order.py#L60-L64 opw-6357001 --- Forward-Port-Of: odoo/enterprise#125481
Meal voucher reports now use the original voucher value when correcting postponed vouchers from a prior period. This prevents employees or employers from being charged using a newer meal voucher amount for vouchers that were actually issued at an older value.
Original PR description
**Purpose:** -In case of postponed Meal vouchers, it may happen that the value of (patronal part + employee part) change. -Example: - June → MV amount 8 € - July → MV amount 10€ -Employee received too many MV in June because some absences where encoded after the order of the MV. -In that case, it will be postponed on July but the employee will be charged for a MV of a value of 10€ while he received meal voucher of 8€. **Proposed Solution:** -The total has been adjusted by considering the original value for _meal_voucher_amount_ in case of postponed MV.
The Belgian payroll report now uses the previous quarter's contract when a mobility budget balance is paid after the current contract no longer includes that budget. This prevents the declared amount from incorrectly showing as zero, improving payroll compliance and reporting accuracy.
Original PR description
When the mobility budget balance is paid on a contract that no longer carries a mobility budget, fall back to the previous quarter's contract to declare the correct amount instead of 0. Task-6384786 Forward-Port-Of: odoo/enterprise#127786 Forward-Port-Of: odoo/enterprise#127318
Fixed an issue where users without certain accounting permissions could be blocked from confirming sales orders when a Studio approval rule referenced a restricted related field. The approval check now runs with the right elevated access so valid approval workflows continue without unexpected access errors.
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
1 change
Resolved issues and error corrections
This fixes an issue where a person listed more than once on a signature request could be prompted to sign again before earlier signers had completed their step. Signing requests now respect the configured order, reducing mistakes and ensuring documents follow the intended approval flow.
Original PR description
### Steps to Reproduce: 1. Create a sign request and have 3 total signers (User, Customer, Employee) 2. Enable Signing Order and make the order as follows: (1) User, (2) Customer, (3) Employee But…
### Steps to Reproduce: 1. Create a sign request and have 3 total signers (User, Customer, Employee) 2. Enable Signing Order and make the order as follows: (1) User, (2) Customer, (3) Employee But make the User and Employee the same contact 3. Send and sign the request > Notice that (1) is able to sign for (3) immediately after, (2) has not signed yet. ### Description of the issue/feature this PR addresses: **Issue:** The signing order is ignored when the same user has to sign multiple times on a document, even if it is configured for a different person to sign in between. This happens because all signature request items are initialized in the 'sent' state upon creation, rather than strictly advancing based on the order. As a result, the system prematurely allows users to sign out of order and prompts them with their next turn too early. **Solution:** To resolve this, the controller was updated to include an `is_mail_sent = True` domain filter. This ensures that the UI's post-sign popup only displays documents where it is explicitly the user's active turn, rather than prompting a premature sign. ### Current behavior before PR: Users are able to sign prematurely, and the system will disregard the configured signing order. ### Desired behavior after PR: Users will only be prompted and able to sign a document when it is explicitly their turn, per the `mail_sent_order`. This way, documents are signed in order. opw-6417327