Wednesday, August 12, 2026
13 changes · master
Resolved issues and error corrections
Fixes a server error that could occur when users turned the No Follow-Up option on or off for invoices paid in multiple installments. This makes follow-up reporting more reliable when some installments are already settled and others remain open.
Original PR description
Steps to Reproduce: 1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments. 2. Create a Customer Invoice with this Payment Term. 3. Post the invoice.…
Steps to Reproduce:
1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments.
2. Create a Customer Invoice with this Payment Term.
3. Post the invoice.
4. Register a payment and fully reconcile one of the installments.
5. Navigate to the customer's Follow-Up Report (Accounting > Reporting > Partner Ledger > Report: Follow-Up Report).
6. Navigate to remaining open installment/account move line for that invoice.
7. Turn On or Off the No Follow-Up toggle for the invoice.
An error occurs when enabling or disabling the No Follow-Up toggle.
Issue:
Enabling or disabling the No Follow-Up toggle on a remaining open installment in the Follow-Up Report raises a server error when the invoice contains multiple installments and one or more installments are already fully reconciled.
Root Cause:
The Follow-Up Report only loads and sends non-fully reconciled account move lines from the JavaScript side through all_line_ids. In action_toggle_no_followup(), when the selected line belongs to an invoice, the code retrieves all receivable/payable lines of the invoice, including fully reconciled installments:
```
move.line_ids.filtered(
lambda line: line.account_type in ('asset_receivable', 'liability_payable'),
)
```
The method then attempts to map every receivable/payable line to a report line ID using aml_id_to_line_id. Since fully reconciled installments are not present in all_line_ids, they are missing from the mapping dictionary, causing a KeyError when accessing:
`aml_id_to_line_id[line.id]
`
Fix:
Restricted the impacted lines to those present in the report by adding a check that the account move line exists in aml_id_to_line_id before performing the mapping:
```
lambda line: line.account_type in ('asset_receivable', 'liability_payable')
and line.id in aml_id_to_line_id
```
opw-6245448
Forward-Port-Of: odoo/enterprise#126785
Forward-Port-Of: odoo/enterprise#126156Shifts for employees with flexible schedules and no fixed start or end times are now included consistently in Planning and Timesheets reports. This prevents planned work from being missing in analysis views, giving managers a more accurate view of allocated time.
Original PR description
## Behavior Before the PR When an employee did not have explicit `hours_from` and `hours_to` values defined, their shift was in the **Schedule by X** pivot view but was not included in the **Planning…
## Behavior Before the PR When an employee did not have explicit `hours_from` and `hours_to` values defined, their shift was in the **Schedule by X** pivot view but was not included in the **Planning / Timesheets Analysis** report. ## Steps to Reproduce 1. Create an employee with a Flexible Working Schedule in the Employee form, or configure working hours where both `Hour from` and `Hour to` are left unset. 2. Add a shift for this employee linked to a project and a task. 3. Publish the shift. 4. Navigate to **Planning → Schedule → By Project**, switch to the pivot view, and observe that the shift created in step 2 appears and is counted. 5. Navigate to **Planning → Reporting → Planning / Timesheets Analysis**, switch to the pivot view, and observe that the same shift does not appear. ## Behavior After the PR When an employee does not have explicit `hours_from` and `hours_to` values, their shift is now considered valid in both the **Schedule by X** views and the **Planning / Timesheets Analysis** report. ## Additional Notes - In earlier versions of Odoo, the `Work From` and `Work To` fields were mandatory. With a change to flexible working schedules and the option to define only the total number of hours per day, these fields may now be left empty. This change exposed the underlying issue addressed by this fix. task-[5969788](https://www.odoo.com/odoo/project/4105/tasks/5969788) Forward-Port-Of: odoo/enterprise#127300 Forward-Port-Of: odoo/enterprise#110606
Users who have both Partner Commissions access and Purchase User access can now create and view purchase orders as expected. This prevents commission-related restrictions from accidentally blocking normal purchasing work, while keeping commission-only users limited appropriately.
Original PR description
## Current behavior: The user Partner Commissions access rights as All Documents or Own Documents and Purchase access rights as User. With this configuration, the user is unable to create new…
## Current behavior: The user Partner Commissions access rights as All Documents or Own Documents and Purchase access rights as User. With this configuration, the user is unable to create new Purchase Orders, and existing Purchase Orders are also not visible in the Purchase module. ## Expected behavior: The expected behavior is that the user should be able to create and view Purchase Orders with these access rights. Additionally, clarification is required regarding the purpose of the new Partner Commissions access group. ## Steps to reproduce: - Go to user and assign Partner Commission rights as All or own document. - On Purchase, select group as User. ## Cause of the issue: partner_commission adds commission-specific purchase order record rules, but purchase users have no matching purchase-order rule in that module. For mixed-role users, the commission rule ends up restricting standard purchase orders as well. ## Fix: Apply the module's explicit all-purchase rule to purchase users so mixed users keep base procurement access while commission-only users remain restricted by the commission rules. opw-6366074 Forward-Port-Of: odoo/enterprise#127188 Forward-Port-Of: odoo/enterprise#126003
A spreadsheet sharing update was incorrectly running during every page load, sometimes disrupting navigation state in other parts of Odoo. This fix limits that behavior to spreadsheet pages only, reducing unexpected page navigation issues.
Original PR description
BUG:
To make make spreadsheet backend shareabable, a patch to the router was done, and ran on *every* page load. The code looks harmless (it already had a `if (pathParts.at(-2) !== "spreadsheet")` early return, but because of the implementation of replaceState, this we had global impact regardless.
Indeed the real problem is that `router.replaceState` routes through doPush(), which replaces `history.state` disregarding the previous history completly (with a debounce, explaining the indeterminism)
In our case the builder stored `{skipRouteChange: true}` in `history.state` which was sometimes wiped by the `replaceState` debounce
FIX:
As a quick fix (JPP is on holidays), we amend the code to make spreadsheet shareable only run if the targetted app is spreadsheet
runbot-error: https://runbot.odoo.com/odoo/error/945518
breaking PR: https://github.com/odoo/enterprise/pull/114484A spreadsheet sharing update was unintentionally affecting navigation data across the system on every page load. This fix limits that behavior to spreadsheet pages only, reducing unexpected navigation issues in other apps.
Original PR description
BUG:
To make make spreadsheet backend shareabable, a patch to the router was done, and ran on *every* page load. The code looks harmless (it already had a `if (pathParts.at(-2) !== "spreadsheet")` early return, but because of the implementation of replaceState, this we had global impact regardless.
Indeed the real problem is that `router.replaceState` routes through doPush(), which replaces `history.state` disregarding the previous history completly (with a debounce, explaining the indeterminism)
In our case the builder stored `{skipRouteChange: true}` in `history.state` which was sometimes wiped by the `replaceState` debounce
FIX:
As a quick fix (JPP is on holidays), we amend the code to make spreadsheet shareable only run if the targetted app is spreadsheet
runbot-error: https://runbot.odoo.com/odoo/error/945518
breaking PR: https://github.com/odoo/enterprise/pull/114484The payroll validation flow now correctly opens any required follow-up step, such as a wizard for missing employee information. This prevents the Validate button from appearing unresponsive and helps users understand what needs to be fixed before completing a payslip.
Original PR description
action_validate() called action_payslip_done() without returning its result. When action_payslip_done() returns a client action (e.g. a wizard to fix missing employee data instead of raising), that action was lost and the Validate button appeared to do nothing, with no error or warning shown. task-6373549
Generating public holidays now works consistently outside Belgium by applying the same automatic public holiday time type behavior to all localizations. This prevents errors when users load public holidays and improves the out-of-the-box payroll experience.
Original PR description
Purpose: generating Public Holidays fails with an error on all localizations except Belgium, preventing users from loading public holidays. This is because the Belgium localization includes a dedicated Public Holiday time type, which is automatically selected when creating public holidays. Extending this behavior to all localizations will make the feature work out of the box and provide a consistent user experience. - removed the inheritance for `load.public.holiday.wizard.line` as it's implemented generally in `hr_holidays` task-id: 6448261
Spreadsheet sharing logic now only runs when users are actually opening a spreadsheet. This prevents unrelated pages from losing navigation state, reducing intermittent page behavior and improving reliability across the app.
Original PR description
BUG:
To make make spreadsheet backend shareabable, a patch to the router was done, and ran on *every* page load. The code looks harmless (it already had a `if (pathParts.at(-2) !== "spreadsheet")` early return, but because of the implementation of replaceState, this we had global impact regardless.
Indeed the real problem is that `router.replaceState` routes through doPush(), which replaces `history.state` disregarding the previous history completly (with a debounce, explaining the indeterminism)
In our case the builder stored `{skipRouteChange: true}` in `history.state` which was sometimes wiped by the `replaceState` debounce
FIX:
As a quick fix (JPP is on holidays), we amend the code to make spreadsheet shareable only run if the targetted app is spreadsheet
runbot-error: https://runbot.odoo.com/odoo/error/945518
breaking PR: https://github.com/odoo/enterprise/pull/114484This fix prevents access errors when displaying salary offer details that depend on payroll information. It also updates the salary configurator test flow to reflect use by an HR user rather than an administrator, helping ensure the feature works for normal HR staff.
Original PR description
A field displayed inside the offer should have been computed with sudo as it accesses some payroll field to compute. Also, the salary configurator tour has been adapted to use a HR user instead of an admin Forward-Port-Of: odoo/enterprise#127510
This fix prevents users in multi-company setups from hitting an unavoidable error when creating quality-related operation steps. It ensures the default quality team works correctly with the current company, reducing blocked manufacturing or quality workflows.
Original PR description
This commit actually reverts [1] and manually forwards [2]. Suppose `mrp_workorder` installed and `quality_control` uninstalled. Because of the default value provided by [1], the only existing quality team is linked to the first company. As a result, when using another company, if the user tries to create an operation step (i.e., a QCP), it will raise an error when the onchange tries to load the default team in charge: https://github.com/odoo/enterprise/blob/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e/quality/models/quality.py#L141-L142 However, the `quality` module doesn't provide any view to create such a team. tldr The module raises an error that is actually impossible to solve... Let's avoid it in the above situation. [1] https://github.com/odoo/enterprise/commit/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e [2] https://github.com/odoo/enterprise/commit/8cd5c9322bef7db49a90d4aef844dd0ba267058e Forward-Port-Of: odoo/enterprise#127438 Forward-Port-Of: odoo/enterprise#126364
This update restores previous Studio behavior after a recent change caused runtime crashes. It keeps the intended flexibility for an optional setting while improving stability for users editing views in Studio.
Original PR description
This commit mostly reverts the commit d9d90bfd6805355909faa28dadb249c88317c2b9 which caused crashes at runtime while keeping the main fix (keeping the prop optional).
The point of sale now correctly blocks payment when an order contains only deleted items. This prevents staff from completing empty orders with no payment and issuing blank receipts.
Original PR description
The payment screen could still be accessed even if the order only contained deleted (struck through) order lines. The user can then complete the order with no payment and an empty receipt. This commit fixes the issue by updating the `isEmpty` function on the order to take the deleted lines into account.
This fixes Mexican payroll payslip CFDIs so their SAT validation status is properly checked and shown in Odoo. Businesses will now see the correct tax authority status instead of an undefined value, improving payroll compliance visibility.
Original PR description
l10n_mx_hr_payroll_account_edi introduces new l10n_mx_edi.document states (payslip_sent, payslip_sent_failed, payslip_cancel, payslip_cancel_failed) but never extends the two hooks the base l10n_mx_edi module relies on to keep sat_state in sync: - _get_update_sat_status_domains(), which builds the domain used by the SAT-status cron (and manual refresh) to pick documents to poll. Payslip states were missing from it, so their SAT status was never fetched at all. - _update_document_sat_state(), which routes a fetched SAT status to a per-source-document handler. It has no branch for the payslip states, so even a manual poll would silently do nothing. As a result, payslip CFDIs validated in the SAT always appeared as "not_defined" in Odoo. opw-6192651 Forward-Port-Of: odoo/enterprise#126294 Forward-Port-Of: odoo/enterprise#124006