Friday, April 24, 2026
13 changes · saas-18.4
Resolved issues and error corrections
Sales orders now calculate the untaxed amount correctly when early payment discounts are combined with tax-included pricing. This prevents small but visible rounding errors on order totals, improving invoice accuracy and customer trust.
Original PR description
Steps to produce: --- - Install the `Sales` module. - Go to `Invoicing > Configuration > Payment Terms`. - Open `Immediate Payment` and enable Early Discount. - Set `Reduced Tax` to `Always (upon…
Steps to produce: --- - Install the `Sales` module. - Go to `Invoicing > Configuration > Payment Terms`. - Open `Immediate Payment` and enable Early Discount. - Set `Reduced Tax` to `Always (upon invoice)`. - Go to Invoicing > Configuration > Taxes. - Create a 21% tax with `Tax included`. - Create a product with a sale price of 7.50 and assign the tax. - Create a Sale Order with this product > Set Immediate Payment as payment term. Issue: --- - The untaxed amount is computed as 6.22 instead of 6.20. Root cause: --- - At [1], in `_add_base_lines_for_early_payment_discount`, the base lines generated for early payment discount were missing the `special_mode='total_excluded'`. - Consequently, the tax engine interpreted these amounts as tax-included and attempted to recompute the untaxed base, resulting in an incorrect untaxed amount. Solution: --- - Add `special_mode='total_excluded'` to the base lines created for early payment discount computation. - This ensures the discount amounts are treated as already tax-excluded. [1]https://github.com/odoo/odoo/blob/a2b4f618328f3ce3f654fd2c1ee4410365706a7e/addons/sale/models/sale_order.py#L515-L550 opw-6023472 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260480 Forward-Port-Of: odoo/odoo#255724
Non-admin users working in a child company can now open the Accounting Dashboard when a journal has a specific currency set. This prevents an access error and keeps accounting overview access consistent across company setups.
Original PR description
Backport of https://github.com/odoo/odoo/commit/e371eb4a1717bfeb65ad756287249a2fb3b13e4f Issue before this commit: Opening the Accounting Dashboard from a child company as a non-admin user raises an…
Backport of https://github.com/odoo/odoo/commit/e371eb4a1717bfeb65ad756287249a2fb3b13e4f Issue before this commit: Opening the Accounting Dashboard from a child company as a non-admin user raises an Access Error when the journal has a currency_id set. The error occurs with journal which currency id is set Steps to Reproduce: - Install the account module. - Create a child company - Create a journal with a currency set - Log in as a non-admin user. - Select only the child company - Open Accounting (Dashboard) Cause of the Issue: When the journal does not have a currency_id, the system reads company data using sudo(), so no access issue occurs. When the journal has a currency_id, sudo() is not used, and reading the company name triggers an Access Error. With This Commit: Bypass record rules when reading the company name if the journal has a currency_id. opw-6048025 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261043
Kit product costs are now calculated per unit instead of using the full bill-of-materials batch cost. This prevents inflated margins or costs on sales orders when kits are defined in larger production quantities.
Original PR description
### Issue: When a kit BoM has `product_qty` > 1 (e.g. 12 Kit X = 12 Comp A + 12 Comp B), the SO line cost after confirmation is multiplied by the batch size. Selling 1 Kit X shows a cost of 360…
### Issue: When a kit BoM has `product_qty` > 1 (e.g. 12 Kit X = 12 Comp A + 12 Comp B), the SO line cost after confirmation is multiplied by the batch size. Selling 1 Kit X shows a cost of 360 instead of 30. ### Cause: The method `_compute_average_price` uses `bom.explode(self, 1)`, which returns raw BoM line quantities for one full batch. It accumulates the total batch cost but returns it without dividing by `bom.product_qty`. ### Steps to Reproduce: - Costing Method = AVCO, Inventory Valuation = Automated - Comp A (cost 10), Comp B (cost 20), Kit X (cost 0) - Kit BoM: 12 Kit X = 12 x Comp A + 12 x Comp B - Create and confirm a SO for 1 x Kit X - Expected SO line cost: 30 - Actual SO line cost: 360 Solution: This fix mirrors the normalization already done in `_compute_bom_price`, which correctly divides by `bom.product_qty` and converts UoMs. opw-5969310 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253948 Forward-Port-Of: odoo/odoo#253406
Fixed an issue where swiping between app settings on mobile could leave users with a blank page. The settings screen now waits for the next page to finish loading before completing the swipe, making mobile navigation more reliable.
Original PR description
Before this commit, swiping between settings for different apps on mobile devices would often result in a blank page. This occurred because the swipe method did not wait for the target page to render completely before completing the transition. This commit ensures the swipe action waits for the rendering process, preventing the blank state during app navigation. Forward-Port-Of: odoo/odoo#260737 Forward-Port-Of: odoo/odoo#260563
Fixed an issue where website menu items with spaces and no leading slash could keep leading visitors to a 404 page after a page was created from that URL. The menu editor now also warns users when a URL contains spaces, helping avoid confusion because those URLs are automatically converted into cleaner page addresses.
Original PR description
When a menu item URL contains a space and has no leading slash (e.g., "some url"), creating a page from its 404 screen does not link the menu to the newly created page. The menu keeps pointing to a…
When a menu item URL contains a space and has no leading slash (e.g., "some url"), creating a page from its 404 screen does not link the menu to the newly created page. The menu keeps pointing to a 404. **Steps to reproduce**: 1. Create a menu item with a URL containing spaces and no leading slash (e.g., "some url"). 2. Click the menu item -> a 404 page is displayed (expected). 3. Click "Create Page" -> the page is created and saved. 4. Click the menu item again -> it still returns a 404 (unexpected). **Issue**: During page creation, the path is slugified (e.g., "some url" -> "/some-url"). The controller then tries to link the menu to the new page by setting `page_id`. However, `pagenew()` only searches for menu URLs with a leading slash, so a menu saved as "some url" is not found when searching for "/some url". As a result, `page_id` is never set, and `_clean_url()` keeps resolving the menu to "/some url" instead of the page's actual URL "/some-url". Menus without spaces (e.g., "mypage") have the same issue where `page_id` is not set, but since `_clean_url()` prepends "/" and renders "/mypage", which matches the new page URL, the menu still resolves correctly. **Fix**: Match both URL formats (with and without leading slash) when linking a menu to a newly created page. Additionally, a warning is now shown in the menu editor when a URL contains spaces, since spaces are slugified during page creation, which could cause confusion. (Note: this is only a warning - URLs with spaces are still allowed.) task-[5095646](https://www.odoo.com/odoo/project/974/tasks/5095646) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260726 Forward-Port-Of: odoo/odoo#248967
This update fixes a problem in the HTML editor where removing formatting from content that included a colored icon could trigger an endless loop and crash. Users can now safely clear formatting in descriptions and other rich-text fields without interrupting their work.
Original PR description
Steps to reproduce: =================== 1. Open the To-do app and pick any task. 2. In the description add text and an icon with a bg color. `(you can add this: <i class="fa rounded rounded-circle…
Steps to reproduce: =================== 1. Open the To-do app and pick any task. 2. In the description add text and an icon with a bg color. `(you can add this: <i class="fa rounded rounded-circle fa-user bg-o-color-1 fa-4x" contenteditable="false"></i>)` 3. Select all and click "Remove format". Result: -> Traceback due to an infinite loop. Cause: ====== Remove format calls `removeAllColor()`, which loops forever at: https://github.com/odoo/odoo/blob/626bde21a25366d0bb29662bae2057c247a1638e/addons/html_editor/static/src/main/font/color_plugin.js#L194-L194 Why: _applyColor doesn't remove the icon's background class, so hasAnySelectedNodeColor keeps returning true and the removal loop never terminates. This happens because `font` is already the `<i>` element with the `fa` class, using `querySelectorAll` on it won't include the element itself, so the icon is never checked or updated. https://github.com/odoo/odoo/blob/6cdc6f55886ea48e90f9023a6c6142bf072745b9/addons/html_editor/static/src/main/font/color_plugin.js#L290 Solution: ========= Check if the font itself has the fa class before doing the `querySelectorAll`, and include it in the nodes to check for color. Test Impact: ============ Before this fix, a `<span>` containing an icon was wrapped in a `<font>` when applying color, treating the icon as a normal span (without size) instead of applying the color directly. https://github.com/odoo/odoo/blob/8792c2d38eb0aadac8d778d83fd76f270404ecd5/addons/html_editor/static/src/main/font/color_plugin.js#L397 opw-5928627 Forward-Port-Of: odoo/odoo#249538 Forward-Port-Of: odoo/odoo#248449
This update fixes an issue where VAT reports were incorrectly using the company's VAT number instead of the fiscal position's foreign VAT ID. This ensures accurate tax reporting for businesses using foreign VAT schemes, particularly in countries like Belgium. The change corrects a data mismatch in generated reports.
Original PR description
### Issue: When a fiscal position defines a `foreign_vat`, tax reports generated for that country still use the company's VAT number instead For example, with a Belgian fiscal position using…
### Issue: When a fiscal position defines a `foreign_vat`, tax reports generated for that country still use the company's VAT number instead For example, with a Belgian fiscal position using `BE010203040`, the generated BE VAT report uses the company VAT instead of `010203040` ### Cause: The report generation did not check whether there is a fiscal position with a `foreign_vat` matching the country of the report ### Note: The example above uses a Belgian fiscal position to reproduce the issue Starting from 19.0, this specific flow is blocked because Intervat is enabled in production mode by default A related fix makes the Intervat settings available in that case Until then, the issue can be reproduced by temporarily commenting out: https://github.com/odoo/enterprise/blob/5fb58a9b7b3ae89f87e84d4ba1fa3a16237d80ac/l10n_be_intervat/models/account_return.py#L15 ### 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 - Create and confirm an invoice for a Belgian customer: - Fiscal Position: Belgium - Any product with a Belgian tax - Invoice Date: 01/01/2026 - Open the Tax Report and select `VAT Return (BE)` for January - Click `Returns` and select the full year - Mark the December return as Completed from the three-dot menu - Review January and fill the missing company data (TIN: 1111111, phone and email) - Click `Validate -> Lock -> Submit` ### Before the fix: The generated XML uses the company VAT number (`1111111`) instead of the fiscal position foreign VAT (`010203040`). opw-6076540 Forward-Port-Of: odoo/enterprise#112610
This update addresses a critical issue where Odoo would crash when attempting to download a URL document alongside a spreadsheet. The fix ensures stable and reliable downloading of both document types, improving user experience and preventing data loss. This resolves a reported bug impacting users accessing and sharing documents.
Original PR description
Try to download a url document along with a spreadsheet. `onDownload` crash when trying to download a url document. Task: 5485662 Forward-Port-Of: odoo/enterprise#113645 Forward-Port-Of: odoo/enterprise#112513
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 fix 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#110652
This update fixes a security issue where unauthorized users could access asset information within invoices. Now, access to assets is restricted to specific user groups within the accounting module, preventing potential data breaches and ensuring data integrity. This change enhances the security of our invoicing process.
Original PR description
Only groups `account.group_account_readonly`, `account.group_account_invoice` or higher have access to model `account.asset`, therefore if an user goes to see an invoice with assets and they are not on either group, they will receive an error and won't be able to access said invoice. How to reproduce: - Create a vendor bill - Create an account.asset and link it to said account.move - Go to the form view with an user that it's on group "Purchase: User" for example --> They get a traceback --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#113858 Forward-Port-Of: odoo/enterprise#112890
This update resolves an issue where the DIAN web service was incorrectly overwriting customer contact information (names and emails) with fiscal data, leading to data loss and incorrect invoice delivery. The fix now intelligently handles email differences, creating a new contact if needed and giving users control over their existing data.
Original PR description
The DIAN web service was overwriting partner names and emails with fiscal data, causing data loss for CRM contacts. The fiscal email often differs from the commercial one, and the overwrite broke the sales flow by sending invoices to the wrong address. Users had no standard workaround short of manually re-entering emails after every invoice generation. Instead of blindly overwriting, only update empty fields and create a child invoicing contact when the DIAN email differs from the existing one. Also remove the automatic onchange and periodic re-fetch triggers to leave existing data under user control. task-5912005 Forward-Port-Of: odoo/enterprise#114017
This update resolves an issue where the minimum IS (Insurance Savings) amount was incorrectly calculated in the Swiss payroll module. The change ensures accurate IS calculations for Swiss employees, aligning with local tax regulations. This update improves the reliability of payroll reporting for our Swiss clients.
Original PR description
Forward-Port-Of: odoo/enterprise#114463
This update fixes a problem where opening a restaurant order with an active Fiskaly transaction on a second device would cause duplicate transaction attempts and errors. The fix ensures that transaction state information is properly saved and shared between devices, preventing these errors and improving the reliability of the POS system.
Original PR description
In a restaurant POS, when an order with an active Fiskaly transaction is opened on a second device, `transactionState` and `tx_revision` were not available (uiState is not persisted to the server), causing the new device to attempt creating a duplicate transaction with a stale revision, which resulted in a Fiskaly API error. opw-6147654 Forward-Port-Of: odoo/enterprise#114911 Forward-Port-Of: odoo/enterprise#114599