Daily updates from Odoo
Monday, April 20, 2026
17 changes · master
Resolved issues and error corrections
The Dutch ICP report now rounds amounts down to whole numbers, matching the rounding already used in exports. This reduces confusion and helps businesses compare report and export values consistently for Dutch tax reporting.
Original PR description
Description of the issue this commit addresses: The Dutch tax authority lets ICP amounts be rounded down which is the behavior of the exports but not of the report itself meaning the values to not match and is quite confusing. --- Desired habevior after this commit is merged: The integer rounding DOWN is added on the ICP report to restore matching values --- task-6065382 Forward-Port-Of: odoo/enterprise#114277 Forward-Port-Of: odoo/enterprise#112953
Payment reminder emails for subscriptions now avoid showing the exact automatic cancellation date until the final 24-hour reminder. This helps encourage earlier payment while also fixing cases where a zero-day grace period was incorrectly treated as the default delay.
Original PR description
- Hide close date until final 24h payment reminder: This commit updates the payment reminder logic to only expose the contract closing date precisely 24 hours before the subscription is automatically cancelled. By hiding the date during the earlier standard reminders, we create urgency without encouraging procrastination. It also fixes a native Python evaluation bug where an auto-close limit explicitly set to zero days would be treated as "falsy" and incorrectly default to a 15-day grace period. Both manual payments and tokenized payment failures have been updated to follow these new rules. task: 5902221
Payments dated in the future are now excluded from Mexico CFDI payment signing, preventing users from accidentally submitting documents that government rules do not allow. The invoice action to update payments will not appear when only future payments exist, and future payments are ignored when eligible payments are processed.
Original PR description
To sign a payment registered in the future is not allowed by the government. See http://omawww.sat.gob.mx/tramitesyservicios/Paginas/documentos/Guia_llenado_pagos.pdf Steps: - Create a PDD invoice (the due date should be at least 1 month later than the invoice date) - Send it to CFDI - Register a payment in the future -> We have the 'Update payments' button that appear on the invoice view, if you clik on it the payment will be signed With this commit, we filter out the payments with a future date, that way we don't have the 'Update Payments' button if there are only future payments, or the future payments won't be taken into account when clicking on the button. opw-5934753 Forward-Port-Of: odoo/enterprise#114074 Forward-Port-Of: odoo/enterprise#112320
A payroll employee field in Belgian localization was being checked too early, before the needed payslip data existed. This change prevents that premature check so holiday pay recovery values are calculated at the right time, improving reliability of payroll tests and results.
Original PR description
…ield The computed, non-stored field `l10n_be_holiday_pay_recovered_n1` had tracking enabled. When writing to any field on the employee, the `write` method calls `_track_prepare` for tracked fields if `mail_notrack` is not set in the context. `_track_prepare` reads the current value of tracked fields to store initial values. Because `l10n_be_holiday_pay_recovered_n1` is non-stored with no dependencies, this triggered a computation at the very beginning of the test, before payslips existed. Later, when payslips were created, the field was never recomputed, causing incorrect values and test failures. Previously, the `tracking_disable` context prevented early computation. The fix removes the tracking attribute entirely, so the field is only computed when accessed, avoiding premature reads and fixing the tests. task: 6095445 Forward-Port-Of: odoo/enterprise#114063 Forward-Port-Of: odoo/enterprise#113015
Subscription payments using a bank default account are now automatically matched with the related invoice. This prevents paid subscription invoices from incorrectly remaining marked as not paid, reducing manual follow-up for finance teams.
Original PR description
Currently, when a subscription payment is processed through a provider configured to use as outstanding account the bank default account, the resulting invoice may remain in an 'open' state even…
Currently, when a subscription payment is processed through a provider configured to use as outstanding account the bank default account, the resulting invoice may remain in an 'open' state even though the payment transaction is 'done'. This type of configuration is usually done when users want to skip the bank reconciliation process, and just create payments without the need to reconcile the payments with transactions. Steps to reproduce: - In Settings, under Sales > Invoicing, disable Automatic Invoice - Activate demo payment method - In the main Bank account add the default account as outstanding account for demo payment method. - Create a sales order with a subscription product - Open Preview - Pay - Go back to the sales order and open the created invoice Issue: The invoice is created and the payment is registered, but the invoice remains 'Not Paid'. Analysis: The invoice and the payment move lines are not automatically reconciled during the post-processing of the transaction, leaving the invoice unbalanced. opw-5869303 Forward-Port-Of: odoo/enterprise#110656
Asset creation eligibility for accounts is now based on whether an account is configured as accumulated depreciation on another account, rather than whether it was used by existing assets. This prevents legacy asset records from blocking valid new asset creation and keeps depreciation account choices clearer.
Original PR description
This commit fixes the `can_create_asset` flag on accounts to limit the creation of asset based on if account is used as an accumulated depreciation on another account, instead of used by an asset. This requirement came after users with old assets couldn't create assets using some accounts because they were used by the old assets with no possible way to change that. Better to limit on configuration data instead of business data. Also now, accounts that have models set do not show up in the accumulated depreciation dropdown. no-task Forward-Port-Of: odoo/enterprise#114096
This update fixes an error that could block upgrades of the Accounting Reports module. It ensures required report grouping data is correctly set, helping upgrades complete smoothly without manual intervention.
Original PR description
Bug introduced by odoo/enterprise#113124, when trying to upgrade the module `account_reports`, traceback error: > psycopg2.errors.NotNullViolation: null value in column "horizontal_group_id" > of relation "account_report_horizontal_group_rule" violates not-null constraint.
The Documents mobile search panel now opens folder sections correctly again, including company and other grouped values. This also restores missing section icons and improves styling and keyboard navigation for a smoother mobile experience.
Original PR description
Follows the changes made in community and fixup some styling introduced in commit[1] - remove unneccessary styling - rescope styling in right files - fixup the searchpanel inside the bottom sheet task-6090140 [1]: odoo/enterprise@c573cd168e2e01bb9390ef7aae714688100fb2ae Community PR: https://github.com/odoo/odoo/pull/257378
Database synchronization no longer fails with an error when a user loses access, receives a new remote document, or the remote database cannot be reached. This helps users complete synchronization cleanly and ensures removed access is reflected without a disruptive traceback.
Original PR description
The aim of this commit is to allow a db_user to synchronize a database without facing a Traceback. Context: - A new document has been received by a remote db and we try to synchronize it. - The current user access has been removed from the remote db. - The database is unreachable. Before this commit: In all 3 previous cases, an access error would be raised because a db_user can't write on a database. After this commit: The synchronization finish gracefully and the db_user should have lost his access if it was removed from the remote db. task-id: 6046087 Forward-Port-Of: odoo/enterprise#114204 Forward-Port-Of: odoo/enterprise#113826
Unpaid work entry types are now properly linked to the Belgium monthly employee pay structure. This prevents unpaid absences from being incorrectly included in payslip payments, improving payroll accuracy for Belgian employees.
Original PR description
Work entry types with "unpaid" in their name were not linked to the "Belgium: Employees Monthly Pay" structure, causing them to still be paid during payslip computation. task-6123817
The Time Off overview no longer crashes when a new company or localization has no time off records yet. This ensures users can open the dashboard normally even before any time off data has been created.
Original PR description
Steps to reproduce: 1. Create a new company or install a localization (resulting in 0 time off records). 2. Open the Time Off overview (defaults to the Dashboard Gantt view). -> OwlError: Cannot…
Steps to reproduce: 1. Create a new company or install a localization (resulting in 0 time off records). 2. Open the Time Off overview (defaults to the Dashboard Gantt view). -> OwlError: Cannot destructure property 'type' of 'fields[fieldName]' as it is undefined. Cause: Following the recent work entries refactoring, the JS function `_fetchUserFavoritesWorkEntries` was added to the base `HrHolidaysGanttModel` to fetch data from the `hr.leave` model. When the Dashboard (`hr.leave.report.calendar`) has 0 records, the frontend `SampleServer` is activated to generate fake background data. It builds its schema based on the Dashboard view. When the JS unconditionally fires the cross-model RPC call to `hr.leave` (grouping by `work_entry_type_id`), the `SampleServer` intercepts it. Because it doesn't have `work_entry_type_id` in its Dashboard schema, it fails to evaluate the field type and crashes the Owl lifecycle. Solution: Restrict the `_fetchUserFavoritesWorkEntries` call in `_fetchData` so it only runs when not using sample data (`!this.useSampleModel`). This prevents the `SampleServer` from intercepting unsupported cross-model queries to `hr.leave` when loading empty views on fresh databases. task-5969290 Forward-Port-Of: odoo/enterprise#108618
The rental duration test has been adjusted to avoid occasional failures caused by timezone differences around midnight. This helps keep automated validation stable without changing the customer-facing rental experience.
Original PR description
The rental test intermittently fails on Runbot due to timezone offsets. Near midnight, the start time can appear after the end time, causing the datepicker to auto-shift the end date by 24h. This commit uses `getFutureDate` to set full future datetimes, bypassing browser timezone and midnight crossover issues. Runbot Error: https://runbot.odoo.com/odoo/runbot.build.error/242000
Customers booking appointments can use quick checkout by default, avoiding repeated requests for full billing address details. This improves the booking and payment experience where taxes are typically based on the event or appointment location rather than the customer address.
Original PR description
Forward-Port-Of: odoo/enterprise#114205 Forward-Port-Of: odoo/enterprise#113575
Odoo now handles LinkedIn organization image data more safely when connecting an account. If LinkedIn omits an optional image link, the setup process skips that image instead of failing, helping users complete the connection reliably.
Original PR description
When importing a LinkedIn account, Odoo fetches the image metadata of the organization page and expects each returned image to contain `downloadUrl`. For some LinkedIn accounts this key is missing from the image response, which makes the callback crash with `KeyError: 'downloadUrl'` and prevents the account from being connected. LinkedIn's current Images API documentation describes `downloadUrl` as an optional field, so the import flow should not assume it is always present. This patch skips image entries without `downloadUrl` instead of crashing. opw-6099244 Forward-Port-Of: odoo/enterprise#113812
Australian payroll no longer crashes when an employee contract has a wage but no schedule pay selected. This keeps employee payroll records usable even when pay schedule information is temporarily missing or removed.
Original PR description
This error occurs when the schedule pay is removed from an employee contract with a defined wage. Steps to reproduce: - Install `l10n_au_hr_payroll` module with demo data - Switch to `My Australian…
This error occurs when the schedule pay is removed from an employee contract with a defined wage.
Steps to reproduce:
- Install `l10n_au_hr_payroll` module with demo data
- Switch to `My Australian Company`
- Open any Employee > Payroll > `Wage` remove `schedule pay`
Traceback:
```py
File "/home/odoo/src/enterprise/saas-19.2/l10n_au_hr_payroll/models/hr_version.py", line 549, in _compute_wage
version.wage = Payslip._l10n_au_convert_amount(daily_wage, "daily", version.schedule_pay)
File "/home/odoo/src/enterprise/saas-19.2/l10n_au_hr_payroll/models/hr_payslip.py", line 511, in _l10n_au_convert_amount
coefficient = PERIODS_PER_YEAR[period_from] / PERIODS_PER_YEAR[period_to]
KeyError: False
```
We are encountering this error because the `schedule pay` is removed, causing the field to become `False`. This False value is then passed to the `_l10n_au_convert_amount` [method], resulting in a `KeyError`.
[method]: https://github.com/odoo/enterprise/blob/92c584cc1426ac70f6f77aa8216c17004fa42d35/l10n_au_hr_payroll/models/hr_payslip.py#L500-L509
sentry-7401189447
Forward-Port-Of: odoo/enterprise#113623Studio-created models with Chatter enabled now get the activity filters needed for the activity menu. This means users clicking Late, Today, or Future activities see the correct records instead of all records.
Original PR description
Steps to reproduce
==================
- Install studio
- Create a new app
- Create a new model
- Keep the Chatter toggled (use_mail)
- Exit studio
- Create three records, one with an activity in the past, one today and one in the future
- Click on the clock status icon in the top right
- There should be a section with the new model
- Click on 1 Late => every records is displayed
- Same for Today and Future
Cause of the issue
==================
https://github.com/odoo/odoo/blob/b6434b91a7f94075e1372ec827787504ef7aa4f0/addons/mail/static/src/core/web/activity_menu.js#L39-L77
For this feature to work, the activities_{overdue,today,upcoming_all} filter should be present
Solution
========
We add them to the search view. They are all pretty much implemented the same way in every model.
opw-6069150
Forward-Port-Of: odoo/enterprise#114217
Forward-Port-Of: odoo/enterprise#113011Users can now clear the scope on an ESG emission source without triggering an error. The change keeps related activity flow fields safely empty when no scope is selected, improving reliability while editing ESG records.
Original PR description
Currently, an error occurs when the user removes the scope of the emission source. **Steps to Reproduce:** - Install the `esg` module. - Create an `emission source` record or open an `existing one`.…
Currently, an error occurs when the user removes the scope of the emission source. **Steps to Reproduce:** - Install the `esg` module. - Create an `emission source` record or open an `existing one`. - Remove the `scope` value and click anywhere. `ValueError: Compute method failed to assign esg.emission.source(<NewId origin=1>,).activity_flow_direct_indirect` **Cause:** Error started occurring in 19.0 due to a change in selection field behavior. Since from [commit](https://github.com/odoo/odoo/pull/214422/commits/8d2a42ac419fdf7943a0c11beb8c5de6c6f85bef), selection fields no longer display an “empty” value. To remove a value from a selection field, the user must clear the field, similar to a many2one field. when the user removes the scope value, The system attempts to compute the activity flow, but since the scope is False, it does not match any case [1]. As a result, the method fails to assign a value to activity_flow_direct_indirect, raising an error. This commit ensures that the activity flow and activity flow direct indirect are initialized to False. If no condition matches, the field remains False, preventing the assignment failure. [1]: https://github.com/odoo/enterprise/blob/eaf4b7559b8eb6c538820d6e54f583a41077ac3d/esg/models/esg_emission_source.py#L79-L89 Forward-Port-Of: odoo/enterprise#114079