Wednesday, April 29, 2026
23 changes · saas-19.3
New functionality added to Odoo
This update integrates AI session data into the live chat functionality. The team added a field to the discuss channel to store AI session information, and updated the tests to ensure this data is correctly managed. This improves the AI-powered features within live chat.
Original PR description
Enterprise PR adds `ai_session_ids` field to `discuss.channel`. This commit adapts the tests that check the content put in the frontend store. Enterprise PR: https://github.com/odoo/enterprise/pull/114472
Enhancements to existing features
This update implements changes required by a new Vietnamese tax regulation (Decree 175/2025) regarding VAT rates on specific goods and services. It allows businesses to generate and export Appendix 142 reports, which are necessary for declaring transactions with the reduced 8% VAT rate. Enterprises meeting specific criteria can now avoid submitting this report.
Original PR description
According to Decree 175/2025/NĐ-CP, an decrease of 2% will be applied to a certain goods and services which has 10% VAT rate (from 10% to 8%) and this will be effective until 12/2026 according to Decision 205/2025/QH15. This decision will be considered after that to decide if 8% VAT rate will be still applied. Appendix 142 report is meant to declare those operations and is only for Purchased and Sold goods with 8% VAT rate. For enterprises which satisfies these two following conditions don't have to submit Appendix 142: + Don't have both input and output invoices related to products & services with applied decreased tax rate (8%) + Only have input but not output invoices related to products & services with applied decreased tax rate (8%) We want to allow users to view and export form 01/GTGT and Appendix 142 with xml format from Odoo. task-5498205
Resolved issues and error corrections
A recent update broke the layout of the payment method form in the Safaricom POS module, making it difficult for users to configure payment terminals. This commit resolves the issue by simplifying the view structure, ensuring the form displays correctly and functions as intended. This improves the user experience for configuring Safaricom payment terminals.
Original PR description
The nested `group` elements in the `pos_payment_method_views.xml` view in `pos_safaricom` caused the layout of the form to break when the module is installed. More specifically, the entire right…
This update enhances the bank reconciliation process by displaying the analytic distribution of each reconciliation line. This provides users with clearer insight into where funds are allocated, simplifying the reconciliation process and reducing potential errors. The changes were based on existing bank reconciliation components and improved usability.
Original PR description
For automated reco models, we didn't take the amount into account. That means that some lines could have a suggestion of reco model that makes no sense. This commit will allow to show the analytic distribution of a line in the line to reconcile so that it's clear for the user. (Most of the code is taken from the analytic distribution widget and adapted) Also make the popover works on hover task-5733382 Forward-Port-Of: odoo/enterprise#106118
This update enhances the website builder's AI functionality by adding a reliable way to track launched AI chat sessions. Previously, tracking was fragile due to user edits, now the system uses a standardized 'interface_key' to identify the source of AI sessions, enabling features like blocking website iframes. This improves the stability and functionality of the AI builder.
Original PR description
__Before this commit__ The `ai.session` record linked to a `discuss.channel` is not accessible from the frontend. This is a problem for the website builder AI because in some cases we need to know if…
__Before this commit__ The `ai.session` record linked to a `discuss.channel` is not accessible from the frontend. This is a problem for the website builder AI because in some cases we need to know if an AI chat session was launched from the website builder sidebar. For instance, to implement custom behaviors such as blocking the website page iframe while the AI is thinking. As a workaround, we currently check if the channel agent external identifier corresponds to the website builder AI, however this might be edited by the user, which would break the flow. __After this commit__ The inverse field `ai_session_ids` is added to `discuss.channel`. In practice, there might only be a maximum of one `ai.session` linked to a channel, but we keep it plural as a convention for `One2many` fields. Only the `ai.composer` and the `interface_key` linked to the session are put in the store at the moment, but fields can now be easily added if needed. We can now check for the `interface_key` in the frontend to know from which part of the code an AI session was launched. Those models have also been added to the Hoot mock server. The `action_launch_ai_chat` method is added to the `ai.agent` mock model and returns the session and the composer. task-5411100
The nested `group` elements in the `pos_payment_method_views.xml` view in `pos_safaricom` caused the layout of the form to break when the module is installed. More specifically, the entire right column of the form loses all the field labels, making it very difficult to fill out the information to configure a payment terminal. This commit fixes the issue by removing the `group` elements from the view, instead just using the `field` elements directly as is done in other payment terminal modules. Before (Safaricom selected): <img width="678" height="504" alt="image" src="https://github.com/user-attachments/assets/9c41643f-1a98-4e44-9493-f0e6e8161a50" /> Before (Viva selected): <img width="674" height="371" alt="image" src="https://github.com/user-attachments/assets/409f5c7a-da13-4f90-8145-a1ed5d6bbf7f" /> After (Safaricom selected): <img width="674" height="531" alt="image" src="https://github.com/user-attachments/assets/a3118563-39a3-4c41-a807-296e531abe58" /> After (Viva selected): <img width="665" height="447" alt="image" src="https://github.com/user-attachments/assets/51140a28-1fca-4d94-a81e-d45e081024a2" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261746
This update resolves a bug that prevented expense card creation when the hr_expense_stripe module was installed without the mail_tracking module. The fix ensures that necessary tracking values are copied, allowing users to successfully process expense cards using Stripe. This improves the reliability of the expense reporting workflow.
Original PR description
In odoo/odoo#235719, the tracking values have been moved to a separate module. Step to reproduce: - Install hr_expense_stripe_demo without mail_tracking (or uninstall it) - Setup the stripe issuing account - Create an employee - Create a card and assign that employee - It will fail with a tracking since `tracking_value_ids` doesn't exist on the message
This update resolves a bug where pasting a list item directly into the HTML editor would cause the main content area of the application to disappear after saving. The fix ensures that newly pasted list items are correctly wrapped within a list container, preventing the browser from incorrectly removing surrounding elements.
Original PR description
Problem: Pasting a `<li>` element inside a header block caused `<main>` and `<footer>` to disappear after saving. The browser's HTML parser ejects everything following an orphaned `<li>` (one without a `<ul>`/`<ol>` parent) out of its ancestor tree. Cause: The root cause was `closestElement(selection.anchorNode, listElementSelector)` finding a `<ul>`/`<ol>` ancestor that was not a direct parent of the insertion point, resulting in a `<li>` being inserted without a wrapping list element. Steps to reproduce: - Copy a `<li>` element and paste it in the Text Element in the header. - Save - `<main>` content disappears from the page. opw-6113857 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260320
This update resolves an issue where the automated reporting cron job for vendor invoices wasn't correctly identifying the target company in multi-company setups. The fix ensures invoices are fetched from the correct company, preventing errors and improving the reliability of the reporting process. This avoids disruptions to invoice reporting.
Original PR description
In a multi-company context, the cron might be run with a user having a default company that is not the same as the target moves companies, maybe raising a `RedirectionWarning` (if the current company is not fully set-up). This commit ensure to fetch the invoice in move's target company. opw-5225553 Forward-Port-Of: odoo/enterprise#115350 Forward-Port-Of: odoo/enterprise#113254
This update resolves a performance issue that caused slowdowns and crashes when working with many2many fields containing a large number of records. The fix replaces a slow search method with a faster one, ensuring smoother operation and preventing UI freezes for users handling extensive datasets.
Original PR description
### Issue before this commit: When handling many2many fields with a large number of records (e.g., 20k+), the client-side performance degraded significantly. In extreme cases, the browser became…
### Issue before this commit: When handling many2many fields with a large number of records (e.g., 20k+), the client-side performance degraded significantly. In extreme cases, the browser became unresponsive or crashed when triggering onchange or compute logic. ### Steps to Reproduce: Create a computed many2many field. Add it to a form view (can be invisible). Populate the related model with a large dataset (20k+ records). Trigger an onchange that recomputes the field. ### Cause of the Issue: In _applyCommands (LINK case), the system checks for existing record IDs using Array.includes(), which has O(n) time complexity. When handling thousands of records, repeated ID lookups using includes() result in O(n²) complexity. ### With This Commit: Replaced Array.includes() with a Set (Set.has()), reducing lookup time to O(1). The set is updated incrementally as new IDs are added, improving overall complexity to O(n) and preventing UI freezes for large datasets. opw-6122024 Forward-Port-Of: odoo/odoo#261319 Forward-Port-Of: odoo/odoo#260993
The Profit and Loss report for French associations was displaying incorrect financial figures due to an error in the report formulas. This update fixes the inverted signs in the report, ensuring accurate calculations and correct totals for association financial reports. This resolves a key issue impacting financial reporting accuracy.
Original PR description
### Issue: The Profit and Loss report for associations shows incorrect values with inverted signs, leading to wrong totals in the final computation ### Cause: In 19.1, a new fiscal localization package for associations as been added In the report `account_financial_report_l10n_fr_cdr_asso`, all formulas in the `Operating income (I)` section are incorrectly inverted The equivalent section in `account_financial_report_l10n_fr_cdr_column_2024` is correct, where accounts are properly inverted in the formulas ### Steps to reproduce: - Install `l10n_fr_reports` - Create and switch to a French company - In Accounting Settings, select the fiscal localization: `France - Associations accounting plan` - Create and confirm an invoice (any amount) - Open `Profit and Loss` and select `Profit and loss account for associations (FR)` Before the fix, the Operating Income (I) is negative opw-6117967 Forward-Port-Of: odoo/enterprise#114414
This update enhances the accuracy of French tax reports sent to authorities by completing XML data and fixing minor bugs. Specifically, it adds necessary fields and tags to ensure compliance and improves data validation for company information, ultimately streamlining the reporting process.
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 update corrects a bug that was incorrectly generating overtime entries on previous days. The fix adjusts how work entries are regenerated to accurately account for employee timezones, preventing incorrect date calculations and ensuring accurate overtime reporting.
Original PR description
How to reproduce: - Select an employee with an overtime ruleset and work entries based on attendances - Create attendance with an approved overtime - Go to "Work Entries" in Payroll, and regenerate…
How to reproduce: - Select an employee with an overtime ruleset and work entries based on attendances - Create attendance with an approved overtime - Go to "Work Entries" in Payroll, and regenerate the work entries for the following day of the attendance - A new overtime work entry is generated on the first day. Reason: Because of how regenerating work entries is done, the computed date for searching overtime lines took into account the previous day (i.e. regenerating a work entry for a tuesday in an UTC+1 timezone made it so the starting date was on monday at 23:00:00), and since the _read_group only looked at the date part of the time start without taking into account the hour, it included the overtime of the previous day. How it was fixed: The domain now takes into account the timezone of the employee to generate the domain for the _read_group to ensure the correct day is selected Task ID: 5899657 Forward-Port-Of: odoo/enterprise#115289 Forward-Port-Of: odoo/enterprise#107266
This update resolves an issue where commission calculations were failing for recurring subscription orders due to an empty currency rate table. The fix adds a fallback rate, ensuring commissions are correctly applied when currency rates are not populated, leading to accurate commission payouts for subscription-based sales. This improves the reliability of our commission tracking.
Original PR description
Steps to reproduce: 1- Installed sale_commission_subscription and accounting 2- Go to [Sales -> Commissions -> Commission Plans] 3- Create a new commission plan of type MRR, specify a salesperson and approve 4- Go to Subscriptions app and create a new order with a recurring monthly plan and specify the same salesperson 5- Create an invoice for the order and confirm it 6- Go back to the commission plan and click on the Commissions smart button Issue: Commissions show up as 0 Expected behavior: Should have the corresponding commission based on the rate specified Why this happens: The `res_currency_rate` table is empty by default and only gets populated if you are in a multi-currency environment and sync the rates in the settings or by manually making a currency rate entry. Since the commission calculation depends on this table, it results in 0 rows when joining the sub-query. opw-6108580 Forward-Port-Of: odoo/enterprise#114354
This update fixes an error in how tax returns are calculated for companies with multiple branches. Previously, rounding adjustments were incorrectly applied, leading to inaccurate closing entries. The change ensures accurate tax return calculations by isolating company-specific rounding data.
Original PR description
Some countries lile Estonia, Nederlands or France apply a rounding from the tax report by adding a line to the end of the query results representing the sum of the roundings on each line of the tax…
Some countries lile Estonia, Nederlands or France apply a rounding from the tax report by adding a line to the end of the query results representing the sum of the roundings on each line of the tax report. When having a company with branches, the rounding is applying in each closing move (one per company/branch) but the value is coming from the aggregated report lines, this leads to wrong computation of the closing entries. Cause: In `_generate_tax_closing_entries` we loop over each company, therefore `_compute_tax_closing_entry` is called one time for each company, but it uses the report options containing all companies Fix: Use options with only the current company in `_compute_tax_closing_entry` Steps: - Install FR localisation - Select FR company and create two branches - Create, for last month: - 1 bill for parent company (100 with tax 20% G) - 1 invoice per branch (200 and 300 with tax 20% G) - Create a tax return with opining date at the beginning of the current month - Submit the last return and go to the created closing entries -> See that closing entries are wrong opw-5976359 Forward-Port-Of: odoo/enterprise#115116 Forward-Port-Of: odoo/enterprise#110652
This update corrects a technical issue preventing correct export of HK payroll XML files to the IRD platform. The fix includes adding a required file header encoding and a Byte Order Mark (BOM) to ensure the files are properly formatted and accepted by the IRD system. This ensures accurate reporting for Hong Kong payroll.
Original PR description
Following recent tests, we noticed that the encoding used when exporting our XML files doesn't follow the required format. We noticed two issues during testing: - The IRD platform expects the file to have BOM included. - The encoding in the header must be capitalized. We solve this in this commit by prepending the BOM bytes to the xml bytes; and making sure to capitalize the URF-8 in the header. task-6150470 --- Note: There will be a lot to do during forward ports, as these have changed quite a bit. (XML support for the other file types, and a proper testing file, at least) Forward-Port-Of: odoo/enterprise#115530 Forward-Port-Of: odoo/enterprise#115227
This update fixes an issue where refund orders weren't correctly included when calculating outstanding balances. Now, the system accurately reflects all payments and refunds, ensuring accurate due amounts are displayed and settled, particularly when using 'pay-later' payment methods. This improves the reliability of our POS accounting.
Original PR description
Step to reproduce - install "pos_settle_due" - have a customer, A and a pos with payment method "customer Account" - start pos, add 3 qty of product with unit price 10$ with partner A - use payment method "customer Account" i.e. of type "pay_later" (do not invoice orders) - refund 1 qty of previous order using same payment method - go to partner list, notice A has 20$ as due - click on "hamburger btn" > settle due amount Observation: - notice we only get the order amount as due i.e order with 30$ - we should have received the refund order too, so that net due of 20$ can be processed Cause: - currently, we didn't considered refunds orders at all, when settling dues Fix: - now we consider order with total < 0 i.e refund orders to be included for settlement opw-5869313 Forward-Port-Of: odoo/enterprise#114143 Forward-Port-Of: odoo/enterprise#107883
This update resolves a problem where unit prices were not being rounded correctly in Peppol transactions, leading to inaccurate invoice data. This change reverts a previous commit and ensures proper price calculations for Peppol-compliant invoices. It improves the accuracy of financial data for international trade.
Original PR description
This reverts commit d19223a148ab3476b83ed71346eb0712394b7de7. opw-6169870 Forward-Port-Of: odoo/odoo#261941
This update allows accountants to retain important XML files received from KSEF (a Polish tax authority) when processing invoices. Previously, these files were automatically discarded after being used. Now, the XML files are attached to the corresponding invoice, providing a permanent record for compliance and auditing purposes.
Original PR description
Description of the issue this commit addresses: When fetching the bills from ksef, the xml with the data about the move is received, parsed and then discarded but the XML can be required to be kept for longer than ksef keeps it so we are lacking a way for an accountant to download it and store it locally. --- Desired behavior after this commit is merged: When a move is fetched from ksef via an xml file, that file is put as an attachment on the move created with its data. --- task-6076505 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259655
This update corrects a bug in the salary configuration process. Previously, payslips were calculated using outdated salary rules if generated on the contract start date, leading to inaccurate net pay figures. Now, payslips are always generated based on the current date, ensuring correct calculations.
Original PR description
When the salary configurator is used, it generate a simulation payslip to know get a net value based on the gross. It should be done at the current date, because if it is at contract_start day, maybe years ago, it'll use wrong salary rules values to compute it Forward-Port-Of: odoo/enterprise#115319
This update resolves an issue where selling a main asset with a closed child asset resulted in incorrect accounting entries. The fix ensures that only active, non-closed assets are considered during the sale process, preventing double-entry errors and maintaining accurate fixed asset and depreciation calculations. A new test case confirms the resolution.
Original PR description
This commit fixes the double entries created when selling the main asset after disposing the child asset. Previously, the sale of the main asset with a closed child asset created 2 entries which resulted in wrong values in fixed asset, depreciation, and gain accounts. This commit filters the non-closed/non-cancelled assets, while previously it would try to close/sell all assets even if it was already closed/cancelled. Test case added to verify fix. opw-6018649 Forward-Port-Of: odoo/enterprise#115452 Forward-Port-Of: odoo/enterprise#115115
This update fixes an issue where Single Touch Payroll (STP) reports were sometimes missed. The system now uses the payslip's creation date instead of the STP submission date, ensuring all payslips are accurately reported to the ATO, even with delayed payment processing. This improves compliance and data accuracy.
Original PR description
When a payslip is created after the submission of a previous payrun, it should trigger an update event to ensure the missed payslip is reported to the ATO with the totals, including all the slips already paid. It currently uses the submit date of STP to check if it's a missed report. However, sometimes the submit/payment date might be set in the future for a delayed payment of the payrun. In this case, the new payrun should not be considered as a missed payrun as it is still the correct order. This fix uses past payslip dates to check if a payrun is a missed report or not, instead of using the submit/payment date of STP. task-6134865 Forward-Port-Of: odoo/enterprise#114280
This update resolves a critical bug that prevented the AI chat feature from working correctly alongside the FileViewer. It now correctly passes context information and restores the chat overlay, while also preventing AI actions on video files to avoid errors. This ensures a smoother and more reliable experience for users.
Original PR description
*={ai_documents}
- Fix crash caused by calling `.values()` on `_ai_read()` result (list), now using it correctly.
- Correct context passed from FileViewer in ai_documents when launching AI chat.
- Fix AI chat appearing behind FileViewer by updating outdated CSS selector.
- Prevent AI actions on video files by showing a warning instead of attempting unsupported processing.
Backport PR of https://github.com/odoo/enterprise/pull/113287
task-5955968This update fixes an issue where the Belgian payroll system incorrectly parsed birthdates when dealing with 'numéros bis' NISS numbers (which have a 20 or 40-month offset). The change normalizes the month value to ensure accurate date calculations and prevents errors in payroll processing.
Original PR description
The NISS month field can be increased by 20 or 40 for "numéros bis". This caused invalid date parsing. Use modulo 20 to normalize the month before constructing the birthday. task-6144297 Forward-Port-Of: odoo/enterprise#114485