Thursday, April 23, 2026
12 changes · 19.0
Enhancements to existing features
This update expands access to return type configuration options within the Odoo Enterprise accounting reports module. Previously, these settings were limited to debug mode, hindering user flexibility. Now, these options are available for authorized users, streamlining report customization and improving usability.
Original PR description
Before, the menu return types in configuration was only available in debug mode. Now it is available for the group `account.group_account_readonly` task-5912751
Resolved issues and error corrections
This update fixes a confusing issue for Mexican employees receiving payslips. Previously, an email was sent with an unstamped payslip before the official CFDI stamp was generated, leading to duplicate emails. Now, emails are only sent with the stamped payslip, ensuring a clearer and more accurate experience.
Original PR description
Currently, when a user confirms a payslip batch (hr.payslip.run), the base payroll module queues the PDF generation and sends an email to the employee with their payslip immediately. For Mexican payslips, this means the employee receives the email with an unstamped payslip (without CFDI UUID). Later, when the CFDI is generated, a second email is sent with the stamped version, confusing the employee. This commit prevents the email from being sent for Mexican payslips if the CFDI has not been generated yet, ensuring only the stamped payslip is emailed.
This update fixes an error in the Mexican payroll calculation, ensuring that basic salaries are accurately calculated based on full calendar periods, including unpaid leave. Previously, unpaid leave was incorrectly prorated, now the system correctly calculates the basic salary based on the full pay period, aligning with Mexican regulations.
Original PR description
In Mexico, the basic salary must be calculated based on the total calendar days of the period. This ensures that both worked days and non-working days (e.g. Sundays) contribute equally to the total…
In Mexico, the basic salary must be calculated based on the total calendar days of the period. This ensures that both worked days and non-working days (e.g. Sundays) contribute equally to the total payment. This calculation also applies to the daily schedule, as the proportional daily wage must be divided equivalently across the hours of the day. Current behavior: When an employee has an unpaid leave, the basic salary is incorrectly prorated using only the registered days/hours. Example: For a monthly wage of 30,000 MXN in a month with 22 scheduled days (21 attendances + 1 unpaid leave), the implicit daily rate becomes 1,363.63 (30,000 / 22). This leads to an incorrect basic salary of 28,636.36 MXN for the days worked. This also happens with unpaid leave for x hours, e.g., for 2 hours, the unpaid leave is calculated as 2 hours * (30,000 / (22 days * 8 hours)) = 340.90 MXN, which is incorrect. Expected behavior: The basic salary should be derived from the full period (e.g., 30 days for a month, 15 for a bi-weekly period). Example: For a 30,000 MXN wage, the daily rate should be 1,000 MXN (30,000 / 30 days). If there is 1 unpaid leave, the basic salary should be 29,000 MXN (29 days * 1,000 MXN), regardless of the number of scheduled working days in the calendar. For unpaid leaves by hours, e.g., for 2 hours, the unpaid leave should be calculated as 2 hours * (30,000 / (30 days * 8 hours)) = 250.00 MXN. To achieve this, the calculation of the days in the `_get_worked_day_lines` is: * Adjust worked days/hours for out-of-contract entries where necessary, ensuring that rest days(Sundays) are included in the count. * Get all worked hours in the lines. * Calculate the number of days to pay based on the total hours and the hours per day. ### Case: payslip does not cover the complete pay period Current behavior: If a payslip is created for a partial period, the total amount is the full period wage. Expected behavior: The total amount should be pro-rated based on the days of the period. For example, if a payslip is created for 25 days(with a monthly schedule pay), the total amount should be the daily salary multiplied by 25 days. To achieve this, `_compute_amount` is updated to calculate the wage based on the `l10n_mx_daily_salary`. Changes on tests: * Add: * `test_monthly_payslip_with_partial_leave`, `test_partial_payslip`, `test_partial_payslip_new_hire_month_31_days` and `test_partial_payslip_new_hire_month_28_days`. * `test_hourly_payslip_by_attendance` to validate when `Work Entry Source` is set to "attendance". * Update: * `test_hourly_payslip`, `test_monthly_payslip` and `test_partial_payslip_new_hire` to align with the new calculation. * Adjust payslips dates to match the `schedule_pay` in `test_regular_payslip_subsidy` and `test_weekly_schedule_pay_no_code` * Fix a one-day difference in `TestMxEdiHrPayrollCommon`(16 days instead of 15 days for a bi-weekly schedule), and update the corresponding CFDI values. * Refactor tests and add new helpers. ### Error on [warning issues generation][1] and [`_compute_is_wrong_duration`][2] The warning: `"The duration of the payslip is not accurate according to the structure type."` appears with these custom periods for Mexican Payroll, although the period is correct: * `10_days` * `14_days` * `bi-weekly` Steps to replicate: * Install `l10n_mx_hr_payroll` module. * Switch to "INNOVACION VALOR Y DESARROLLO SA SA" company. * Go to Employees and open "Cesar Osbaldo Cruz Solorzano". * Click on "Payroll" tab, change the "Pay Schedule" to any option listed above, for example "Bi-weekly". * Go to Payroll > Payslips > Payslips and create a new pay run. * Select Salary Structure 'Mexico: Regular Pay', Pay Schedule 'Bi-weekly' and the Period '01/01/2026 -> 01/15/2026'. * Click on "Continue", select Cesar and click on "Select". * It appears the warning issue. Problem: The warning is raised because of `slip.date_from + slip._get_schedule_timedelta() != slip.date_to` condition, because `_get_schedule_timedelta` function calls [`self._schedule_timedelta(schedule, self.date_from)`][3] without the `country_code` argument. In the Mexican Payroll [_schedule_timedelta is overriden][4] but it is necessary to call it with the country code to use the custom periods; similar to how the [`date_end` is computed][5]. Solution: Call `_get_schedule_timedelta` passing the `country_code` [1]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip.py#L1367 [2]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip.py#L1454 [3]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip.py#L275 [4]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/l10n_mx_hr_payroll/models/hr_payslip.py#L58 [5]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip_run.py#L211 target: 19.0 task-6073601
This update corrects a bug in the project timesheet forecasting report that incorrectly showed planned hours on public holiday days. The fix addresses an issue where the system wasn't properly accounting for general public holidays and timezone differences, ensuring accurate reporting of employee time allocation.
Original PR description
### Steps to reproduce: - Install project_timesheet_forecast module - Configure your database to have a far timezone (Montevideo/Uruguay in my case) - Create a public holiday starts from 12AM to…
### Steps to reproduce: - Install project_timesheet_forecast module - Configure your database to have a far timezone (Montevideo/Uruguay in my case) - Create a public holiday starts from 12AM to 11:59PM with a calendar - Create a planning slot for a resource that overlap with the public holiday - Check the Timesheets / Planning analysis report - Group by employees > day **- Check the date of the public holiday and notice there are still planned hours shown** - Remove the calendar from the public holidays that we created previously - Check the report once again **- Notice the day of the public holiday and the day after has no planned hours** ### Cause: In the query we are using to exclude the leave days from the report we only exclude the ones that has calendar_id assigned, not taking into consideration that some of the public holiday are general and is not applied to just one working schedule. Also if we have a leave starting midnight to 11:59PM since we store dates in database as UTC for timezone like Uruguay's one it will shift the end with one day which will introduce inconsistencies ### Fix: We check if the calendar_id is null on the resource_calendar_leaves and make sure we take timezone of the resource into account when checking the dates of the leaves. opw-5027070 Forward-Port-Of: odoo/enterprise#111846
This update resolves an issue where scanning a lot initially added an extra unit to the quantity. It also corrects a problem where packaging quantities weren't being applied to subsequent lots. The change simplifies the underlying code to ensure accurate quantity updates when using packaging with lots.
Original PR description
## Issue Currently, the Barcode app doesn't work very well when the user scans packaging and lots. If they want to apply one or multiple packagings to a specific lot, the quantity is not quite exact…
## Issue Currently, the Barcode app doesn't work very well when the user scans packaging and lots. If they want to apply one or multiple packagings to a specific lot, the quantity is not quite exact since scanning a lot already increases the quantity by 1. Also, if there is multiple lots, the packaging quantity isn't added to the last scanned lot which is problematic. ## How to reproduce 1. Active "Units of Measure & Packagings" and "Lots & Serial Numbers" settings; 2. Create a product tracked by lots with a barcode; 3. In the "Sales" tab, add a packagings (for example, "Pack of 6"); 4. Configuration > Units & Packagings > Selected the added UoM > Click on "Packaging Barcodes"; 5. Create a new barcode for the created product; 6. Create and confirm a receipt for 12 units of this product and open the operation in Barcode app; 7. Scan the product's barcode, then a lot then the packaging barcode :arrow_right: First issue: the line has 7 units. 8. Scan a second lot and scan the packaging again :arrow_right: Second issue: the packaging quantity is added to the first line, not the second one. ## Explanation About the first issue, it is the expected behavior. When the user scans a lot, we increase the line quantity by 1. When the user scans a packaging, we increase the line quantity by this packaging quantity. The issue here is the user expects to scan a lot and then to apply a packaging quantity to it. For example, scanning a lot then a pack of six should result by a line with 6 units, not 7. About the second issue, it is caused by some conditions in the `_findLine` method which don't prioritize the right line. [OPW-6045395](https://www.odoo.com/odoo/project.task/6045395)
This update fixes an issue where the quantity of scanned packages was incorrectly displayed after re-entering a delivery order with full packaging enabled. Previously, the system didn't properly track reserved quantities, leading to inaccurate counts. Now, the system correctly reflects the picked quantity, ensuring accurate inventory management.
Original PR description
Issue ----- When using full packaging in barcode, leaving the operation and opening it again shows incorrect quantity for already scanned packages. Steps to reproduce ----- - Enable packages - Create…
Issue ----- When using full packaging in barcode, leaving the operation and opening it again shows incorrect quantity for already scanned packages. Steps to reproduce ----- - Enable packages - Create a product with one package in stock - Operation Types > Delivery Orders, set Move Entire Packages to true - Create a delivery for a package - Scan the package barcode - Exit the delivery - Re-enter the delivery > Quantity for the line is 1/false Cause ----- The line is picked, so it is considered as not reserved https://github.com/odoo/enterprise/blob/02f957b600bac3d86411091fd762d88e372db7c5/stock_barcode/static/src/models/barcode_picking_model.js#L288-L289 when doing https://github.com/odoo/enterprise/blob/02f957b600bac3d86411091fd762d88e372db7c5/stock_barcode/static/src/models/barcode_picking_model.js#L812-L813 This leads to `qtyDemand` returning false instead of 1 https://github.com/odoo/enterprise/blob/02f957b600bac3d86411091fd762d88e372db7c5/stock_barcode/static/src/components/package_line.js#L17-L18 ----- Ticket: opw-5960629 Forward-Port-Of: odoo/enterprise#114451 Forward-Port-Of: odoo/enterprise#113816
This update ensures that the AI chat window opens in full-screen mode whenever it's launched, regardless of how it's initiated (e.g., from the system tray or command palette). Previously, the chat would open in a background window, which has now been resolved. This improves the user experience and allows for more efficient interaction with the AI assistant.
Original PR description
Prior to this commit, when opening the chat with an agent from the systray button, the chat window was opened in the background. This commit fixes the issue by adding a call to `channel.open` which opens the chat when in full-screen mode. This commit also fixes an issue where the chat window wasn't properly opened when done from the command palette. task-5172978
This update clarifies the Profit and Loss report in French accounting by splitting account 649 into two new accounts (6491 and 6492). This separation accurately reflects social security charges and salaries, aligning with French accounting standards (ANC PCG 2026). The original account remains for legacy systems.
Original PR description
Splitting account 649 into two new accounts (6491 and 6492) is necessary to handle the Profit and Loss report properly. This ensures we can accurately separate social security charges from salaries in the report. Reference: ANC PCG 2026, page 445, note (h) https://www.anc.gouv.fr/files/anc/files/1_Normes_fran%C3%A7aises/recueil/RECEUIL-PCG-2026-AVEC-COUVERTURE.pdf task-6053784 Forward-Port-Of: odoo/enterprise#112905 Forward-Port-Of: odoo/enterprise#111420
This update fixes a bug in the bank statement reconciliation process. Previously, a payment from a different company with a matching UUID could incorrectly link to another company's transaction, leading to inaccurate financial reporting. The fix ensures that both the bank statement and payment belong to the same company hierarchy, preventing foreign transactions from being added to the wrong accounts.
Original PR description
ticket-5992100 When auto-reconciling bank statement lines, the end-to-end UUID lookup correctly checked that matched AMLs and their payment belong to the same company hierarchy, but missed checking that the payment also belongs to the same company hierarchy as the bank statement line itself. This allowed a payment from an unrelated company (sharing the same end-to-end UUID from an inter-company bank transfer) to be matched against another company's bank transaction, pulling foreign tax lines into the wrong company's journal entry. Fix by adding the same parent-path company check between the bank statement line and the payment.
This update fixes an issue where events were missed, particularly impacting Worldline payments, due to a failure in the system's fallback mechanism. The change ensures that if longpolling fails, the system automatically attempts to use the more reliable websocket connection, guaranteeing event delivery.
Original PR description
Community PR: https://github.com/odoo/odoo/pull/260931 Before this commit, if `onMessage` in `iot_http_service` was called directly, it would fail to fallback to websocket if the longpolling request failed, causing events to be missed. One symptom of this is Worldline payments failing to confirm when using websocket. After this commit, the `_longpolling` method will now throw an error in this case, causing the fallback mechanism to attempt websocket instead.
This update adds 'survey' as a required dependency for the ESG module's automatic installation. Previously, users without 'survey' would incorrectly install it, leading to migration issues. Now, only instances with the necessary dependencies will automatically install 'survey', ensuring a stable and reliable upgrade process.
Original PR description
Description of the issue this commit addresses: As survey is a dependency but not an auto_install requirement of esg_csrd only from 19.0, when migrating to that version, users that don't have survey installed but do have esg will auto_install survey and pull a new computed stored field, ResUsers.karma which causes migrations issues as no script was made to account for that scenario. --- Desired behavior after this commit is merged: This commit adds survey in the auto_install requirements for the module so only instances that already have ResUsers.karma can auto_install esg_csrd --- runbot-238524
This update corrects a display issue related to time zones, specifically when viewing invoices and purchase orders. Previously, invoices created in time zones ahead of UTC would not appear in reports due to date discrepancies. The fix uses the user's local date to ensure accurate reporting across different time zones.
Original PR description
Why this commit: When loading the 'bills to receive' or 'Invoices to be Issued' The time zones ahead of UTC will face the discrepancy in the view. e.g. etc/GMT-12 timezone is 12 hours ahead of UTC,…
Why this commit: When loading the 'bills to receive' or 'Invoices to be Issued' The time zones ahead of UTC will face the discrepancy in the view. e.g. etc/GMT-12 timezone is 12 hours ahead of UTC, So 12 AM UTC is 12 PM etc/GMT-12. So report view will not include the invoices/bill with order_date of current day till its 12 AM[next day] IN UTC, Meaning etc/GMT-12 will be seeing today's bills/invoices after 12 PM. After this commit: To resolve this discrepancy we use the context_today date to get the user local date. Which is required by the [domain sanitizer](https://github.com/odoo/odoo/blob/8bff78853f6ab8dc2cc951c03bb30181c0745834/odoo/orm/domains.py#L1572-L1574) too. Steps to reproduce (Possible in runbot) : 1. Select etc/GMT-12 timezone in preferences [when UTC is between 13:00-24:00 ~ 1:00-12:00 GMT-12(of next day)] 2. Create a PO and Validate the quantity received. 3. Go to accounting>review>bills to receive. 4. the newly created PO won't be listed here. OPW: 6083526