Thursday, August 6, 2026
11 changes · saas-19.1
Enhancements to existing features
Bank synchronization now recognizes advisory errors from Odoofin that should not interrupt the connection. This helps avoid unnecessarily marking bank links as failed when the issue does not block synchronization.
Original PR description
Odoofin now sends a 'non_blocking_error' error response to indicate that the state on account.online.link shouldn't be set to error. In this commit, we start using it. Task ID: 6358809 Forward-Port-Of: odoo/enterprise#126737 Forward-Port-Of: odoo/enterprise#123287
Odoo now checks whether a payment or batch payment exceeds the maximum amount allowed by the connected financial institution before trying to process it. This helps prevent failed payment attempts and gives businesses earlier warning when a bank-imposed limit applies.
Original PR description
Before trying to initiate payments through Odoo/Odoofin, we should check that the total amount for the (batch) payment does not exceed the maximum payment amount allowed by the institution (some Powens institutions introduced that limit). task-6310729 Forward-Port-Of: odoo/enterprise#126699 Forward-Port-Of: odoo/enterprise#121513
Resolved issues and error corrections
Online orders from UrbanPiper now calculate the price per item correctly when taxes are included and customers order more than one unit. This prevents inflated POS order totals and helps ensure accurate billing, receipts, and sales reporting.
Original PR description
Steps to reproduce: --- - Configure a Point of Sale with UrbanPiper credentials. - Create a product priced at 100 with a 5% GST (Tax Included). - Sync the product with UrbanPiper. - Place an online order with a quantity greater than 1. Issue: --- - `total_with_tax` was incorrectly treated as the unit price for multi-quantity tax-included orders. Fix: --- - Calculate the unit price by dividing `total_with_tax` by the ordered quantity before creating the POS order line. task-6427634 Forward-Port-Of: odoo/enterprise#126723 Forward-Port-Of: odoo/enterprise#125989
This fixes an issue where clicking a financial report line repeatedly while it was loading could create duplicate expanded rows. Reports now ignore extra rapid clicks during loading, so users can expand and collapse lines reliably even on slower connections.
Original PR description
Steps to reproduce:- - Open any report. - Click on a particular line to unfold more than once very fast(or throttle network to 3G) - Once line is unfolded click again to fold that line. - Line is not…
Steps to reproduce:- - Open any report. - Click on a particular line to unfold more than once very fast(or throttle network to 3G) - Once line is unfolded click again to fold that line. - Line is not folding. Cause:- - When we clicked multiple times to unfold line, duplicate child lines were created(as many times as many times we clicked). - Because when first promise was not resolved so `unfolded = false` and we clicked again so new promise also tries to unfold the same line, resulting in unfolding the same line multiple times. - In version 17.0 these duplicate child lines are created but somehow not visible but it breaks `foldLine`. From version 18.0 onwards these duplicate child lines are visible. Solution: In `unfoldLine` set the flag `unfolding`. So in all clicks other than first, we get `unfolding = true` and don't proceed further, preventing unfolding the same line multiple times. task-6260425 Forward-Port-Of: odoo/enterprise#126765 Forward-Port-Of: odoo/enterprise#120392
Planning slots for employees without a fixed working schedule now appear in the Timesheet/Planning Analysis report. This ensures reporting is complete for teams using fully flexible work arrangements and avoids missing planned work in analysis.
Original PR description
Steps to reproduce: ------------------- 1. Install project_timesheet_forecast. 2. Create a fully flexible employee (without a working schedule). 3. Create a planning slot. 4. Open the Timesheet/planning Analysis report. Issue: ------ Planning slots for fully flexible employees are not included in the report. Cause: ------ https://github.com/odoo/enterprise/blob/7d4b43cfa1934856d41992cbe8242eaf62575c2c/project_timesheet_forecast/report/timesheet_forecast_report.py#L142-L161 The report assumes every resource has a working schedule and only considers resources with a resource calendar. As a result, resources without a calendar are excluded from the report. Solution: --------- Handle resources without a working schedule separately so that planning slots for fully flexible employees are also included in the report. opw-6361571 Forward-Port-Of: odoo/enterprise#126682 Forward-Port-Of: odoo/enterprise#125072
This fix prevents Odoo Studio from crashing when users edit fields that are added dynamically in specific accounting and Dutch reporting views. Instead of showing an error, Studio now handles the situation gracefully and hides technical-only fields that should not be edited.
Original PR description
* = account_invoice_extract, l10n_nl_reports Example of steps: - Install web_studio and `accountant` - Open the corresponding form view in Studio - With debug mode toggle "Show invisible Elements"…
* = account_invoice_extract, l10n_nl_reports Example of steps: - Install web_studio and `accountant` - Open the corresponding form view in Studio - With debug mode toggle "Show invisible Elements" and edit "Invisible" on the second partner_id field - Traceback `normalize()` compares the combined arch without the studio customization to the one with it, in order to compute the smallest possible set of xpaths. To do so, it calls `apply_inheritance_specs` (the low-level function from `odoo.tools.template_inheritance`) directly on the statically combined arch. Some models add or duplicate nodes dynamically in `_get_view()` (Python postprocessing, run after the static view combination). A studio operation can target such a node, since it is what the user actually sees and clicks on. But that node has no counterpart in the purely static combined arch used by `normalize()`, so `apply_inheritance_specs` raises a ValueError. `edit_view()` only catches `ValidationError` to fall back to an un-optimized (but valid) studio arch instead of failing the request. Since the low-level function raises a plain `ValueError` here, that fallback never triggers, and the exception is not caught anywhere. To fix this, we will keep the behavior from version 18.0 and catch the ValueError raised by `apply_inheritance_specs` in `normalize_with_keyed_tree` and re-raise it as a ValidationError, like `ir.ui.view.apply_inheritance_specs` already does elsewhere. This lets `edit_view()`'s existing fallback handle the case gracefully instead of crashing. Additionally, the two models responsible for the dynamically-added nodes described above are fixed at the source. `account_invoice_extract`'s duplicated `partner_id` field and `l10n_nl_reports`'s injected `company_id` field are now marked with `data-used-by`, the same attribute `_add_missing_fields` already sets in `ir_ui_view.py` for the fields it adds. Studio already skip rendering and computing xpaths for any node carrying this attribute (since https://github.com/odoo/enterprise/pull/92862), so these nodes are no longer exposed to the user and can no longer produce a studio operation that `normalize()` is unable to locate. opw-6332911 Forward-Port-Of: odoo/enterprise#122829
This fixes a crash that could happen when approval requests in approved or refused states were linked through a custom Studio field and a form recalculated values. Users can now continue editing affected forms without interruption, and tests now cover all approval request states.
Original PR description
**Before this change** We have the potential to attempt to send a notification email from virtual records created by our `BaseModel.new()` method. This can happen during an `onchange` request, given…
**Before this change** We have the potential to attempt to send a notification email from virtual records created by our `BaseModel.new()` method. This can happen during an `onchange` request, given that we'll be working with a virtual "snapshot" record to recompute potentially changed values for our origin record after a change to one or more values. This issue manifests when using Studio to attach a many2many field to a form view, where the related model is "Approval Request". If an approval request record in either the "Approved" or "Refused" state is attached to our record via this new Studio field, any `onchange` requests will trigger this bug. This is because we can't send messages on a virtual record. **After this change** Prevent the creation and sending of a message if we are computing the request status of a virtual `approval.request()` record. The field `request_status` on this model is computed and stored, but the fact that it is a computed field means that it must be recomputed for a virtual record, even if the origin record already has a stored `request_status`. Thus, we may need to compute a `request_status` value for an ephemeral "snapshot" record. Though the issue only manifests for the "Approved" and "Refused" states, this PR expands on a test that covers every approval request state. opw-6390453 Forward-Port-Of: odoo/enterprise#125374
This fixes an issue that could stop bulk product imports when subscription-related settings were changed. Restoring the missing logic helps businesses update product catalogs reliably without import errors.
Original PR description
The port https://github.com/odoo/enterprise/commit/68640b5bddf51a8cbf58d3af3628cd4b57e08913 added a call to self._get_confirmed_order_lines() in product.template.write() (on import, when recurring_invoice changes), but the helper itself was never ported to 19.0. Importing products in bulk then fails with AttributeError: 'product.template' object has no attribute '_get_confirmed_order_lines'. Restores the method from master (PR https://github.com/odoo/enterprise/pull/117046) at the end of the ProductTemplate class. Forward-Port-Of: odoo/enterprise#122146
Changing a payslip to a payroll structure that does not use worked day lines now clears old worked day data instead of leaving misleading information behind. Belgian payroll reporting was also adjusted so off-cycle payslips without worked day lines still include the correct remuneration amounts in DMFA reports.
Original PR description
hr_payroll: Previously, changing to a structure with `use_worked_day_lines = False` (e.g., 13th month) caused `valid_slips` to be empty and return early, leaving stale worked day lines on the payslip. This commit resets the worked_days_lines before filtering for valid payslips. l10n_be_hr_payroll: After fixing the payroll bug and clearing worked_days_lines correctly, the DMFA report fails to correctly consider remunerations since the off-cycle payslips do not have worked_days_lines anymore. This commit backports a fix from odoo/enterprise#106689 to not skip remunerations for payslips with no worked days lines. task-6401942 Forward-Port-Of: odoo/enterprise#124986
Users can now revoke a Belgian CodaBox connection using either the fiduciary password or a valid IAP token. This fixes a client-side gap so the revocation process works as already supported by the server.
Original PR description
The user should be able to revoke the CodaBox connection by either entering the fidu password or by using a valid iap_token. This was implemented in the iap server but not in the client side, after this commit the user should be able to either revoke by using the fidu password or by using the iap_token. task-6348433 Forward-Port-Of: odoo/enterprise#126698
Users can now be re-invited to a shared Documents folder after their previous access expired. This prevents misleading success messages and ensures portal users regain access when invited again.
Original PR description
Sharing a folder with a portal user with an expiration date cannot be done again after the access has expired. The sharing dialog reports success, but the user does not get access and is no longer…
Sharing a folder with a portal user with an expiration date cannot be done again after the access has expired. The sharing dialog reports success, but the user does not get access and is no longer listed. ### Steps to reproduce - In Documents, share a folder with a portal user and set an expiration date. - Wait until the expiration date has passed. - Share the same folder with the same user again from the invite box. => The dialog says the member was added, but the user has no access and does not appear under "People with access". ### Cause The invite box has no expiration field. When re-inviting a user, it updates the existing `documents.access` record and passes `None` for the expiration, which keeps the old `expiration_date`. If that date is already in the past, the user remains expired even though the invite reports success. ### Fix Pass `False` instead of `None` when inviting a member so the existing record's expiration date is cleared. Re-inviting an expired user now restores access. Setting an expiration from the "People with access" list is unchanged. opw-6387559 Forward-Port-Of: odoo/enterprise#125140