Friday, April 17, 2026
12 changes · saas-18.4
Resolved issues and error corrections
Mercado Pago payment notifications can now be received correctly when an invoice reference includes slashes, such as INV/2026/00001. This prevents missed webhook updates and 404 errors for affected payments, helping payment statuses update reliably.
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#259378
Stock quantity records are now shown only to the company that owns the related product. This prevents users in another active company from seeing inventory records they cannot open, reducing confusion and access errors in multi-company workflows.
Original PR description
**Purpose:** Since a stock.quant is a combination of the stock move lines of a product and a location, it should be restricted by the product's company. **Before this commit:** In a multi-company…
**Purpose:** Since a stock.quant is a combination of the stock move lines of a product and a location, it should be restricted by the product's company. **Before this commit:** In a multi-company environment. If a purchase order with product from company 1 is being confirmed, received, and validated when company 2 is being selected as the primary active company while company 1 is also checked. It will create a stock.quant that is searchable for company 2. However, it will raise an error when company 2 is trying to access it. **After this commit:** Even if the stock.quant is created when company 2 is the primary active company, it will not be searchable for company 2 since the product's company is company 1. **Steps to Reproduce on Runbot:** - Create a storable product exclusive to Company A - Create & validate a receipt for that product in Company A. - Switch to Company B -> Reporting > Locations > Remove all filters: The negative quant for the product in Partners/Vendors is visible. opw-6082330 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259272 Forward-Port-Of: odoo/odoo#257211
This fixes how rounding amounts are calculated in UBL/CII electronic invoices when down payments are involved. It helps ensure invoice totals and tax details remain accurate, reducing the risk of incorrect exported invoice data.
Original PR description
'total_excluded_currency' is for the base amount. 'base_amount_currency' should be used only when getting the base per tax. When dealing with a down payment, a distortion in the taxes amounts might be introduced to ensure the total of the invoice is exactly the expected one. opw-6060486 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259426
This fix ensures the Point of Sale only loads the employees configured for the session instead of loading all employees in certain setup cases. This helps keep POS sessions more efficient and avoids exposing unnecessary employee information to the POS interface.
Original PR description
Before this commit, when some employee was assigned to advanced or minimal employee, all of the employees were loaded in the POS session, because there was no basic employee assigned to the POS config. opw-5898068 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247043
Fixes an issue in the website builder where documents uploaded while replacing existing media were not prepared correctly for inline translation. It also restores expected document selection behavior in the media dialog, so website editors can open and replace documents more consistently.
Original PR description
[FIX] website: translate links inline on media replacement On the website builder, files added through the `/file` command would go through the domPlugin `insert` method, which would call…
[FIX] website: translate links inline on media replacement
On the website builder, files added through the `/file` command would go
through the domPlugin `insert` method, which would call
`before_insert_processors` and apply `.o_translate_inline` as expected.
But there is another flow to add a document on the page: replace an
image (or video, or icon), then select the "Documents" tab and upload
a file. With this flow, `insert` is not called, so we have to add the
class through some other resource.
[FIX] html_editor: target documents with right class
The class `.o_image` was still associated with documents (in the context
of the file selector) and the expected tag of a document was `A`, in
spite of it not being true in `html_editor` since the introduction of
the file box in [1].
This has also been updated in the website builder since the introduction
of the `html_builder` module in 18.4, which swapped uses of `web_editor`
components for `html_editor`.
As a side-effect, in website, a double click on a file did not open the
media dialog on the "document" tab, unlike other media (images, videos,
icons). In such a case, the file was also not shown as already selected
in the media dialog (because it targetted the wrong tag name). Both of
those behaviors were lost as we used the new file box design in 18.4.
[1]: https://github.com/odoo/odoo/commit/7f9afa21dffba2f74f9fb8a68809db4af6c7c225
task-5876278Purchase receipts now use the destination configured on the receipt operation type when it points to a warehouse sub-location. This keeps forecasted quantities aligned with where goods are actually expected to arrive, avoiding misleading stock forecasts for teams using sub-locations.
Original PR description
### **Description of the issue/feature this PR addresses:** **Issue:** In Odoo 18/19, purchase move lines default to the WH's main stock location (`lot_stock_id`) as the `location_final_id`. However,…
### **Description of the issue/feature this PR addresses:** **Issue:** In Odoo 18/19, purchase move lines default to the WH's main stock location (`lot_stock_id`) as the `location_final_id`. However, when a user configures a sub-location on the Receipt Operation Type, the picking destination is correct, but the move lines are defaulted to the main warehouse. This mismatch causes the Forecasted Quantity to not increment for the intended sub-location **Solution:** Prioritize the `default_location_dest_id` before falling back to the default stock location opw-6032018 ### **Current behavior before PR:** When confirming a PO, the `location_final_id` on stock moves defaults to the `lot_stock_id`, regardless of the specific destination set on the Operation Type. This causes a mismatch in 1-step receiving flows where a sub-location (e.g., WH/Stock/Test) is intended, since the move lines revert to the root warehouse location (WH/Stock). Thus, the forecasted quantity for the specific sub-location doesn't increment as expected. ### **Desired behavior after PR is merged:** The `_get_final_location_record` method will now evaluate if the Operation Type's `default_location_dest_id` is a child of the warehouse's main stock. If it is, the sub-location is used as the `location_final_id` for the moves and move lines. This ensures that the forecasted quantity reflects the intended destination upon PO confirmation while still maintaining the fallback to the warehouse root for standard multi-step routes. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256725 Forward-Port-Of: odoo/odoo#254527
Branch company accounting users can now create TDS entries on vendor bills without being blocked by access errors. The fix uses the active branch company for currency handling instead of the parent company's tax record, keeping the workflow aligned with the user's permissions.
Original PR description
**Steps to reproduce:** * Install the **l10n_in** module. * Create a **branch company** under an Indian company. * Switch to the branch company only. * Create a user with **Accounting Administrator**…
**Steps to reproduce:** * Install the **l10n_in** module. * Create a **branch company** under an Indian company. * Switch to the branch company only. * Create a user with **Accounting Administrator** access (and bank validation rights) and also give permission of this branch company. * Login from this user . * Create and confirm a vendor bill in the branch company. * Click **TDS Entry** and select any TDS section. **Observed behavior:** * An **AccessError** is raised when selecting the TDS section. **Cause:** * In `_compute_amount` (wizard), currency is taken from `tax_id.company_id`. * For branch setups, taxes (and related accounts) belong to the **parent company**, so `tax_id.company_id` points to the parent. * The user operating in the branch company does not have access to the parent company, triggering an access error. **Fix:** * Use the wizard’s `company_id` instead of `tax_id.company_id` when determining currency. * The wizard `company_id` is correctly computed based on the active company, ensuring proper access rights. **Note:** * Regression test is not feasible due to ORM cache behavior: * In tests, `mock` environments share a transaction-level cache. * `compute_sudo=True` fields populate cache with superuser access. * By the time `_compute_amount` runs, values are already cached. * No database fetch occurs, so record rules are not evaluated and the AccessError cannot be reproduced. opw-6095312 Forward-Port-Of: odoo/odoo#259091
Peppol invoice XML now keeps unit price calculations consistent with invoice line totals, preventing validation errors when prices have many decimal places. This helps businesses send compliant electronic invoices without manual correction or rejection risk.
Original PR description
**PROBLEM** Previously, we rounded the unit price up to 6 digits in the generated xml for peppol. However, odoo compute the lineExtensionAmount with the raw unit price. The generated xml is invalid because `priceAmount*InvoicedQuantity != LineExtensionAmount`. **STEP TO REPRODUCE** 1. Create an invoice with unit price of 0.01110515964, and quantity of 278362.5. 2. Generate an XML with peppol, and try validating the invoice. You should have the following error: `[PEPPOL-EN16931-R120]-Invoice line net amount MUST equal (Invoiced quantity * (Item net price/item price base quantity) + Sum of invoice line charge amount - sum of invoice line allowance amount` opw-6009771 Forward-Port-Of: odoo/odoo#255358
This fixes Italian electronic invoice exports so Spanish VAT numbers that begin with a letter are no longer shortened by mistake. It helps ensure invoices sent to the tax agency contain the correct customer tax identification details.
Original PR description
**Steps to reproduce:** * Install `l10n_it_edi` module. * Create a partner with country **Spain** and VAT `A95758389`. * Create an invoice and send it to the Tax Agency, and download XML. **Observed behavior:** * The exported XML contains `5758389` in <IdCodice> instead of `A95758389` — the first two characters of the VAT are silently dropped. **Cause:** * In `_l10n_it_edi_get_values`, the EU branch that strips the country-code prefix used a bare `else` after the `isdecimal()` check, unconditionally removing the first two characters of any VAT that does not start with two digits. Spanish NIFs like `A95758389` start with `A9` (letter + digit), which is not a country-code prefix but was treated as one, corrupting the value. **Fix:** * Remove country prefix from normalized VAT by `removeprefix(normalized_country)` Instead of removing the first two characters. It will ensure that only the country prefix will be removed. opw-6089198 Forward-Port-Of: odoo/odoo#258626
Odoo now blocks users from creating related fields that depend on non-stored fields. This prevents configuration mistakes that could later cause search, reporting, or data consistency problems.
Original PR description
**Steps to Reproduce:** - Create a new database. - Install any module (for example, Sale). - Go to Settings → Technical → Database Structure → Fields. - Create a new field using Studio or manually. -…
**Steps to Reproduce:**
- Create a new database.
- Install any module (for example, Sale).
- Go to Settings → Technical → Database Structure → Fields.
- Create a new field using Studio or manually.
- Set the field as a related field using a path that includes a non-stored field (e.g., product_variant_id.active where product_variant_id is non-stored). Save the field.
**Issue:**
- Odoo allows defining related fields that depend on non-stored (non-searchable) fields in the dependency chain.
- This leads to runtime issues such as:
- Cannot convert field to SQL because it is not stored
- Failures in search, domains, and reporting
- Inconsistent behavior depending on usage context
- Currently, no validation prevents users from configuring such invalid related fields.
**Solution:**
- Add validation in the related field resolution logic to ensure that all fields In the related path are stored.
- Raise a ValidationError when a non-stored field is encountered in the related path, clearly indicating the offending field and model.
This prevents invalid related field configurations at creation time and ensures data consistency and predictable behavior across ORM operations.
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-prThis update fixes an issue where rental price calculations were inconsistent due to how relativedelta handled time-zoned dates. The change ensures accurate price calculations across different time zones, specifically addressing discrepancies in rental durations. This improves the reliability of rental pricing for all users.
Original PR description
Relativedelta on UTC dates or time-zoned dates doesn't return the same result. In order to calculate consistent prices (price for 1 month in December = price for 1 month in January), we need to work…
Relativedelta on UTC dates or time-zoned dates doesn't return the same result. In order to calculate consistent prices (price for 1 month in December = price for 1 month in January), we need to work on time-zoned dates. Example: Consider a website in UTC+1 (Brussels timezone DST off). And a rental from the 01/12/2025 to the 31/12/2025 = by design, from the 01/01/2025 00h00 (start_date) to the 31/12/2025 23h59 (end_date). Converted in UTC for the back-end, we have: from the 30/11/2025 23h00 to the 31/12/2025 22h59. relativedelta(end_date, start_date) = time between the 2 dates is calculated as follow: 30/11/2025 23h00 + 1 month = 30/12/2025 23h00 +23h59 = 31/12/2025 22h59. Time difference = 1 month, 23 hours, 59 minutes. Price = 2 months. Consider a second rental from the 01/01/2026 to the 31/01/2026. 31/12/2025 23h00 + 30 days = 30/01/2026 23h + 23h59 = 31/01/2026 22h59. Time difference = 30 days, 23 hours, 59 minutes. Price = 1 month. opw-5130762 Forward-Port-Of: odoo/enterprise#102109 Forward-Port-Of: odoo/enterprise#98571
This update resolves an error that occurred when processing DTE XML files from Chile. Specifically, the system was incorrectly setting a default journal, leading to a 'journal_id' error during account move calculations. This fix ensures proper DTE XML processing and prevents data discrepancies.
Original PR description
Currently, when receiving a DTE XML fetched by the fetchmail server, if there is no purchase journal with `l10n_latam_use_documents` enabled, an empty recordset (account.journal()) is set in the default context values. This prevents the proper computation of the field and raises an error, since the `journal_id` is mandatory on account moves. Steps to reproduce: - Ensure you have no purchase journal with `l10n_latam_use_documents` enabled - Simulate the reception of a DTE XML via the fetchmail server - Observe the error: "NotNullViolation: null value in column 'journal_id'" opw-5950116 opw-6111041