Daily updates from Odoo
Wednesday, April 22, 2026
34 changes · master
Security fixes and vulnerability patches
The AI website builder now sanitizes generated HTML and CSS before use. This reduces the risk of unsafe or unwanted content appearing on websites, helping businesses rely on AI-generated pages with greater confidence.
Enhancements to existing features
The timesheet kanban views have been redesigned to show more useful information at a glance, with the personal timesheet view now feeling more like a calendar. This should make it easier for users and managers to review time entries, billable work, and overall timesheet status without opening individual records.
Original PR description
Redesign the timesheet kanban views to display more relevant information and make the *My Timesheet* view feel more calendar‑like. ## Additional - To ensure `is_billable` behaves correctly with the kanban progress bar, a non-stored `is_billable_select` field was added to `analytic.account.line`. This field can be queried through its `sql_search` method, allowing efficient access without introducing redundant stored fields in the database. Using a selection field is required for proper progress bar functionality. task-[5180328](https://www.odoo.com/odoo/project/4105/tasks/5180328) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users now see a warning as soon as they assign someone and choose planned dates that overlap with that person's existing tasks. This helps teams spot conflicts earlier and adjust schedules before saving, reducing planning mistakes.
Original PR description
When a user plans a task, they are not aware if the assigned user already has other tasks at the same time. Currently, the overlapping warning is only triggered when the task is saved. This commit ensures that the warning appears as soon as the user selects the assigned user and planned dates, allowing the user to reschedule the task before saving. task-4300405
Helpdesk teams can now see the coupon email and its attachment directly in the related ticket chatter. This makes it easier to track what was sent to customers and keeps the ticket history complete for follow-up and audits.
Original PR description
Log the coupon email and the attachment in the helpdesk chatter --- Task-5075162
Belgian payroll now applies caps to Premium Pay calculations, helping ensure employee payslips follow the required limits. This reduces payroll errors and improves compliance for companies using Belgian payroll rules.
Original PR description
add premium pay caps Task: 6119891
The French reporting export screen now allows longer text lines to wrap instead of being cut off. This makes export information easier to read and reduces confusion for users reviewing async export details.
Original PR description
Improves the UI by allowing the text lines to wrap and fully be visible. No task ID
The accounting reports setup screen no longer shows an informational warning about reports using custom handlers. This reduces clutter for users who customize reports and removes a message that is no longer considered useful.
Original PR description
Before this commit: - We had one info banner with the message indicating that the report is using a custom handler, so a change in the parameters used for computation could lead to errors. After this commit: - Now, we are removing this info banner from the report form view, because there is no need for this banner anymore, as if the user wants to customize the reports, they'll do it anyway. Task-6037421
This update changes how VoIP-related records are stored internally to better handle frequent creation and deletion of calls, messages, and related items. Users should not see workflow changes, but the app may feel smoother and more responsive during busy usage.
Original PR description
`Store.MyModel.records` is an object whose key is record local id and value is the record. While format of object is nice, this object has its shape changing quite often as this is based on creation and deletion of records. Objects in javascript are expected to have their shape changed rarely, which is not the case of `records`. In theory, creation of JS models can lead to noticeable stuttering from major and minor GC. This commit changes the shape of `records` to become a Map instead, which doesn't have these problems. As this becomes a Map, and quite some business code was using `Object.values()` around records, this commit also add a new feature on Model object: `.all()`, which returns list of all records of the given model: ```js // previously Object.values(store.MyModel.records); // now store.MyModel.all(); ``` Task-5437248
The Documents app now keeps page navigation visible in Kanban and List views, even when the details panel is open. This makes it easier for users to move through document pages without changing panel visibility, and the details panel now updates to show the current folder when pages are opened or changed.
Original PR description
Before this commit, the pager would only be displayed if the right panel is invisible. This commit allows to be always displayed in `Kanban` and `List` views regardless of the state of the right panel. task-6070904
The Belgian payroll module now includes the 2026 salary scale values for Joint Committee 302, covering both regular and flexi jobs. This helps ensure payroll calculations stay aligned with the latest sector requirements and that related checks continue to validate the updated amounts.
Original PR description
. Add JC302 salary scale 2026 effective values for normal & flexi jobs . Update the corresponding tests task-6127071
The settings text for the Invoicing Switch Threshold now explains that all entries created by Invoicing before the threshold date are ignored, not just invoices. This helps users better understand what data is excluded and reduces confusion during accounting setup.
Original PR description
The previous "Invoicing Switch Threshold" explanation was misleading as it said only invoices prior to the threshold date is not taken into account. The explanation is updated to state that all entries created by Invoicing before the threshold date will be ignored. task-5940144 Forward-Port-Of: odoo/enterprise#113635
Resolved issues and error corrections
Approval request reports now still translate correctly when no contact is selected. If the contact language is unavailable, the report uses the request owner’s language or the system default, ensuring users receive printed approvals in the expected language.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
The UAE financial audit report test data was updated to match the latest account codes from the new chart of accounts. This keeps automated checks aligned with the current accounting setup and helps avoid false test failures.
Original PR description
in the odoo PR we changed a lot of the account codes. in this pr we are just fixing a test where the csv was still comparing old account codes in the CSV task-5455978
The Chilean currency rate provider can now wait longer when the source service is slow, instead of failing after a fixed 30 seconds. This helps avoid missed daily exchange rates and reduces manual corrections caused by temporary delays from mindicador.cl.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
Companies that are not based in Belgium but use Belgian taxes can now see and manage Intervat settings. This lets users change or disable the automatic Intervat redirection when Belgian accounting is enabled through a Belgian fiscal position.
Original PR description
### Issue: When demo data is disabled, creating a Belgian fiscal position installs the Belgian taxes and enables BE accounting Starting from 19.0, Intervat redirection is enabled automatically, but the Intervat settings are not available because the company itself is not Belgian As a result, the Intervat configuration cannot be changed or disabled ### Cause: The Intervat settings were only shown when the company country was Belgium However, companies using Belgian taxes through `account_enabled_tax_country_ids` must also be considered ### Steps to reproduce: - Disable demo data and install `accountant` - Create a Fiscal Position "Belgium" (Country: Belgium, Foreign Tax ID: BE010203040) - Click the alert to install the Belgian taxes - Open Settings Before the fix: The Intervat settings are not available opw-6068480 Forward-Port-Of: odoo/enterprise#112609
This fix makes French fiscal declaration exports more complete and reliable before they are sent to the ASPone platform. It adds missing report information, improves company data checks before export, and corrects small errors that could affect tax filing submissions.
Original PR description
This commit aims to make the xml that we send to aspone for the liasse fiscale is the more complete as possible and to correct some small bugs. - Add missing fields in the reports - Add missing tags in the xml - Add a data validation on company data before exporting the reports - Correct errors in the reports - Add country fields in the reports as many2one task-6128878
This fixes an issue where adding a configurable employee benefit could cause an error if no salary summary existed for the same contract structure. Benefits are now shown consistently, preventing interruptions during salary package configuration.
Original PR description
Cause: After this task https://www.odoo.com/odoo/project/1251/tasks/5419466, the showing of benefits was restricted by mistake to only when there was a salary summary for the same structure type. This meant that adding a configurable benefit would result in a traceback, since the template was then used to get more info later on. Fix: Always show configurable benefits, even if there is no salary summary for the same structure type. task-6126621
This fix makes an age-related Belgian payroll test use a fixed date so results no longer change as time passes. It prevents intermittent nightly build failures and improves confidence in payroll validation checks without changing customer-facing payroll behavior.
Original PR description
The test was failing intermittently in nightly builds that run at a date in the next year (e.g.: 2027-04-20). The issue was that the student's age is calculated at runtime using : - When the student is age 19 (2026): min wage = 2057.87 < 2100 → PASS - When the student is age 20 (2027): min wage = 2136.84 > 2100 → FAIL task-6144986 Runbot error: https://runbot.odoo.com/odoo/runbot.build.error/242589
Opening an AI agent chat from the systray or command palette now brings the conversation to the front in full-screen Discuss. This prevents users from thinking the action failed and makes access to AI assistance more reliable.
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
The accounting reports return name now shows the correct calendar year for date ranges that start near the beginning of January. This prevents confusing labels such as showing January 2022 for a return that actually starts in January 2023.
Original PR description
Steps to reproduce: - Create a return from Jan 2023 to April 2023 -> the dates displayed in the name will be Jan 2022 - Apr 2023 The display is incorrect because we used the wrong date format, and therefore switch from using YYYY to yyyy as the first one is the ISO standard year and the second the calendar year. They might differ on the result here because 01 Jan 2023 falls on a Sunday, but ISO week starts on Monday, so it took the previous year (2022) Forward-Port-Of: odoo/enterprise#114428
The deduplication screen now correctly hides the discard button when users are viewing records that have already been discarded. This avoids confusion and prevents users from trying to discard records again, including when only some records in a duplicate group are discarded.
Original PR description
Ensure the discard button is hidden in the deduplication view when displaying discarded records, including cases where only part of a duplicate group is discarded and shown through the archive/discarded filter. task-6124494
Signed files added from a project or task now automatically select the project's configured Documents folder instead of defaulting to My Drive. This keeps signed project paperwork organized in the same place as other project attachments and reduces manual filing.
Original PR description
Steps to Reproduce --- - Request a signature from a project task or project and complete the signing process. - In the chatter, click "Add to Documents" on the signed attachment. Issue --- Signed documents attached to projects or tasks default to "My Drive" when added to Documents, instead of using the project's configured Documents folder. Current Behaviour --- - Regular task/project attachments correctly preselect the project Documents folder. - Signed attachments fall back to "My Drive". Expected Behaviour --- Signed documents linked to projects or tasks should preselect the project's Documents folder, consistent with regular attachments. Fix --- Extend get_documents_operation_add_destination to handle sign.request attachments linked to project.task or project.project, resolving to the corresponding project Documents folder. task - 5226770 Forward-Port-Of: odoo/enterprise#105600
Restarting an IoT box no longer resets a printer subtype that a user manually selected. This prevents unwanted configuration changes and keeps device settings aligned with business preferences.
Original PR description
Steps to reproduce: 1. Connect a printer to the IoT box and pair with a DB 2. Manually change the subtype of the printer in the DB 3. Restart the IoT box so it resends its devices. **Expected behaviour**: Subtype remains as the user-set value. **Actual behaviour**: Subtype is reset to the original value. To fix this issue, we simply remove any check for subtype in the device updating condition. Now, a device will only reset if its type changes. Forward-Port-Of: odoo/enterprise#114416
Vendor bills created with auto-complete now keep the correct Intrastat transaction details from the original bill. This helps EU companies avoid missing trade reporting information and reduces manual corrections.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#114520 Forward-Port-Of: odoo/enterprise#112857
The W-2 report CSV export no longer fails when the End Date field is left blank. In that case, the file name now uses the current year, allowing payroll users to generate the report successfully.
Original PR description
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined. Steps to replicate: - Install `l10n_us_hr_payroll`. - Open Payroll > Reporting > W2 Report. - Click…
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined.
Steps to replicate:
- Install `l10n_us_hr_payroll`.
- Open Payroll > Reporting > W2 Report.
- Click `New` > Remove value from `End Date` and click Generate.
Error:
```
File '/home/odoo/odoo19/enterprise/l10n_us_hr_payroll/models/l10n_us_w2.py', line 249, in action_generate_csv
self.csv_filename = f'form_w2_{self.date_end.year or date.today().year}.csv'
^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'year'
```
Cause:
- As the user did not give any value for `End Date`, False was passed and when the execution flow reached [here] `self.end_date` is False and attempting to access `self.end_date.year` results in this error.
Solution:
- If we do not receive the `self.end_date` while generating the CSV, we will use the current year to generate the CSV file name.
[here]: https://github.com/odoo/enterprise/blob/01be8d6e9384bcb340559847d529b4887e073519/l10n_us_hr_payroll/models/l10n_us_w2.py#L248
No ID
Forward-Port-Of: odoo/enterprise#114363
Forward-Port-Of: odoo/enterprise#113408Rental planning now correctly applies calendar leave entries that are not tied to a specific resource to all resources. This helps prevent availability and scheduling errors when company-wide unavailable periods are configured.
Original PR description
Before this commit, any `Resource Calendar Leave` created with no `Resource` related to it was ignored, while it should have been applied to all `Resources`. This commit makes sure that any `Resource Calendar Leave` with no related `Resource` is applied to all `Resources` as intended. task-5798796 Forward-Port-Of: odoo/enterprise#114274 Forward-Port-Of: odoo/enterprise#112575
Self-ordering now loads only the point-of-sale configuration and session information it actually needs. This reduces unnecessary data handling, helping the self-ordering experience run more efficiently without changing how users interact with it.
Original PR description
This commit optimizes pos_config and pos_session data loading by only loading the fields required for self-ordering. X-original-commit: ce78609b368e541a70c17141ee5b51543c73c1d0 Forward-Port-Of: odoo/enterprise#113801 Forward-Port-Of: odoo/enterprise#113661
The employee form in Swiss payroll now shows the contract template button with styling that matches the surrounding interface. This removes visual inconsistency and makes the form look more polished for users.
Original PR description
Fix contract template button styling: remove incorrect classes and align font-size and border with the surrounding UI task-6068488 Forward-Port-Of: odoo/enterprise#112113
Users without inventory access can now duplicate Helpdesk tickets without encountering an access error. The fix avoids copying restricted product information for those users and also prevents a related refund access issue, keeping helpdesk workflows moving for non-stock staff.
Original PR description
Steps to reproduce: - Install helpdesk_sale_timesheet. - Create a Helpdesk Ticket and set its sale_line_id. - Log in as a user without stock.group_stock_user access. - Try to duplicate the ticket. Issue: Duplicating a ticket raises an AccessError because the user lacks stock rights required when copying the product_id. Fix: Set `product_id` to False during duplication for non-stock users. Reference: https://github.com/odoo/enterprise/pull/9100 task-5356318 Forward-Port-Of: odoo/enterprise#114266 Forward-Port-Of: odoo/enterprise#101338
The ecommerce product page now shows rental availability based on the customer’s selected rental period, even when “continue selling” is enabled. This prevents shoppers from seeing misleading stock numbers and helps businesses communicate accurate rental availability before checkout.
Original PR description
**Issue**: The displayed available quantity on the ecommerce product page is incorrect for rental products when "continue selling" is enabled. **Steps to reproduce**: - Create a rental product…
**Issue**: The displayed available quantity on the ecommerce product page is incorrect for rental products when "continue selling" is enabled. **Steps to reproduce**: - Create a rental product tracked in stock with a quantity of 5 - Enable "continue selling" and "show available quantity below 10" - Go to the ecommerce page of this product - Rent 3 units for a given period, confirm and pay - Return to the ecommerce product page -> Whatever the selected renting period, the displayed quantity is always 2 **Cause**: The website displays `free_qty`: https://github.com/odoo/enterprise/blob/41c729e22c5fd1abb690f8335e933f793be0b319/website_sale_stock_renting/static/src/xml/website_sale_stock_renting_product_availability.xml#L15 `free_qty` is computed in: https://github.com/odoo-dev/odoo/blob/0935829ddaecd7b2b6eec9157f8f790b546d06ff/addons/website_sale_stock/models/product_template.py#L36 which leads to: https://github.com/odoo/enterprise/blob/41c729e22c5fd1abb690f8335e933f793be0b319/website_sale_stock_renting/models/website.py#L10 and ultimately relies on: https://github.com/odoo/odoo/blob/37bf1703c7478a3010b71cd60bbb43b3295a605b/addons/stock/models/product.py#L213 This computation does not take the selected renting period into account. There is a period-aware computation here: https://github.com/odoo/enterprise/blob/41c729e22c5fd1abb690f8335e933f793be0b319/website_sale_stock_renting/models/website.py#L15C17-L21C1 but it is only triggered when `product.allow_out_of_stock_order` is False (i.e. when "continue selling" is disabled). opw-[5354163](https://www.odoo.com/web#id=5354163&view_type=form&model=project.task) Forward-Port-Of: odoo/enterprise#108493 Forward-Port-Of: odoo/enterprise#103333
When users select all documents across multiple pages, the Share panel now includes every selected file instead of only the files visible on the current page. This ensures permission changes are applied consistently to the full selection, preventing missed documents in large batches.
Original PR description
**Steps to reproduce:** - Install Documents app - Upload more than 80+ files (max page size is 80) - Use the checkbox to select all files on the page - Click the 'Select All' button in the control panel to select allfiles - Use Share action button - Pop-up only takes the current page into account - Rights modifications will not be applied on remaining records **Issue:** `onShare()` only takes current records into account even if the full selection was applied. **Fix:** Fetch all document ids (if needed) before opening the dialog. opw-5957777 Forward-Port-Of: odoo/enterprise#110299
The Peruvian reporting export no longer fails when draft invoices are included in the General Ledger. This helps users generate Inventory and Balance reports reliably without needing to post every invoice first.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#114550 Forward-Port-Of: odoo/enterprise#113405
This update stabilizes the geolocation service tests used by Field Service planning. It reduces unnecessary test work so the checks run consistently and no longer fail at random, which helps keep development and releases more reliable.
Original PR description
This commit fixes the undeterministic test failures for the geolocation service. We reduce the [workload](https://github.com/odoo/enterprise/blob/master/planning_field_service/static/src/services/field_service_geolocation_service.js#L26) of the `startWatch` method by mocking the `has_group` calls. Forward-Port-Of: odoo/enterprise#114572
This change updates several internal counters used by mail and related performance checks so they match the expected system state. It helps ensure automated checks stay reliable and prevents incorrect error handling when rendering content with a missing field.
Original PR description
> > Update various (main mail-related) counters according to runbot state. Forward-Port-Of: odoo/enterprise#114603