Friday, August 14, 2026
8 changes · saas-19.4
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
Budget reports now load much faster for databases with many analytic lines and budget lines. The report matching logic was reorganized to avoid excessive comparisons, reducing a sample load time from nearly a minute to about one second.
Original PR description
**Description:** While loading the budget report, the bad queries are created by ```def _get_aal_query()``` and ```def _get_pol_query()``` function, makes the budget report unusable. **Root cause:**…
**Description:**
While loading the budget report, the bad queries are created by
```def _get_aal_query()``` and ```def _get_pol_query()``` function, makes
the budget report unusable.
**Root cause:**
Instead of doing a hash join while searching the record,
the OR statement in the Left Join in the condition
```(%(bl)s IS NULL OR %(a)s = %(bl)s)```
creates a nested for loop that compares everything single aal to bl,
this causes a significant performance issue as the number of the
number of check will be the the number aal * bl,
if a database has a 70k aal and 20k bl, both numbers are not large
but it will cause a 70k * 20k search which is more than a billion.
**Fix**:
There are some refactors made in this PR.
_First_, separate out the Q1.
In order to find the aal that has no bl connects to it.
Doing a search to find the aals that have bl and then subtract them from all aals.
_Second_, Instead of doing a nested loop for by using
```(%(bl)s IS NULL OR %(a)s = %(bl)s)```,
originally we will have do something like
```
JOIN budget_line bl
ON (bl.x_plan2_id IS NULL OR aal.x_plan2_id = bl.x_plan2_id)
AND (bl.x_plan3_id IS NULL OR aal.x_plan3_id = bl.x_plan3_id)
AND (bl.x_plan4_id IS NULL OR aal.x_plan4_id = bl.x_plan4_id)
```
Assuming each bl has three plans ```x_plan2_id```, ```x_plan3_id```, ```x_plan4_id```
Grouping the bl base on whether a specific plan is set, (i.e. shapes)
we can skip the ```IS NULL OR``` because we already know which plan
is null and do the hash join directly.
For example, the shapes will be a dictionary with a key of a tuple of booleans
based on whether a plan is set or not and the value is a list of bl_id.
```
{
(True, False, False): [1, 2],
(False, True, True): [3, 4],
(False, False, False): [5],
}
```
we can end up doing something like
```
JOIN budget_line bl
ON bl.id = ANY(ARRAY[3,4])
AND aal.x_plan3_id = bl.x_plan3_id AND aal.x_plan4_id = bl.x_plan4_id
```
which is way more faster.
---
The benchmark is made locally from this client's database which contains
69k aal, 23k bl, 6829 pol and 3 plans for aal and bl.
|Record count |Time before|Time after|
|--------------------------------------------------|-----------------|---------------|
|69k aal, 23k bl, 6829 pol, 3 plans |70.04s |4.6s |
Dalibo:
Before:
Month-over-month grand total by company:
https://explain.dalibo.com/plan/8h3d4e89aaf9f3d4
Overall grand total by company:
https://explain.dalibo.com/plan/445g1f9caf4923e2
Month-over-month grand total by plan:
https://explain.dalibo.com/plan/53a138ca50b2a7c4
Overall grand total by plan:
https://explain.dalibo.com/plan/hdbe169ddc7g5785
After:
Month-over-month grand total by company:
https://explain.dalibo.com/plan/hcc86c801e6872bf
Overall grand total by company:
https://explain.dalibo.com/plan/69b2421a3581f98h
Month-over-month grand total by plan:
https://explain.dalibo.com/plan/a88f398bbbch3148
Overall grand total by plan:
https://explain.dalibo.com/plan/1gg749ae7ab1553c
opw-6345552
Forward-Port-Of: odoo/enterprise#127732
Forward-Port-Of: odoo/enterprise#124161Timesheet 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
Currently all of our iot boxes are updated on mondays. This PR adds the dynamic selection of the update day of the week based on the rpi serial number. This allows our iot boxes not to be updated all at the same time, reducing the risk of introducing bugs for our clients all at the same time. Related: https://github.com/odoo/odoo/pull/278914 Forward-Port-Of: odoo/odoo#280317 Forward-Port-Of: odoo/odoo#278661
Original PR description
Currently all of our iot boxes are updated on mondays. This PR adds the dynamic selection of the update day of the week based on the rpi serial number. This allows our iot boxes not to be updated all at the same time, reducing the risk of introducing bugs for our clients all at the same time. Related: https://github.com/odoo/odoo/pull/278914 Forward-Port-Of: odoo/odoo#280317 Forward-Port-Of: odoo/odoo#278661
Steps to reproduce: 0. Link a Stripe terminal to a payment method and add the payment method to a kiosk pos.config 1. Select products and initiate payment 3. Stripe error - TypeError: Cannot set properties of undefined(setting 'stripecardpresentnetwork') Paymentline uiState is never initialized because pos_stripe/static/src/overrides/models/pos_payment.js is missing from the payment_terminals bundles and is therefore never loaded in kiosk mode. This commit ensures that the file is loaded
Original PR description
Steps to reproduce: 0. Link a Stripe terminal to a payment method and add the payment method to a kiosk pos.config 1. Select products and initiate payment 3. Stripe error - TypeError: Cannot set properties of undefined(setting 'stripecardpresentnetwork') Paymentline uiState is never initialized because pos_stripe/static/src/overrides/models/pos_payment.js is missing from the payment_terminals bundles and is therefore never loaded in kiosk mode. This commit ensures that the file is loaded and that the PosPayment setup() is completed. opw-6419140 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282049
Task: 6442237 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280219
Original PR description
Task: 6442237 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280219