Daily updates from Odoo
Monday, June 22, 2026
7 changes · 19.0
Enhancements to existing features
This update allows administrators to control when payslip PDFs are generated and emailed to employees – options include automatic delivery on validation or payment, or manual delivery. Previously, this setting was managed differently, requiring a migration script. This change simplifies management and avoids disruption for existing users.
Original PR description
Backport of odoo/enterprise#97957 adapted for stable 19.0 policy.
This commit adds a global setting that controls when payslip PDFs are generated and emailed to employees: on validation, on payment, or never (manual). The three modes are exposed in Payroll settings.
Difference from 19.1: the trigger is stored in ir.config_parameter ('hr_payroll.payslip_generate_and_send_trigger') instead of a new column on res.company, avoiding any migration script. When the parameter is absent the behaviour falls back to 'on_confirmed', preserving the existing behaviour for all current installations.
task-6268644Resolved issues and error corrections
This update resolves an issue where DIAN XML files were being rejected due to incorrect calculations of prepaid payments. The fix combines payment amounts into a single tag, ensuring accurate totals and preventing negative payment lines that triggered errors with the DIAN API. This ensures proper reporting and compliance for Colombian Point of Sale transactions.
Original PR description
**Steps to reproduce:** To test this, you will need an official DIAN setup, because this error comes from the response to our API call to the DIAN. - Setup the DIAN in a colombian company - Open the…
**Steps to reproduce:** To test this, you will need an official DIAN setup, because this error comes from the response to our API call to the DIAN. - Setup the DIAN in a colombian company - Open the PoS - Order a product - Before paying, make the amount we are paying bigger than the amount due - We get an error response from the API, the error is saying that the total due does not match what we paid **Why the fix:** Currently, the xml is rejected because the sum of the **PaidAmount** in the **PrepaidPayment** tag is not equal to what we are trying to pay for. This is happening because to avoid the fact that we can not send a line with negative amount, we used the **abs()** function on the line amount to make it positive. The negative line comes from the fact that when we have a total due that is below the amount paid, we create a new payment line with a negative amount to balance it out. But as we can't send lines with negative amount, we needed to make it positive. This does not work, as the sum of the lines' amount will then be too much compared to what we are paying for, because instead of substracting it we will be adding it. To avoid this, we now group the amount in one single tag and send it this way. This ensures that the sent amount is correct and equals the amount due, and does not send a negative line. opw-6232575 Forward-Port-Of: odoo/enterprise#121075 Forward-Port-Of: odoo/enterprise#119255
This update resolves an issue where changes to roles within duplicated sign templates were unintentionally reflected across all instances. By copying the role data when duplicating a sign item, each template now has its own independent roles, ensuring data consistency and preventing conflicts.
Original PR description
When duplicating a sign template, its sign items were copied but their `responsible_id` was kept as a reference to the same `sign.item.role` records. As a result, editing a role on one template (e.g. assigning a partner through `assign_to`) leaked to the other template sharing it. Copy the role when copying a sign item so each template owns its own roles. task-6288951
This update removes an unnecessary 'external' tag from the SendCloud delivery module's tests. Previously, errors were only detected during nightly builds, not by the standard Continuous Integration process. Removing the tag now ensures all tests run correctly and efficiently.
Original PR description
Test class was tagged as external although calls are mocked. This means errors were only caught in nightly and not by CI. Removing the tag requires fixing some of the tests. For `test_multicollo`, we send the average weight of packages instead of the total since 97f82442c9fee7dcb3e8c5e9bacddcd6bb864e11. Forward-Port-Of: odoo/enterprise#118386 Forward-Port-Of: odoo/enterprise#111660
This update significantly speeds up the loading of large General Ledger reports by optimizing how display names are retrieved. Previously, the system loaded unnecessary data, leading to slow performance. Now, a single fetch call efficiently retrieves only the required display name information, dramatically reducing memory usage and improving loading times.
Original PR description
### Issue Loading a large General Ledger (e.g., during an "Unfold All" action) and retrieving display names for thousands of journal lines (`account.move.line`) causes excessive memory and…
### Issue Loading a large General Ledger (e.g., during an "Unfold All" action) and retrieving display names for thousands of journal lines (`account.move.line`) causes excessive memory and performance overhead. Profiling with `memray` showed that one of the main memory hotspots was located in `custom_label_builder`. **Previous behavior:** Accessing `record.display_name` in a loop without an explicit `fetch()` call triggered lazy computation of the field via `_compute_display_name()`. When the compute method accessed stored dependency fields (such as `name`, `ref`, `move_id`), each cache miss went through `_fetch_field()`, which greedily loaded **all fields sharing the same prefetch group** on the model, far beyond the dependencies of `display_name` alone. This caused the ORM cache to be filled with many unnecessary stored fields for every record in the prefetch set. --- ### Dataset Volume The performance metrics were captured using a dataset consisting of: * **455,694** Journal Items (`account.move.line`) * **19,947** Journal Entries (`account.move`) --- ### Solution Add a single `fetch(['display_name'])` call on the browsed recordset. By calling `fetch(['display_name'])` upfront, the ORM goes through `_determine_fields_to_fetch(['display_name'])`, which walks only the declared `field_depends` of `display_name` and fetches **only those specific stored fields**. nothing more. --- ### Impact & Results | Metric | Before Optimization | After Optimization | Change / Note | | :--- | :--- | :--- | :--- | | **Peak Memory** | ~856 MB | ~223 MB | ~74% reduction | | **Execution Time** | 2.48s | 2.13s | About the same time with multiple tries | OPW-6275158 Forward-Port-Of: odoo/enterprise#121020
This update clarifies the Budget Report by adding more specific labels for budget lines. Previously, lines were grouped with generic names like 'Budget 2026 x', making it difficult to distinguish them. Now, the report includes the associated analytic accounts, providing a clearer and more informative view of budget data.
Original PR description
Budget report grouping by budget line displayed the budget name for every line, which made different lines indistinguishable and produced labels like "Budget 2026 x", "Budget 2026 x (2)", etc. Compute a more specific display name for budget lines by appending the analytic accounts concerned by the line to the budget name. Also expose Budget Line as a first-class group-by in the Budget Report search view and apply it by default when opening the report. task-6293065
This update resolves an issue where clicking the 'Documents' button on an employee form opened a new browser tab. The change adds a setting to ensure the button opens directly within the existing employee form, improving user experience and workflow efficiency.
Original PR description
Issue: ---------------------------------------- When on an employee form, clicking the "Documents" button opens a new page instead of staying on the same. Steps to reproduce: ---------------------------------------- - Install `documents_hr` - Go on an employee form - Click the "Documents" button - It opens a new page Cause: ---------------------------------------- The `'ir.actions.act_url'` opens a new page by default. Solution: ---------------------------------------- Add `'target': 'self',` to make it open the URL in the same page. opw-6284677