Daily updates from Odoo
Monday, October 13, 2025
18 changes
1 change
Enhancements to existing features
The link editing popover now clearly shows which field or button is selected when users navigate with the keyboard. Keyboard focus also stays within the popover, making link editing more predictable and accessible.
Original PR description
Steps to Reproduce: - Select a word in the editor. - Press Ctrl + K and Enter to open the link popover. - Use the Tab key to move between the fields and buttons. Current behavior before PR: - It was not clear which field had the focus. - The border was always overridden by the `border-dark-subtle` class with `!important`, so users had no visual feedback when tabbing. - When tabbing, focus could escape the link popover instead of looping inside it. Desired behavior after PR is merged: - Inputs and selects now use the correct border color on focus, aslo discard button changes opacity when focused. - The link popover traps focus: pressing Tab/Shift+Tab will cycle through focusable elements without leaving the popover. task-4965566 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
1 change
Enhancements to existing features
UAE payroll now excludes unpaid leave, unpaid sick leave, and out-of-contract days from end-of-service and provision salary rule calculations. End-of-service payslips also show the total unpaid leave days, improving transparency and accuracy for payroll teams.
Original PR description
This commit excludes the Out Of Contract Unpaid Leaves and Unpaid Sick Leave days from the EoS and EoS Provision Salary Rule Calculations. We also show the total number of unpaid leave days on the EoS payslip. task-4886104 Forward-Port-Of: odoo/enterprise#96681 Forward-Port-Of: odoo/enterprise#95465
2 changes
Enhancements to existing features
Unpaid leave and unpaid sick leave days are now excluded from UAE end-of-service and provision salary calculations, making payroll results more accurate. End-of-service payslips also display the total unpaid leave days for clearer employee and HR review.
Original PR description
This commit excludes the Out Of Contract Unpaid Leaves and Unpaid Sick Leave days from the EoS and EoS Provision Salary Rule Calculations. We also show the total number of unpaid leave days on the EoS payslip. task-4886104 Forward-Port-Of: odoo/enterprise#95465
Paired IoT Boxes will now always connect to the database IoT communication channel, instead of checking whether that channel is marked open or closed. This makes the behavior easier to understand and helps teams troubleshoot connection issues more consistently.
Original PR description
In order to simplify debugging and UX, we removed the open/closed WebSocket logic for IoT Boxes. A paired IoT Box should always connect to the db IoT WebSocket channel. Forward-Port-Of: odoo/enterprise#96822
9 changes
Enhancements to existing features
Payroll now shows clearer warnings and errors on payslips, helping payroll teams understand and resolve salary issues faster. Missing bank account information is treated more seriously when payroll accounting is enabled, reducing the risk of payment problems during pay runs.
Original PR description
Improved issues shown in payslip warnings and errors, fixed multiple tracebacks and errors related to the new issues system with payruns and payslips Task: 5065090
The Documents app now offers Duplicate and Move actions directly from the left-side cog menu, making common folder management tasks easier to find. The shortcut option is also available in more appropriate places while respecting user permissions and excluding special areas such as Company, Recent, and Trash.
Original PR description
- This commit adds the `Duplicate` and `Move` options on the left cog wheel. - Adapt the conditions for the `Add to shortcut` so that it is available in the cog menu, except for folders which already have a shortcut, moved used `DocumentsCogMenuItemOperation` for `DocumentsCogMenuItemShortcut` to avoid code duplication. - These options will not be there when the user lacks access, and for special roots like `All Company, Recent, Trash ... Task-4949092
The Belgian payroll reporting menu has been cleaned up by removing several specialized options from the main menu. Work entry exports are still available from the Work Entry cogwheel when relevant, making the interface less cluttered while keeping export actions accessible in the right context.
Original PR description
removed the menu items: Meal Vouchers, Export Work Entry Types, and Departure: Notice Period & Holiday Attests from the top menu bar but added the Export Work entry types to the cogwheel inside the work entry with some limitations such as to appear only when: - The company is in Belgium (country code: BE). - The Work Entry page (not the employees page for example). - With all views (e.g. list, grantt, ...etc.) but the form view. - We have any of the export types installed, such as the group_s, ucm, sd_worx... etc. task-5005925
UAE payroll now handles all sick leave types through a single salary rule instead of separate rules for each type. This simplifies payroll configuration and accounting setup while keeping sick leave calculations consistent.
Original PR description
Originally, each sick leave in the UAE's localization has its own salary rule. The logic for all the sick leave types has been grouped into one salary rule.
Overtime rules can now be created without automatically linking them to a work entry type. When a work entry type is selected, the overtime rate is controlled by that type and cannot be manually changed, helping keep payroll calculations consistent.
Original PR description
If Work Entry module is installed --> Make the rate readonly within the form view of the attendance overtime rule. changes: - work_entry_type is not required anymore on ot (overtime) rules. - ot rules won't be assigned a default work_entry_type. - if there's no work_entry_type assigned on the ot rule, the user can manually edit the rate. - if there's a work_entry_type, the rate becomes readonly within the view and computed from the work entry type. Task-5107738
Indonesian payroll now calculates net salary and taxes more accurately by including company contributions, employee-specific payslip data, and updated statutory rounding rules. The update also adds a fixed allowance salary rule and improves tests to help ensure payslip results match local payroll requirements.
Original PR description
* Update the calculation of net salary in indo localization to use company contribution category too * Update the domain search for searching gross / pph21 yearly so it search only the current employee's payslip * Move Biaya Jabatan threshold rule to apply after the calculation instead of before (to follow the rules of 500.000 / payslip(month)) * Add rounding to pph21(round half up) and PKP (round down to nearest thousand) * Add new salary rule (Fixed Allowance) * Fix and add new unit test Task: 4967867
Indian payroll reports now present salary figures more clearly with better alignment, currency symbols, and improved ordering of key totals. The salary statement also corrects the Cost to Company amount so it reflects the actual wage, while the yearly salary report is easier to use with the current year selected by default and years shown newest first.
Original PR description
- Salary Register Report: - Aligned character fields to the left and number fields to the right - Salary Statement Report: - Aligned all amount fields to the right and added currency symbols - Moved 'Net Salary' field before 'Cost to Company' and made it bold - Corrected 'Cost to Company' amount to reflect actual wage - Labor Welfare Fund Report: - Aligned amounts to the right and added currency symbols - Yearly Salary by Employee Report: - Set current year as default in the wizard - Displayed years in descending order - Aligned month name to the left in the generated PDF task-5026145
Belgian payroll users can now manage Group Insurance Exports through standard list and form screens instead of a temporary wizard. This makes the process more consistent with other payroll exports and improves maintainability across payroll export providers.
Original PR description
In this PR we: - Converted the Group Insurance Export from a wizard-based flow into standard list and form views. - Extracted common fields and views from both Group Insurance Export and HR Work Entry Export mixin into a new hr.export.mixin - Updated Group Insurance Export and HR Work Entry Export to inherit from hr.export.mixin and override their views. Related task: 5010866.
Users are now notified as soon as their payment initiation is activated, instead of waiting for the next account synchronization. This reduces delays in communicating activation status and adds test coverage for the payment verification flow.
Original PR description
Before this we sent activation emails when synchronizing accounts, this could cause a delay for the users knowing when their payment initiation was activated. Now, we send it as soon as we receive the webhook from Odoofin. This commit also adds tests for the KYC flow. Part of: 4487895 Forward-Port-Of: odoo/enterprise#93971
3 changes
Enhancements to existing features
Peppol UBL electronic invoices now include the delivery party in the delivery information. This makes exported invoices clearer for recipients by showing who the delivery is for, using the shipping contact when available or the customer name otherwise.
Original PR description
Previously, the Peppol UBL export only covered the mandatory delivery fields and did not include the `delivery party`. This commit adds the `<cac:DeliveryParty>` element under `<cac:Delivery>` to improve the exported information. - Include `<cac:DeliveryParty>` in the `<cac:Delivery>` section of UBL invoices. - Use the shipping partner name if set; otherwise, fallback to the customer name - Keep existing `<cac:DeliveryLocation>` and delivery date logic unchanged. <img width="766" height="306" alt="image" src="https://github.com/user-attachments/assets/d07c1b37-4c6d-42d1-99b4-66c5abc8e298" /> ----- task-5022404 Forward-Port-Of: odoo/odoo#230468 Forward-Port-Of: odoo/odoo#223756
Users are now notified as soon as their payment initiation is activated, instead of waiting for the next account synchronization. This reduces delays and improves visibility in the online payment setup process, with added tests covering the verification flow.
Original PR description
Before this we sent activation emails when synchronizing accounts, this could cause a delay for the users knowing when their payment initiation was activated. Now, we send it as soon as we receive the webhook from Odoofin. This commit also adds tests for the KYC flow. Part of: 4487895
Payment terminals connected through the IoT Box now use the same communication service as other IoT actions. This enables additional connection methods such as WebRTC and WebSocket, improving reliability and flexibility beyond long polling.
Original PR description
As for any other actions sent from the db to the IoT Box, we updated payments terminals logic to use the `iot_http` service in order to allow them using webrtc and websocket in addition to longpolling. odoo/odoo#230970
1 change
Enhancements to existing features
The Inventory replenishment view now calculates quantities in batches instead of one item at a time. This reduces repeated database work and makes the replenishment action open much faster for users managing many products.
Original PR description
Go to menu -> Inventory -> Operations -> Procurement -> Replenishment It is slow opening this action Notice this menu is similar to call the following action: ```python…
Go to menu -> Inventory -> Operations -> Procurement -> Replenishment
It is slow opening this action
Notice this menu is similar to call the following action:
```python
self.env.ref("stock.action_replenishment").run()
```
I got profilers and I have noticed the slow part is the following kind of queries:
<details>
<summary>Query</summary>
```sql
select
"purchase_order_line"."order_id",
"purchase_order_line"."product_id",
"purchase_order_line"."product_uom",
"purchase_order_line"."orderpoint_id",
"purchase_order_line"."location_final_id",
sum(
"purchase_order_line"."product_qty"
)
from
"purchase_order_line"
where
(
(
(
"purchase_order_line"."state" in (...)
)
and (
"purchase_order_line"."product_id" in (...)
)
)
and (
(
(
(
"purchase_order_line"."id" not in (
select
"stock_move"."purchase_line_id"
from
"stock_move"
where
"stock_move"."purchase_line_id" is not null
)
)
and (
"purchase_order_line"."location_final_id" in (
select
"stock_location"."id"
from
"stock_location"
where
(
"stock_location"."parent_path" like ?
)
)
)
)
or (
not exists (
select
?
from
"stock_move_created_purchase_line_rel" AS "purchase_order_line__move_dest_ids"
where
"purchase_order_line__move_dest_ids"."created_purchase_line_id" = "purchase_order_line"."id"
)
and (
"purchase_order_line"."orderpoint_id" in (
select
"stock_warehouse_orderpoint"."id"
from
"stock_warehouse_orderpoint"
where
(
"stock_warehouse_orderpoint"."location_id" in (...)
)
)
)
)
)
or (
"purchase_order_line"."order_id" in (
select
"purchase_order"."id"
from
"purchase_order"
where
(
"purchase_order"."picking_type_id" in (
select
"stock_picking_type"."id"
from
"stock_picking_type"
where
(
"stock_picking_type"."default_location_dest_id" in (...)
)
)
)
)
)
)
)
group by
"purchase_order_line"."order_id",
"purchase_order_line"."product_id",
"purchase_order_line"."product_uom",
"purchase_order_line"."orderpoint_id",
"purchase_order_line"."location_final_id"
order by
"purchase_order_line"."order_id" asc,
"purchase_order_line"."product_id" asc,
"purchase_order_line"."product_uom" asc,
"purchase_order_line"."orderpoint_id" asc,
"purchase_order_line"."location_final_id" asc
```
</details>
It is called 1.5k times ~35ms average duration
It sums ~1 minute
The code generating this query is the following "_compute_qty_to_order_computed" method:
https://github.com/odoo/odoo/blob/4baf55a5d108063b0b60beddf332b6ae367f1871/addons/stock/models/stock_orderpoint.py#L353
I have noticed the method `_quantity_in_progress` is called record by record without cache or prefetch to re-use the same query with multiple records
It is important to group-by location_id since that the query is filtering by "stock_location.parent_path" and it could combine results wrong
The profiler results are
Total time: 123.646 s
File: /home/odoo/instance/odoo/addons/stock/models/stock_orderpoint.py
Function: _compute_qty_to_order_computed at line 357
Line # Hits Time Per Hit % Time Line Contents
==============================================================
357 @api.depends('qty_multiple', 'qty_forecast', 'product_min_qty', 'product_max_qty', 'visibility_days')
358 @profile
359 def _compute_qty_to_order_computed(self):
360 1429 10722.3 7.5 0.0 for orderpoint in self:
361 1426 56357.7 39.5 0.0 if not orderpoint.product_id or not orderpoint.location_id:
362 orderpoint.qty_to_order_computed = False
363 continue
364 1426 123579332.8 86661.5 99.9 orderpoint.qty_to_order_computed = orderpoint._get_qty_to_order(qty_in_progress_by_orderpoint=orderpoint._quantity_in_progress())
Changing the method to use multi advantages the profiler result is
```txt
Total time: 31.7207 s
File: odoo/addons/stock/models/stock_orderpoint.py
Function: _compute_qty_to_order_computed at line 347
Line # Hits Time Per Hit % Time Line Contents
==============================================================
347 @api.depends('qty_multiple', 'qty_forecast
', 'product_min_qty', 'product_max_qty', 'visibility_days')
348 @profile
349 def _compute_qty_to_order_computed(self):
350 6 22373.3 3728.9 0.1 records = groupby(
351 3 68436.0 22812.0 0.2 sorted(self.filtered(lambda o: o.p
roduct_id and o.location_id), key=lambda o: o.location_id),
352 3 6.5 2.2 0.0 lambda o: o.location_id)
353 3 4.0 1.3 0.0 qty_in_progress_by_orderpoint = {}
354 32 99.2 3.1 0.0 for _location, orderpoints in records:
355 1455 2447053.1 1681.8 7.7 qty_in_progress_by_orderpoint.upda
te(self.browse([op.id for op in orderpoints])._quantity_in_progress())
356 1429 6515.8 4.6 0.0 for orderpoint in self:
357 1426 29176220.5 20460.2 92.0 orderpoint.qty_to_order_computed =
orderpoint._get_qty_to_order(qty_in_progress_by_orderpoint=qty_in_progress_by_orderpoint)
```
This way is ~3.5x faster
The query generated changed from:
"purchase_order_line"."product_id" in {only one id}
to:
"purchase_order_line"."product_id" in {many ids}
Reducing the calls from ~1.5k to only 0.1k
and the total duration reduced from ~1 minute to only ~3 seconds
Also, the validation
if not orderpoint.product_id or not orderpoint.location_id:
It is already considered from the method `_get_qty_to_order`
https://github.com/odoo/odoo/blob/5071c52bdae637dfc1292602a5dda2bf650e5abd/addons/stock/models/stock_orderpoint.py#L357-L358
So, removing this duplicated validation
Screenshots of the results:
- 
Code before of this commit:
- <img width="1507" alt="Screenshot 2025-05-16 at 1 17 36 p m" src="https://github.com/user-attachments/assets/368270d9-534b-475f-af27-a81eb02e6ecb" />
Code after of this commit:
- <img width="1507" alt="Screenshot 2025-05-16 at 1 21 16 p m" src="https://github.com/user-attachments/assets/11498d2a-fe53-49b5-a82e-bfc504dbfe05" />
UPDATED: for record I have ran the following methods
```python
# one by one
orderpoints = self.env["stock.warehouse.orderpoint"].search([("product_id", "!=", False), ("location_id", "!=", False)], order='id')
for orderpoint in orderpoints:
qty_in_progress_by_orderpoint = orderpoint._quantity_in_progress()
for (id, qty) in sorted(qty_in_progress_by_orderpoint.items()):
if not qty:
continue
print(f"{id}:{qty},")
```
and
```python
# multi in one shot
orderpoints = self.env["stock.warehouse.orderpoint"].search([("product_id", "!=", False), ("location_id", "!=", False)], order='id')
qty_in_progress_by_orderpoint = orderpoints._quantity_in_progress()
for (id, qty) in sorted(qty_in_progress_by_orderpoint.items()):
if not qty:
continue
print(f"{id}:{qty},")
```
And the result output for both codes are the same
UPDATED: Odoo is working on https://github.com/odoo/odoo/pull/2131541 change
Enhancements to existing features
This update lets Odoo resize image files before they are uploaded. It helps reduce database storage growth and can make image uploads more efficient for users working with customizations or file inputs.
Original PR description
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