Daily updates from Odoo
Tuesday, April 28, 2026
14 changes · master
Resolved issues and error corrections
This update resolves an issue preventing AI chat functionality on Safari iOS devices. The fix addresses a compatibility problem with older Safari versions that don't fully support a key streaming technology. By switching to a manual reader loop, the AI chat now functions correctly on Safari, ensuring a smooth user experience.
Original PR description
Steps: - Install ai - Open ai chat - Try to send a message - Traceback The AI chat was failing on iOS with a traceback when trying to process the stream response. Even though MDN suggests…
Steps: - Install ai - Open ai chat - Try to send a message - Traceback The AI chat was failing on iOS with a traceback when trying to process the stream response. Even though MDN suggests compatibility, Safari (WebKit) versions prior to 26.4 do not implement the AsyncIterator protocol on ReadableStream. This makes `for await (const chunk of response.body)` throw a TypeError as `[Symbol.asyncIterator]` is undefined. https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream This commit replaces the async iteration with a manual reader loop (`getReader().read()`). This is the low-level primitive supported by all versions of Safari and ensures the stream is properly consumed and unlocked even if the connection is interrupted. Steps to reproduce: 1. Open Discuss/AI Chat on an iPad or iPhone (eg. 26.4). 2. Send a message. 3. The response triggers a JS error. ```js Uncaught Promise > undefined is not a function (near '...chunk of asyncStream...') ``` opw-6054307 Forward-Port-Of: odoo/enterprise#113926
This update resolves an issue where Peruvian identifiers (like driver licenses) were not being displayed correctly in the system. The change in 19.1 impacted how these identifiers were handled, and this commit restores the visibility of these fields. A related fix was implemented in the Community version to ensure overall consistency.
Original PR description
In 19.1 we changed the `is_company` field to a computed stored field. That change broke the visibility for some Peruvian identifiers (driver license, etc). This commit removes the visibility condition on those fields to be displayed all the time. Note: we still add the correct compute on related Community commit for sake of correctness and completeness. Community: https://github.com/odoo/odoo/pull/260224 Related: https://github.com/odoo/odoo/pull/211043 task-6141307 Forward-Port-Of: odoo/enterprise#115204 Forward-Port-Of: odoo/enterprise#114403
This update fixes a reporting issue for Hong Kong payroll taxes. It adds adjustments to the calculations for IR56B/F/G reports, ensuring that global reimbursements and deductions are accurately reflected in the taxable income totals. This improves the accuracy of tax reporting for Hong Kong businesses using Odoo Enterprise.
Original PR description
Added GLOBAL_REIMBURSEMENT and GLOBAL_DEDUCTION to the AmtOfSalary calculation for IR56B/F/G reports. This ensures adjustments are properly reflected in taxable income totals. task-6126661 Forward-Port-Of: odoo/enterprise#115229 Forward-Port-Of: odoo/enterprise#114041
This update resolves a problem where correction payslips were failing validation due to missing information. The change ensures that correction payslips include the necessary 'structure_id' and adjusts the payrun period to accurately handle multi-month corrections. This improves the reliability of payroll processing.
Original PR description
Ensure `structure_id` is set when creating correction payslips to avoid validation errors. Group payslips by structure before creating pay runs for corrections/reverts, and set the payrun period from the minimum to maximum payslip dates. Fix condition in "Payslip period does not match payrun" to exclude correction payslips (they may span multiple months). task: 6089082
This update corrects a bug where flexible employee hours were incorrectly hidden in the Gantt view for longer work periods. The fix ensures accurate hour calculations across all flexible schedules, displaying progress bars correctly and improving the visibility of employee time tracking. This ensures accurate reporting and scheduling for flexible staff.
Original PR description
For employees having a `resource_calendar_id` with `flexible_hours`, the max hours displayed in the gantt view were incorrectly `days * hours_per_day`. This fixes it by taking the most relevant data between `days * hours_per_day`, `weeks * hours_per_week`, both, or nothing if the range is more than a month. The new calculation is `(weeks * hours_per_week) + min((days * hours_per_day), (hours_per_week))` task 5075953 Forward-Port-Of: odoo/enterprise#114661 Forward-Port-Of: odoo/enterprise#105266
This update ensures that replacement invoices generated after a cancellation process include the original invoice's 'Source' (origin) information. Previously, this data was missing, leading to traceability issues. This fix maintains accurate links between invoices and Sales Orders, improving document accuracy and compliance.
Original PR description
### Issue before this commit: The "Source" (origin) field was missing from the PDF of replacement invoices. While the original invoice correctly displayed the Sales Order reference, the new invoice…
### Issue before this commit: The "Source" (origin) field was missing from the PDF of replacement invoices. While the original invoice correctly displayed the Sales Order reference, the new invoice generated through the request cancel process had an empty origin field. ### Steps to reproduce the issue: 1. Download Sales and l10n_mx 2. Set a UNSPSC Category for one product 3. Go to Sales, create a new Quotation and confirm it 4. Create invoice, confirm and send & print 5. Request cancel button -> create replacement invoice 6. In the new invoice there is no source origin invoice ### Cause of the issue: The invoice_origin field is defined with copy=False. Since the replacement logic uses the copy_data method without explicitly passing the origin value, the field was automatically cleared during the creation of the new invoice. ### Reason to introduce the fix: To ensure document traceability, the fix explicitly passes the invoice_origin from the original invoice to the replacement. This maintains the link to the Sales Order in the database and ensures the "Source" label appears on the printed PDF. opw-6070016 Forward-Port-Of: odoo/enterprise#114099
This update resolves an issue where the 'Configuration' menu was hidden for users with 'All Timesheets' access, preventing them from managing billing targets. The fix ensures that billing-related menus are correctly displayed or hidden based on user permissions and feature settings, improving usability for approvers.
Original PR description
Steps to reproduce Bug 1: 1. Login as a user with "All Timesheets" (Approver) access. 2. Disable the "Timesheet Assistant" feature for this user. 3. Ensure "Billing Rate Indicators" is enabled in…
Steps to reproduce Bug 1:
1. Login as a user with "All Timesheets" (Approver) access.
2. Disable the "Timesheet Assistant" feature for this user.
3. Ensure "Billing Rate Indicators" is enabled in settings.
Steps to reproduce Bug 2:
1. Login as a user with "All Timesheets" (Approver) access.
2. Disable the "Billing Rate Indicators" setting in company settings.
3. Ensure "Timesheet Assistant" is enabled in settings.
Steps to reproduce Bug 3:
1. Only install 'sale_timesheet_enterprise'.
2. Go to Timesheets > Configuration > Settings.
3. Toggle "Billing Rate Indicators" (timesheet_show_rates) or change the encoding unit (timesheet_encode_uom_id), then save and check the menus.
Issue:
1. The "Configuration" menu is hidden, preventing access to billing targets even if the user has "All Timesheets" access.
2. The "Billing Time Targets" menu is still visible inside Configuration even if the "Billing Rate Indicators" feature is disabled in the settings.
3. Menu visibility does not update immediately after saving the settings. Menus that should appear (e.g., "Employee Billing Time Targets" or "Timesheets Assistant") remain hidden, or vice versa, until the cache is cleared or the server is restarted.
Cause:
1. The `hr_timesheet_enterprise_menu_configuration` was restricted in XML to groups that excluded "All Timesheets" users.
2. The `_load_menus_blacklist` logic in Python only blacklisted billing menus for users who were both Managers and System Admins, leaving them visible to regular Approvers even when the feature was disabled.
3. The load_menus method is decorated with @ormcache and stored in the Registry LRU cache. Menu visibility depends on timesheet_show_rates and timesheet_encode_uom_id through _load_menus_blacklist. When this field is updated, the ORM does not automatically invalidate the cached load_menus result because these specific fields are not part of the configuration fields. As a result, the stale old menu remains in memory.
Fix:
- Updated XML to include `hr_timesheet.group_hr_timesheet_approver` in the Enterprise Configuration menu permissions.
- Refactored `_load_menus_blacklist` to:
- Hide all billing-related menus for all users when the feature is disabled.
- Hide the parent Configuration menu if it would otherwise be empty.
- Override the write method in res.company in both modules and explicitly call env.registry.clear_cache() when the relevant configuration fields are modified.
task-5428010
Forward-Port-Of: odoo/enterprise#106464A small typo was causing a critical error when users attempted to clock in with a blackbox POS system. This update corrects the error, ensuring receipt data generation functions correctly and preventing system crashes. This resolves a technical issue impacting POS functionality.
Original PR description
There is a typo trying to assign the server version to `this` instead of the `data` object which is used for the receipt. This causes a `cannot set properties of undefined` error when trying to clock in with a blackbox Forward-Port-Of: odoo/enterprise#115098
This update fixes a bug where bank statement reconciliation could incorrectly match transactions from different companies. The fix ensures that payments and bank statements share the same company hierarchy, preventing foreign tax lines from being added to the wrong company's accounting records. This improves the accuracy of financial reporting.
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. Forward-Port-Of: odoo/enterprise#114881 Forward-Port-Of: odoo/enterprise#113279
This update resolves an issue where SEPA payment files generated with split payslips (using multiple bank accounts) contained duplicate transaction identifiers. The change adds a unique identifier to each transaction block, ensuring compliance with ISO 20022 standards and preventing potential payment processing errors. This ensures accurate and compliant SEPA file generation.
Original PR description
### Issue: If a payslip is split into multiple bank accounts (Salary Allocation), the generated SEPA file contains duplicate <InstrId> tags ### Cause: The `_get_payments_vals` method, `InstrId` is…
### Issue: If a payslip is split into multiple bank accounts (Salary Allocation), the generated SEPA file contains duplicate <InstrId> tags ### Cause: The `_get_payments_vals` method, `InstrId` is based on the payslip ID When a single payslip generates multiple transaction blocks, this ID is duplicated, violating the ISO 20022 requirement for unique instruction identifiers https://knowledge.xmldation.com/support/iso20022/general_rules/instrid This commit adds a unique suffix (e.g., -1, -2) to the `InstrId` for each transaction generated from the same payslip to ensure technical uniqueness Nothing change when you only have one account This is the part of the code that use the payment name: https://github.com/odoo/enterprise/blob/194a8d35ef3e9b47ff566479b0c35c0f963fb42d/account_iso20022/models/account_journal.py#L294-L299 ### Steps to reproduce: - Install `hr_payroll_account_iso20022` with demo data - On the Bank Journal, set a valid IBAN (e.g. BE04957751619131) for `Bank Account Number` - Open the Employee page for Abigail Peterson - In the Personal tab, add 2 Bank Accounts (Send Money: True, Account Number: any) - Click on Salary Allocation and Save (You'll have a 50/50 ratio) - Create a new Pay Run (for Abigail Peterson) - Open the last PaySlip and Validate - Create Payment Report (Export Format: SEPA) - Download the Payment Report and check the <InstrId> tags opw-6069670 Forward-Port-Of: odoo/enterprise#114821 Forward-Port-Of: odoo/enterprise#113113
This update resolves a technical issue preventing the 'Ask AI' graph view from functioning correctly. The fix ensures that AI-generated groupings are processed properly, preventing a crash and restoring the graph view's functionality. This improves the user experience when using the AI tools.
Original PR description
Steps to reproduce:
1. Install `crm`, `sale_management`.
2. Navigate to a list view (e.g. Sales > Orders).
3. Open the "Ask AI" chatbox from the system bar.
4. Ask: "graph view of opportunities per month".
5. [ISSUE] Client traceback after the agent loop tries to open the graph view with groupbys.
The pivot and graph AI tools emitted `rowGroupBys` / `groupBys`, but `search_model_patch` relies on `selectedGroupBys` (the key already used by the list/kanban tools). As a result, groupbys bypassed `applyAISearch` and, for graph, landed as raw `{field_name, intervals}` dicts in `modelParams.groupBy`, where `_normalize` crashed.
Rename the keys to `selectedGroupBys` so pivot/graph go through `applyAISearch` like list/kanban.
Task-ID: 6148879
Forward-Port-Of: odoo/enterprise#114802This update resolves an issue where portal users creating tickets via email would experience errors due to permission restrictions accessing employee calendars across different companies. The fix ensures the system correctly accesses calendar data, allowing ticket assignments to proceed smoothly. This improves the reliability of the helpdesk system for all users.
Original PR description
Problem: Portal email with auto-assignment crashes ticket creation due to calendar access. When a helpdesk ticket is created via email from a portal user and automatic assignment is enabled, the…
Problem: Portal email with auto-assignment crashes ticket creation due to calendar access. When a helpdesk ticket is created via email from a portal user and automatic assignment is enabled, the system computes working intervals for users to determine assignment. This computation goes into resource logic, where resource.calendar fields (flexible_hours) are read. If the assigned user is linked to multiple employees across companies, multiple resource.resource records are evaluated. The helpdesk email flow starts in sudo, but the employee calendar lookup explicitly drops sudo before returning the calendar. Then, the calendar is accessed in the portal context, which does not have permission to read the other company's resource.calendar, leading to an AccessError and preventing ticket creation. Although the failure is triggered from Enterprise helpdesk, the actual crash occurs in Odoo (resource.calendar), meaning the fix must be applied there. Fix: Preserve sudo when fetching employee calendars to ensure that scheduling logic does not depend on the access rights of the email sender. A test is added in helpdesk_holidays, as the issue requires both helpdesk (auto-assignment) and hr (employees/resources) to reproduce. The test simulates a portal email flow with a multi-company user linked to multiple employees and ensures ticket creation succeeds. Steps to Reproduce: 1. Install Helpdesk, Employees, and enable multi-company 2. Create two companies (e.g., Company A and Company B) 3. Create one internal user (User X) with access to both companies 4. Create two employees linked to the same user: - Employee 1 in Company A - Employee 2 in Company B Make sure they are set with a start date, but no end date. Needs to be active employee. 5. Create a Helpdesk team in Company A 6. Add Agent X as a team member 7. Enable automatic assignment 8. Configure an email alias for the helpdesk team 9. Create a portal user 10. Send an email from the portal user to the alias Related Ticket: opw-6035099 Forward-Port-Of: odoo/enterprise#114986 Forward-Port-Of: odoo/enterprise#113047
This update allows administrators to control when subscription users are automatically reset. Previously, this process was automatic and inflexible. By making it configurable, we provide greater control over user management for subscription-based customers.
Original PR description
After this commit, the auto resetting of subscription user is overridable. Doing business logic in CRUD methods makes them impossible to bypass, by encapsulating the logic in another method, it would be easily overridable. Forward-Port-Of: odoo/enterprise#114459 Forward-Port-Of: odoo/enterprise#114055
This update fixes an error in how degressive assets are depreciated when companies use shortened fiscal years. Previously, depreciation entries were incorrectly skipped for months within the wrong fiscal year. The fix ensures accurate depreciation calculations by correctly determining the start date of the next fiscal year, preventing missed entries and improving financial reporting.
Original PR description
When a company has a shortened fiscal year defined via account.fiscal.year (e.g. May-December), the depreciation board computation for degressive assets incorrectly computes the start of the next…
When a company has a shortened fiscal year defined via account.fiscal.year (e.g. May-December), the depreciation board computation for degressive assets incorrectly computes the start of the next fiscal year using `date_from + 1 year` instead of querying the actual next fiscal year. This causes entries for the months between the wrong and correct FY start (e.g. January-April) to be skipped entirely. Step to reproduce: - Create a company with a fiscal year starting in May (e.g. May 1st 2025 to 31st December 2025) - Create an asset with a start date in the 1 December 2025, with a 24 months duration and degressive method - Compute the board and observe that entries from January to April 2026 are missing Fix the FY boundary detection in _recompute_board to query the fiscal year containing the day after the current period end, revert the effective_start_date logic in _compute_board_amount that was masking the root cause, and move the prorata date clamping to _create_move_before_date where it is needed for disposal. opw-6016834 Forward-Port-Of: odoo/enterprise#113895 Forward-Port-Of: odoo/enterprise#113521