Saturday, April 25, 2026
18 changes · saas-19.3
Resolved issues and error corrections
This update fixes an issue where draft stock moves were incorrectly flagged as unavailable, even when sufficient stock existed. The fix adjusts how availability is calculated to accurately reflect available quantities, ensuring accurate forecasting and preventing fulfillment delays. This improves the reliability of stock management.
Original PR description
Steps to reproduce: - Create a storable product "P1" - Update on-hand quantity to 2 units - Create a delivery with 2 units of P1 and keep it in draft state Problem: The forecast availability is…
Steps to reproduce: - Create a storable product "P1" - Update on-hand quantity to 2 units - Create a delivery with 2 units of P1 and keep it in draft state Problem: The forecast availability is displayed in red (not available), even though the stock is sufficient to fulfill the move. Explication: For draft consuming moves, the forecast availability is computed as: `virtual_available - move.product_qty` In the case where stock exactly matches the demand, this results in 0. However, on the JS side, availability is evaluated with: `forecast_availability >= product_qty` So with forecast_availability = 0 and product_qty = 2, the condition evaluates to False, incorrectly marking the move as not available. https://github.com/odoo/odoo/blob/c7fede7f44c668ccc0a094d8341c3cae8879a7f1/addons/stock/static/src/widgets/forecast_widget.js#L31 Solution: When the available quantity is sufficient to cover the move (using float_compare), set forecast_availability to the full available quantity instead of subtracting the move quantity. This ensures the JS condition correctly evaluates to True and the move is marked as available. opw-5159142 Forward-Port-Of: odoo/odoo#260489 Forward-Port-Of: odoo/odoo#257354
This update resolves an issue where downloading attachments from Odoo's mobile app was failing due to incorrect URL formatting. The fix ensures that attachment URLs are properly handled, allowing users to download files from the chatter feature without errors. This improves the mobile user experience.
Original PR description
In Odoo 18.4+, downloading attachments from the chatter is broken.
See: https://github.com/odoo/odoo/pull/200099
The `onClickDownload` function now passes an absolute URL to `downloadFile`.
The download function is implemented natively in the mobile apps.
The Android implementation always prefixes the provided URL with the
database origin (i.e.: `https://example.odoo.com`).
`download({url: "https://example.odoo.com/web/content"})` will try to
download `https://example.odoo.comhttps://example.odoo.com/web/content`.
This results in an UnknownHostException.
We can remove the origin from the url before calling the native method.
By doing this on the JS side, there is no need to update the Android app.
opw-6033150
Forward-Port-Of: odoo/enterprise#114832This update fixes an issue where signatures added to documents caused a loss of original PDF structure and settings. Now, the system duplicates the original document before applying signatures, ensuring the full document layout, bookmarks, and metadata are preserved. This improves the reliability and usability of signed documents.
Original PR description
Instead of rebuilding the PDF by copying content, metadata, and bookmarks, we now duplicate the original document first and then apply the signature overlays. This ensures the full structure and settings are preserved without loss. task-6083291 Forward-Port-Of: odoo/enterprise#114618
This update resolves an issue where role mentions within the full composer weren't working correctly, leading to emails being sent to the wrong addresses or failing to send at all. The fix ensures accurate role mentions are displayed and utilized, improving the reliability of email communication within Odoo. This enhances the user experience and prevents potential communication errors.
Original PR description
There is an issue when tagging a role using the full composer: 1. Emails are sent to the wrong address or sometimes no address at all 2. The displayed URL is not correct This commit fixes the issue by correctly rendering the mention block for roles in the full composer, using the correct configuration. task-6139162 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260750 Forward-Port-Of: odoo/odoo#260094
This update enhances the account reports experience on mobile phones and tablets by ensuring the chatter is always visible and the annotation icon is consistently accessible via touch. Previously, the chatter was hidden on smaller screens, making it difficult to use. This change improves usability and allows users to easily engage with reports on any device.
Original PR description
Previously, the chatter was hidden on device too smalls and the annotation icon was only visible with hover so not visible on touch devices such as phones or tablets. Now, we have the chatter at the bottom when the device is too small and always display the annotation icon on touch devices. task-5106852 Forward-Port-Of: odoo/enterprise#114700 Forward-Port-Of: odoo/enterprise#95737
This update fixes an issue where Mercado Pago webhooks with invoice references containing slashes (like INV/2026/00001) were not being correctly processed, resulting in 404 errors. The change allows the webhook to handle these references, ensuring accurate processing of Mercado Pago payments. This improves the reliability of payment processing.
Original PR description
Currently, the mercado_pago_webhook http route only takes into consideration 1 url segment. This means that invoices with references like INV/2026/00001 don't match any defined route and the server returns a 404. /payment/mercado_pago/webhook/S00001 => OK /payment/mercado_pago/webhook/INV/2026/00001 => KO This commit allows references with slashes to be matched by the route by capturing the entire remaining url path including the slashes. /payment/mercado_pago/webhook/S00001 => OK /payment/mercado_pago/webhook/INV/2026/00001 => OK opw-6035161 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259933 Forward-Port-Of: odoo/odoo#259378
This update ensures that Brazilian tax documents (EDI) accurately reflect tax amounts as required by Brazilian law. Previously, these approximate tax values were missing, and this fix incorporates them from Avalara's calculations, ensuring compliance and accurate reporting.
Original PR description
All fiscal documents are required by Brazil law to include the approximate value of fed, state, and city taxes that affect it. Avalara already provides back these values in their tax calculation response, we just missed sending it to the EDI. This commit takes the information from that response and adds it to the EDI payload to make sure that it is generated properly into the generated documents. We are required to always show this even if there are no informative taxes as such we combine it with the T&C sent already. task-5478059 Forward-Port-Of: odoo/enterprise#113732
This update resolves an issue where the minimum IS (Insurance Savings) amount was incorrectly calculated in the Swiss payroll module. The change ensures accurate reporting of IS contributions, aligning with Swiss tax regulations. This correction improves the reliability of payroll data for Swiss businesses using Odoo Enterprise.
Original PR description
Forward-Port-Of: odoo/enterprise#114463
This update fixes a confusing error message that appeared when employees changed their contracts and working schedules, particularly when leaves were involved. The fix now includes the original error traceback, providing developers with more information to quickly diagnose and resolve the issue. This improves the overall stability and usability of the HR module.
Original PR description
A validation error is raised if changing employee's contract with a new working schedule on a period with leaves and the new working schedule changes the duration of these leaves in such a way that the employee no longer has the required allocation for them. This adds to the error message the original error traceback for debuggig purposes. Task: 6105516 Forward-Port-Of: odoo/odoo#258280
This update fixes an issue where the system incorrectly calculated available stock when creating procurements through the MTSO method. Specifically, it ensures that stock availability is accurately considered across multiple levels of a product's bill of materials, preventing overestimation of required quantities. This improves the accuracy of purchase order generation and reduces potential stock discrepancies.
Original PR description
When creating a procurement through mtso, if the product has a muti level bom with the same component at multiple levels, it will consider the available quantity multiple times. Steps to reproduce:…
When creating a procurement through mtso, if the product has a muti level bom with the same component at multiple levels, it will consider the available quantity multiple times. Steps to reproduce: ------------------- * Enable MTO and change supply method to: "Take From Stock, if unavailable, Trigger Another Rule" * Create three products : final, semi, component - final: mtso, manufacture - semi: mtso, manufacture - component: mtso, buy, on hand quantity to 4 * Create a bom for final: - 10 components - 1 semi * Create a bom for semi: - 10 components * Create and confirm a MO for 1 "final" -> Issue the purchase order is only for 12 components and not 16. Observation: ------------- When confirming our MO, it will create a manufacture procurement for the products. The procurement will recursively create procurements and stock moves for each of its components. https://github.com/odoo/odoo/blob/b0b8a102153eaa9231321524ec5140cc6d754502/addons/stock/models/stock_move.py#L1563-L1571 Since its a MTSO, it will first check the products if there is available products in stock (free_qty) and create the procurement for the missing quantity: https://github.com/odoo/odoo/blob/b0b8a102153eaa9231321524ec5140cc6d754502/addons/stock/models/stock_move.py#L1646-L1647 https://github.com/odoo/odoo/blob/b0b8a102153eaa9231321524ec5140cc6d754502/addons/stock/models/stock_move.py#L1657-L1663 And each procurement, if it is of the manufacture type, will create corresponding procurements for their components. Once all the procurements and stock moves have been created, the stock move will confirmed and assigned. https://github.com/odoo/odoo/blob/942cbbbf243ff28f84fdaa40ed73b6572e0032a6/addons/stock/models/stock_move.py#L1627-L1629 -> The issue arise because the free_qty will only be updated when the stock moves are assigned which happen after all the procurement quantity are calculated for all the levels. opw-5514788 Forward-Port-Of: odoo/odoo#253958
This update corrects a technical issue that was preventing users from accessing the Mobile Menu (QR ordering) or Self-Ordering interface in Odoo Enterprise. The fix involved updating a field name within the POS data loading process, ensuring these key ordering features are now functioning correctly.
Original PR description
## Overview Accessing the Mobile Menu (QR ordering) or Self-Ordering interface crashes after installing `pos_blackbox_be` on SaaS-19.1. The interface fails to load due to a missing field in the POS…
## Overview Accessing the Mobile Menu (QR ordering) or Self-Ordering interface crashes after installing `pos_blackbox_be` on SaaS-19.1. The interface fails to load due to a missing field in the POS data loading flow. ## Steps to Reproduce 1. Install `pos_blackbox_be` 2. Open POS 3. Access the Mobile Menu (QR code) or Self-Ordering page ## Current Behavior - A traceback is raised - The interface does not load ## Root Cause The method `_load_pos_self_data_fields` returns the field: iface_fiscal_data_module However, from SaaS-19.1 this field was renamed to: iot_fdm_be_id This mismatch causes the POS self-ordering data loading to fail. ## Fix Updated the returned field to match the new field name. # Before return fields + ['iface_fiscal_data_module'] # After return fields + ['iot_fdm_be_id'] ## Impact - Restores proper loading of Mobile Menu (QR ordering) - Fixes Self-Ordering interface crash opw-6044883 ## Reproduction Video https://drive.google.com/file/d/1R5TYVIXvtts12YLF5iB4GKZirMZePoGr/view?usp=sharing Forward-Port-Of: odoo/enterprise#114357
This update resolves an issue where deleting a project stage caused unexpected view navigation and the display of archived tasks. The fix ensures the original view remains active, the stage is properly deleted, and the user's intended task list is presented without disruption. This improves the user experience when managing project stages.
Original PR description
# Steps to reproduce 1. Create a project 2. Create a stage 4. Remove the stage # Current behavior Instead of remaining in the project tasks view, it switches to the tasks view filtered with the current project. Additionally, it displays archived tasks because no filter is selected, thereby discarding original ones. This also applies to stage deletion in other views (e.g., My Tasks), where the search filters are completely discarded. # Expected behavior The dialog should be closed, the stage should be deleted, and the original view should remain active. This is done through a soft-reload of the page, ensuring the original view is kept, together with original breadcrumbs, and the stage is visually disappearing. task-5498274 Forward-Port-Of: odoo/odoo#260213 Forward-Port-Of: odoo/odoo#246935
This update ensures that the default website correctly reflects the latest sequence order, even in incognito browsing sessions. Previously, changes to website sequence didn't update the default website selection. This fix resolves an issue where the lowest sequence website wasn't consistently being served as the default.
Original PR description
**Problem:** Changing the order of websites does not update which website is shown as the default when visiting from an incognito window (no domain match). **Steps to reproduce:** 1. Create two…
**Problem:** Changing the order of websites does not update which website is shown as the default when visiting from an incognito window (no domain match). **Steps to reproduce:** 1. Create two websites with no domain set 2. Change their sequence order via the handle widget in the backend 3. Open an incognito window 4. The default website shown is still the old one **Current behavior:** The default website does not change after reordering. **Expected behavior:** The website with the lowest sequence should be served as the default. **Cause of the issue:** Commit d6f4af2790a0 replaced `models.Model` with `models.CachedModel` and removed the blanket `self.env.registry.clear_cache()` from the top of `write()`. CachedModel only auto-clears caches for fields listed in `_cached_data_fields`, but `sequence` is not in that list. As a result, `_get_current_website_id` (decorated with `@tools.ormcache`) keeps returning the stale cached website ID after a sequence change. https://github.com/odoo/odoo/commit/d6f4af2790a0abacba6e616b00d999eddc30edc9#diff-5e92e473fa4d3da6db7ef727fb217dad51ef6c2383913edca73fe040a23e82c2L339-L341 **Fix:** Restoring `clear_cache()` scoped to the existing sequence/company_id check ensures the ormcache is invalidated only when relevant fields change, rather than on every write as before. opw-6102426 Forward-Port-Of: odoo/odoo#257913
This update resolves a technical issue that was limiting the efficiency of WhatsApp marketing automation. Previously, the system wasn't processing all relevant messages at once, leading to slower performance. This change ensures that all necessary steps are executed, resulting in faster and more reliable automation for WhatsApp marketing campaigns.
Original PR description
Forward-Port-Of: odoo/enterprise#114570
This update corrects a bug where sales orders were incorrectly linked to manufacturing orders, and vice versa, even when the orders were unrelated. The fix ensures that manufacturing orders only link to sales orders, and purchase orders only link to the sales order they originate from, improving data accuracy and streamlining workflows.
Original PR description
**Steps to reproduce:** * Install modules: *mrp*, *purchase*, *sale_management*. * Go to *Settings* and enable: * *Multi-Step Routes* * *Replenish on Order (MTO)* * *Dropshipping* * Create a…
**Steps to reproduce:**
* Install modules: *mrp*, *purchase*, *sale_management*.
* Go to *Settings* and enable:
* *Multi-Step Routes*
* *Replenish on Order (MTO)*
* *Dropshipping*
* Create a *Dropship* product:
* Set route to *Dropship*.
* Add a vendor under the *Purchase* tab.
* Create an *MTO* product:
* Set route to *Replenish on Order (MTO)*.
* Configure a *Bill of Materials (BoM)*.
* Create a *Sales Order*:
* Add both products.
* Confirm the order.
* Open the Sales Order:
* Observe smart buttons for *Delivery*, *Purchase*, and *Manufacturing*.
* Open the linked *Purchase Order* and *Manufacturing Order*.
**Observed behavior:**
* The *Purchase Order* shows a smart button linking to a *Manufacturing Order*.
* The *Manufacturing Order* shows a smart button linking to a *Purchase Order*, even when unrelated.
**Expected behavior:**
* The *Purchase Order* should only show a smart button linking to the *Sales Order*.
* The *Manufacturing Order* should only show a smart button linking to the *Sales Order*.
* No cross-link between unrelated PO and MO should be displayed.
**Cause:**
* The SO pushes the `stock.reference` into procurement values: https://github.com/odoo/odoo/blob/8a871a120b75f7c09c70dbf07530239244dbb5d6/addons/sale_stock/models/sale_order_line.py#L289
* The same reference is propagated to:
* Purchase Orders: https://github.com/odoo/odoo/blob/8a871a120b75f7c09c70dbf07530239244dbb5d6/addons/purchase_stock/models/stock_rule.py#L355
* Manufacturing Orders: https://github.com/odoo/odoo/blob/8a871a120b75f7c09c70dbf07530239244dbb5d6/addons/mrp/models/stock_rule.py#L184
* Opening the *Purchase Order* form triggers `_compute_mrp_production_count`.
* This compute calls `_get_mrp_productions()`: https://github.com/odoo/odoo/blob/8a871a120b75f7c09c70dbf07530239244dbb5d6/addons/purchase_mrp/models/purchase.py#L21
* That method returns `self.reference_ids.production_ids`.
* Since the MO shares the same sale reference, the PO incorrectly fetches that MO and shows the *Manufacturing* smart button.
* Similarly, opening the *Manufacturing Order* form triggers `_compute_purchase_order_count`.
* This compute calls `_get_purchase_orders()`, which returns `self.reference_ids.purchase_ids`.
* Since the dropship PO shares the same sale reference, the MO incorrectly fetches that PO and shows the *Purchase* smart button.
**Fix:**
* Stop relying on shared `reference_ids` to compute links.
* Instead, follow the actual stock and procurement chain:
* For *MO → PO*:
* Use raw material moves to find related purchase lines: `self.move_raw_ids.created_purchase_line_ids.order_id | self.move_raw_ids.purchase_line_id.order_id`
* For *PO → MO*:
* Use stock move destinations to identify consuming productions.
* This ensures:
* MOs link only to POs supplying their raw materials.
* POs link only to MOs they actually replenish.
* Unrelated documents sharing the same sale reference remain isolated.
---
opw-6008943
---
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#254292This update resolves an issue where deferred invoice moves weren't consistently linked to the correct customer partner. The change ensures that the partner ID is taken directly from the original invoice line, improving data accuracy and preventing discrepancies in financial reporting. This enhances the reliability of deferred accounting processes.
Original PR description
When creating deferred move lines, the `partner_id` could be incorrectly influenced by the `default_partner_id` context key (e.g., when generating an invoice from a Sales Order). This led to inconsistencies where the deferred move lines did not match the partner on the original invoice line. This commit ensures the `partner_id` is explicitly taken from the source invoice line, guaranteeing data integrity across all deferred move lines. Steps: - Create a sale order for partner X, receive and confirm it - Create the invoice from the SO - Change partner to Y but keep X as delivery partner (not essential to reproduce bthough) - Set a deferred start date and a deferred end date on the invoice line, covering two full months - Confirm the invoice and open deferred moves via the smart button -> Note that one deferred move's lines get the partner id from the SO instead of the invoice opw-6095711 Forward-Port-Of: odoo/enterprise#115026 Forward-Port-Of: odoo/enterprise#114439
This update resolves an issue where creating a filter with invalid data in Odoo views would cause the application to crash. While the fix prevents the crash, it also means the filter isn't active. This change improves stability and prevents disruptions to user workflows when creating filters.
Original PR description
On some view, create and edit a filter, but put something unparseable by JS in the `context` field eg: `{123}`.
Go back to the view.
Before this commit there was a crash, because the python parser in JS crashed.
After this commit, there is no crash, the filter is visible but not activable.
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#260999
Forward-Port-Of: odoo/odoo#260612This update corrects a critical 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 separate invoicing 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#115018 Forward-Port-Of: odoo/enterprise#114017