Thursday, September 17, 2026
33 changes · master
Resolved issues and error corrections
Sales teams can now use Studio to edit the list view for sales order lines without running into an error. This restores the ability to customize columns and add fields on sales orders, reducing disruption for users configuring their sales workflow.
Original PR description
Before this change: When opening Studio on a Sales Order with existing line items, clicking "Edit List View" on the order lines component triggered a JavaScript error. This prevented users from customizing columns or adding custom fields to the sale order line list view. To reproduce: 1. Open the Sales app and create a new Sales Order with at least one product line. 2. Toggle Studio on. 3. Select the Sale Order Lines list component and click "Edit List View". After this change: Clicking "Edit List View" on sale order lines in Studio works as intended without throwing errors, allowing standard view customizations. opw-6545970 Forward-Port-Of: odoo/odoo#288171
Cancelling an Adyen card payment from the Point of Sale now sends the cancellation to the correct payment request. This prevents payment terminals from continuing to wait for a customer payment after the cashier has cancelled it in Odoo.
Original PR description
Steps to reproduce: - Configure a POS with an Adyen payment terminal - Open the POS, add a product and go to the payment screen - Select the Adyen payment method and click Send - Wait at least 5 seconds - Cancel the payment from the POS - => The terminal keep waiting for the payment (it's not canceled) `_adyenCancel` read `most_recent_service_id` but this value is overwritten by the `_adyenCheckPaymentStatus` polling after 5s, so we try to cancel the wrong payment. We now read the ServiceID from the payment line instead of using `most_recent_service_id`. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288874
Vendor bill lists in Accounting now load quickly again after a recent change caused severe slowdowns. The database lookup used to detect duplicate bills was updated so it also covers vendor receipts, restoring the expected performance for users viewing bills.
Original PR description
commit https://github.com/odoo-dev/odoo/commit/391278237dc4fdbf48039bb269f1377d83bbc54d introduced a performance regression.
Go to Accounting > Vendors > Bills
On odoo.com:
| | Time | Query plan |
|--------|--------|--------|
| Before | ~600ms | https://explain.dalibo.com/plan/3ge1afa2aa632be9 |
| Now | 44s | https://explain.dalibo.com/plan/99e847h8d1c38dfd |
After this commit, we're back with the same query plan :)
The reason is the condition `.move_type in ('in_invoice', 'in_refund')`
which was changed to include 'in_receipt':
`.move_type in ('in_invoice', 'in_refund', 'in_receipt')`
Because of that, the query can no longer use the partial index
`_duplicate_bills_idx` because it doesn't include 'in_receipt'.
This commit adapts the index to include moves with type 'in_receipt'.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#288481Fixes French PDP partner lookup so it works when a company endpoint uses a personalized SIREN or SIRET with an added suffix. This helps affected businesses find and validate partners reliably instead of being blocked by overly strict identifier length checks.
Original PR description
In PDP the lookup didn't work if the endpoint is of any length other than 9 or 14 characters, however personalised SIREN/SIRET can have a higher length, this pr fixes that by allowing a SIREN/SIRET suffix in the lookup following the format 'SIRET_SUFFIX' no task id Forward-Port-Of: odoo/odoo#288509
This fixes an issue where status steps could incorrectly collapse into a single “More” dropdown when users viewed records at certain browser zoom or display scaling settings. Users on high-resolution screens should now see the full statusbar when there is enough space, making record stages easier to read and navigate.
Original PR description
`areItemsWrapping` decides whether the statusbar buttons fit on one line by comparing `getBoundingClientRect()` heights. Those rects are rounded to physical pixels, so depending on the zoom/DPI ratio…
`areItemsWrapping` decides whether the statusbar buttons fit on one line by comparing `getBoundingClientRect()` heights. Those rects are rounded to physical pixels, so depending on the zoom/DPI ratio a single-line height can come out a fraction of a pixel taller than the reference button height, even though nothing actually wraps. That false positive made the whole statusbar collapse into a single dropdown at some (but not all) browser zoom levels, most noticeable on high-DPI screens where OS scaling and browser zoom combine into non-integer ratios. Steps to reproduce: 1. On a high-DPI screen (e.g. 4K) with OS display scaling enabled. 2. Open any record with a statusbar field (e.g. a CRM opportunity). 3. Set the browser zoom to a value close to 100%. 4. The statusbar collapses into a single "More" dropdown instead of showing every stage inline, even though there is enough room. Round both heights before comparing to ignore that sub-pixel noise while still detecting genuine wrapping. Regression introduced by 7e77b99d2845. task-6545990 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#288194
This fix prevents sale orders from failing when a user saves immediately after reordering order lines. Odoo now pauses saving while the line reorder action finishes, making the Sales workflow more reliable for quotations and orders with multiple lines.
Original PR description
When we save a sale order just after reordering its sale order lines, there's a chance that an error is thrown Steps to reproduce: 1. Install Sales 2. Go to Sales and open any quotation that has…
When we save a sale order just after reordering its sale order lines, there's a chance that an error is thrown Steps to reproduce: 1. Install Sales 2. Go to Sales and open any quotation that has multiple sale order lines 3. Reorder a sale order line and immediately save (there's more chance to reproduce if you have a lot of sol and if you use the shortcut `ALT + S`) 4. An error is thrown Issue: It is possible that the save takes place during the execution of super.sortDrop. This reassigns the id of all the records in this.props.list.records Therefore, calling `_handleQuantityAdjustment` with the recordMap computed before the save uses an id that has disappeard from this.props.list.records so we cannot find it at https://github.com/odoo/odoo/blob/4973903252865a6a7a2da235bc3a01675dbbff4d/addons/sale_management/static/src/fields/sale_order_line_field/sale_order_line_field.js#L263 which eventually throws an error Solution: Suspend any save mechanism when sortDrop starts and resume it when sortDrop has finished opw-6483206 Forward-Port-Of: odoo/odoo#288370 Forward-Port-Of: odoo/odoo#286787
This fixes an access error that could stop warehouse users from creating backorders during multi-step deliveries when the original sales order belonged to another user. It restores the expected workflow so inventory teams can validate transfers and create backorders without unnecessary sales order permissions.
Original PR description
Multi-step deliveries backorders may create a new picking when processed by a user who only has access to their own sales orders. But, `_key_assign_picking` reads from the related sales order that they don’t have access to. Previously, these moves were confirmed with superuser rights, so this read did not trigger the sales order record rule. Since 19.2, the `sudo()` was removed. The fix would be to add this back in so the access rights error would not be raised. Steps to reproduce on Runbot: 1. Log in as User A (Admin) Turn on Multi-Step Routes Set the warehouse to use 2-step delivery (Pick then Deliver) 2. Create a Sales Order for a product with demand more than stock available and confirm it. 3. Log in as User B with (Demo): Sales: User: Own Documents Only Inventory: User 4. Open the picking transfer generated from User A’s Sales Order. 5. Click Validate and choose Create Backorder. Related: opw-6509032 Forward-Port-Of: odoo/odoo#285778
Fixes a crash when exporting the Peruvian "Inventory and Balance" General Ledger report. The report now generates successfully while preserving the required SUNAT file format, preventing disruption for users preparing compliance reports.
Original PR description
### Description of the issue/feature this PR addresses: This PR fixes a server crash in the Peruvian localization (l10n_pe_reports_lib) that occurs when generating the "Inventory and Balance" General…
### Description of the issue/feature this PR addresses: This PR fixes a server crash in the Peruvian localization (l10n_pe_reports_lib) that occurs when generating the "Inventory and Balance" General Ledger report. The crash is triggered by strict validation rules within Python's csv module, which rejects the custom line terminator used to fulfill the SUNAT PLE formatting requirements. ### Current behavior before PR: When a user attempts to generate and export the "Inventory and Balance" report, the server crashes with a ValueError: bad delimiter or lineterminator value. This happens because the csv.DictWriter is initialized with lineterminator='|\n' to ensure every row ends with a pipe. Python's underlying csv implementation rejects this, as it expects standard line endings (\r, \n, or \r\n) and throws an error if the delimiter character (|) is included in the terminator string. ### Desired behavior after PR is merged: The "Inventory and Balance" report generates successfully without server errors. The code now uses the standard lineterminator='\n' to satisfy Python's validation rules. To maintain the mandatory trailing pipe (|) at the end of each row required by SUNAT, a dummy empty column (['']) is appended to the field names with restval=''. This prompts the writer to naturally append the final pipe as a column delimiter before the newline, resulting in the exact |\n output format required, safely and reliably. opw-6509674 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#131302 Forward-Port-Of: odoo/enterprise#129636
This fixes naming and selection issues in marketing automation views introduced by a recent revamp. Users should no longer see crashes or be sent to the wrong screen when opening server actions or trigger forms in campaign flows.
Original PR description
This commit fixes issues that were introduced with the new marketing automation revamp. Some views were either wrongly renamed or no longer used to display server actions or trigger form views in the flow view. Which is an issue as this would either create a crash or open the wrong view entirely. Now the views are correctly renamed and used. task-6559148
Fixed an issue where one-time purchases of recurring products were treated like ongoing subscriptions in stock forecasts. This prevents misleading future demand and helps replenishment planning reflect actual sales commitments.
Original PR description
When a recurring product (with `allow_one_time_sale = True`) is sold as a one-time purchase (no subscription plan), the stock forecast report and replenishment logic incorrectly treat it as an active…
When a recurring product (with `allow_one_time_sale = True`) is sold as a one-time purchase (no subscription plan), the stock forecast report and replenishment logic incorrectly treat it as an active subscription. This results in infinite projected future outgoing moves for standard sales. This occurs because the logic only checks if `recurring_invoice` is True on the product, ignoring whether the parent order actually has a `plan_id`. This commit fixes the issue by: 1. Updating `_get_stock_subscription_lines` in `sale.order.line` to filter out lines using `_subscription_is_one_time_sale()`. 2. Updating the domains in `stock.forecasted_product_product` to require `order_id.plan_id != False` for subscription forecasts, while correctly routing one-time sales (`order_id.plan_id == False`) back to the standard sale domain. 3. Adapting existing tests to verify that one-time sales do not generate future subscription stock forecasts. Task-6193648 Forward-Port-Of: odoo/enterprise#128018 Forward-Port-Of: odoo/enterprise#116889
Vendor bills now keep the manually selected recipient bank account when using Auto-Complete, as long as the bill currency has not actually changed. This prevents accidental payment detail changes for vendors with multiple bank accounts.
Original PR description
### Issue: When a bank account is manually set on a bill for a partner with multiple bank accounts, using the Auto-Complete feature could reset the manual selection even without a currency change ###…
### Issue: When a bank account is manually set on a bill for a partner with multiple bank accounts, using the Auto-Complete feature could reset the manual selection even without a currency change ### Cause: When `invoice_vendor_bill_id` is set, an onchange assigns `currency_id` unconditionally, even when it is the same value This triggers `_compute_partner_bank_id`, which always recomputes the best matching bank account from scratch without considering the currently set value If the currency did not change, this recompute is unnecessary and silently overrides the manual selection ### Steps to reproduce: - Install `account` - Create a Vendor with 2 bank accounts (keep default values to have equal priority on all accounts) - Create and post a Bill for this vendor with at least one line - Create a new Bill for the same vendor - Set the Recipient Bank to the second account in the list - In Auto-Complete, select the first Bill Before the fix, the Recipient Bank is reset to the first account opw-6210414 Forward-Port-Of: odoo/odoo#288386 Forward-Port-Of: odoo/odoo#283479
This fix ensures that when a past point-of-sale order is later invoiced, the cancellation sent to the Spanish tax authority targets the original simplified receipt instead of the newly created full invoice. This prevents incorrect electronic tax records and helps businesses keep Verifactu POS reporting accurate.
Original PR description
When creating an invoice for a previous POS order, the data sent to AEAT cancels the full invoice instead of the order's simplified invoice. Steps to reproduce: - Open a POS and make a sale without invoicing it; - In the POS, go to the Order tab; - Select the order and fully invoice it. Issue: The AEAT cancellation line added to the pos order actually cancels the full invoice just created [opw-6471927](https://www.odoo.com/odoo/project/49/tasks/6471927) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284277
Colombian Point of Sale orders no longer fail when a company has several DIAN obligation types configured. Receipts can now be generated and printed correctly by listing all applicable obligation descriptions instead of assuming only one exists.
Original PR description
Steps to reproduce: - Colombian company with DIAN electronic invoicing enabled in PoS - On the company contact, set more than one obligation type (e.g. O-13, O-15 and O-23) - Open a PoS session, sell…
Steps to reproduce: - Colombian company with DIAN electronic invoicing enabled in PoS - On the company contact, set more than one obligation type (e.g. O-13, O-15 and O-23) - Open a PoS session, sell a product and pay Issue: The order fails to sync with "Expected singleton: l10n_co_edi.type_code(x, y, z)" as soon as the DIAN document is accepted, and the receipt cannot be printed. On 18.0 to saas-19.1 the same crash happens when the receipt data is generated for printing. Cause: `_compute_l10n_co_edi_pos_receipt_data` fills `obligation_type_description` by reading `description` directly on `l10n_co_edi_obligation_type_ids`, which is a many2many. The read only works when the company carries exactly one obligation type, while a Colombian company commonly has several (they are all sent to the DIAN in `TaxLevelCode`). Fix: Join the descriptions of all obligation types, the same way the DIAN invoice PDF report already does. opw-6576523 Forward-Port-Of: odoo/enterprise#131747
GCC Arabic-English invoice PDFs no longer fail when an invoice includes section or note lines. This prevents internal server errors during invoice preview or printing, making invoice generation more reliable for affected businesses.
Original PR description
## Problem When rendering PDF invoices that contain **section** or **note** lines, the `l10n_gcc_invoice.arabic_english_invoice` QWeb template raises: ``` TypeError: argument of type 'bool' is not…
## Problem When rendering PDF invoices that contain **section** or **note** lines, the `l10n_gcc_invoice.arabic_english_invoice` QWeb template raises: ``` TypeError: argument of type 'bool' is not iterable ``` This happens because `account.move.line` records of type `line_section` or `line_note` have `name = False`. The template evaluates `arabic_name not in line.name` (and the same for `english_name`), which fails because Python cannot apply the `in` operator on a boolean value. ## Fix Add a `line.name and` guard before each `not in` check: ```xml <!-- Before --> <span t-if="arabic_name not in line.name" .../> <span t-if="(english_name != arabic_name) and (english_name not in line.name)" .../> <!-- After --> <span t-if="line.name and arabic_name not in line.name" .../> <span t-if="line.name and (english_name != arabic_name) and (english_name not in line.name)" .../> ``` ## Steps to reproduce 1. Install `l10n_gcc_invoice` on an Odoo 16.0 instance. 2. Create a customer invoice and add a **Section** line. 3. Print/preview the invoice PDF. 4. Observe `Internal Server Error` / `TypeError: argument of type 'bool' is not iterable`. Forward-Port-Of: odoo/odoo#278887 Forward-Port-Of: odoo/odoo#267147
This fix prevents Argentina electronic invoices from sending zero-value VAT details when advance payments fully offset the invoice. It helps $0 final invoices pass ARCA validation instead of being rejected, supporting the standard 100% down payment workflow.
Original PR description
## Description of the issue When an Argentinian invoice contains advance-payment deduction lines that exactly cancel the product lines (net taxable base = 0 for a given VAT aliquot), the invoice is…
## Description of the issue
When an Argentinian invoice contains advance-payment deduction lines that exactly cancel the product lines (net taxable base = 0 for a given VAT aliquot), the invoice is rejected by the ARCA (AFIP) WSFE web service with:
> **Error 10018**: "Si ImpIva es igual a 0 el objeto Iva y AlicIva son obligatorios. Id iva = 3 (iva 0)"
This is the standard "100% down payment" flow: the customer is invoiced an advance for the full amount, and the final invoice deducts that advance, resulting in a $0 invoice that must still be validated against ARCA.
This is a forward-port to 19.0 of #270846 (same fix, targeted at 18.0, closed unmerged). The bug is still present in 19.0: `_get_vat()` in `addons/l10n_ar/models/account_move.py` evaluates its filter on the raw unrounded aggregated floats.
## Steps to reproduce
1. On a company with the Argentinian localization (`l10n_ar_edi`) configured for electronic invoicing (WSFE), create a sale order with one or more product lines taxed at IVA 21% (e.g. total $121,000).
2. Create a **down payment invoice for 100%** of the order and validate it against ARCA (this one succeeds).
3. Create the final invoice from the sale order: it contains the product lines (positive) and the down-payment deduction line (negative), both at IVA 21%. Total to pay: **$0.00**.
4. Confirm the invoice and send it to ARCA.
5. **Current behavior (bug):** ARCA rejects the request with error 10018. Inspecting the generated WSFE request shows `ImpNeto=0.0`, `ImpIVA=0.0`, `ImpTotal=0.0` and an `Iva` block containing an all-zero aliquot, e.g. `{'AlicIva': [{'Id': '5', 'BaseImp': 0.0, 'Importe': 0.0}]}` — instead of `Iva: null`.
6. **Expected behavior (after fix):** no zero-amount aliquot is sent (`Iva` is `null`) and ARCA approves the $0 invoice.
## Root cause
In `_get_vat()`, the positive product lines and the negative down-payment deduction line share the same VAT aliquot, so the aggregation by `vat_afip_code` nets the group to zero. However, floating-point accumulation in the aggregated tax details leaves a tiny residual (~1e-12) in `base_amount_currency` / `tax_amount_currency`. The filter condition checks the **raw unrounded** values:
```python
if grouping_key['vat_afip_code'] not in (False, '0', '1', '2') and (values['base_amount_currency'] or values['tax_amount_currency']):
```
The ~1e-12 residual is truthy in Python, so the aliquot entry is kept — even though both `BaseImp` and `Importe` are rounded to `0.00` two lines below when building the entry. The WSFE request therefore carries a non-null `Iva` block with all-zero amounts, which ARCA rejects with error 10018.
## Fix
Round `BaseImp` and `Importe` to 2 decimals **before** evaluating the filter condition, so an aliquot whose amounts cancel out is excluded from the `Iva` array (the same rounded values are then reused when building the entry, keeping the sent amounts unchanged for every other case):
```python
base_imp = float_round(amount_sign * values['base_amount_currency'], precision_digits=2)
importe = float_round(amount_sign * values['tax_amount_currency'], precision_digits=2)
if grouping_key['vat_afip_code'] not in (False, '0', '1', '2') and (base_imp or importe):
```
Behavior is unchanged for every invoice whose aliquots round to a non-zero base or tax amount.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#286005Vehicle imports now better understand the expected brand/model format when creating vehicle model records. This helps manually created fleet vehicles import more reliably and reduces avoidable errors during data migration or updates.
Original PR description
The name has a specific format `<brand>/<model>`, hence the fix overwrites the `name_create` function called when the import tries to create new model records, so that the name passed to that function can be correctly interpreted. Errors will occur for vehicles from the demo data (because of their external ID) but should work for any vehicle created manually. task-6578351
Fixes an issue where editing certain Kanban cards in Odoo Studio, such as Project tasks, could fail when adding or removing fields. This lets users customize those views reliably without save errors, while leaving other views unchanged.
Original PR description
Issue: Editing the Project task Kanban with Studio fails with an "element cannot be located in parent view" error. This affects Kanban views whose card architecture is provided through `card_id`.…
Issue: Editing the Project task Kanban with Studio fails with an "element cannot be located in parent view" error. This affects Kanban views whose card architecture is provided through `card_id`. Adding or removing a field produces an XPath targeting the inlined `<card>`, but that node cannot be found when the Studio customization is saved. Steps to reproduce: * Open Project > Tasks > My Tasks in Kanban view. * Open Studio. * Add or remove a field from the card. Cause: The client receives a postprocessed Kanban architecture in which the view referenced by `card_id` has already been appended as a `<card>` node: https://github.com/odoo/odoo/blob/1aa1f1967c7b9c8fd2c941fbc0c7b4c563698e46/odoo/addons/base/models/ir_ui_view.py#L3138-L3140 Studio therefore generates paths containing `/kanban/card`. However, Studio normalization applies those paths to the pre-postprocessed architecture, which still contains only the `card_id` attribute: https://github.com/odoo/enterprise/blob/42aa8fafdef159476d708f91467cba6f7fb2c6d3/web_studio/models/ir_ui_view.py#L667-L671 As `<card>` does not exist in that source tree, the inheritance engine cannot locate the target. Solution: We need to inline the referenced card before applying or normalizing Studio customization specifications. This makes Studio operate on the same architecture shape that was presented to the client. The `card_id` attribute is then removed from that temporary source to prevent regular post processing from appending the card a second time. The behavior is limited to Studio customization views and is a no op for Kanban views without `card_id`, preserving the existing inheritance flow for other views. opw-6445398 Forward-Port-Of: odoo/enterprise#127393
This change restores the previous way Mexican electronic payment complements calculate amounts, following updated guidance from the certification provider after consultation with the government. It helps reduce compliance and validation issues by using the maximum allowed decimal precision for payment amounts.
Original PR description
Quadrum reverted their changes because > Derived from a consultation with the government we reverted to our previous behavior, we recommend using the maximum number of decimals allowed Reverts commit https://github.com/odoo-dev/enterprise/commit/f13d204dacf9eae98c78de26e9f2e54387a0eaee as well opw-6561617 Forward-Port-Of: odoo/enterprise#131640 Forward-Port-Of: odoo/enterprise#131581
Fixes a VoIP call flow editor issue that prevented users from moving an existing connection to a new destination. This helps teams update call routing flows without losing connectors or being blocked by connection limits.
Original PR description
An output port that already has a connection couldn't be rewired to a new target: grabbing it looked for another output port instead of an input port, so the old connector was removed and never replaced. Dropping a new connection onto an output port that was already at its connection limit was rejected outright instead of replacing the existing connection.
This fix makes Belgian payroll time off allocations more consistent and accurate, especially when employees have multiple contract changes or working schedule updates. It also improves the schedule change process and adds clearer explanations in the interface so payroll teams can better understand allocation values.
Original PR description
Time off allocation fixes:
- Fixed rounding of time off allocations: some parts of the code rounded to full days, while others rounded to half-days.
- Fixed the calculation of time off from holiday attestations, which was done differently in different parts of the code.
- Fixed allocation calculations for employees with multiple contract versions, ensuring that each version is only taken into account for its actual effective period.
- Fixed the Working Schedule Change wizard:
-- allocations were not found when the work entry types had the same code but different records (generic vs. Belgian);
-- the calculated allocation was not correctly displayed in the wizard;
-- fixed the allocation update for working schedule changes starting in the future.
- Added a tooltip to explain the time off allocation values in the UI.
task: 6452166This update fixes cases where some screens could behave as if the user was not on a small device, which could affect mobile layouts in areas like accounting, imports, mail, and navigation. It also adds safeguards so outdated internal references fail visibly during testing instead of causing quiet display issues later.
Original PR description
Removes depracated `env.isSmall` and `env.debug` and make it throw if used (to prevent forward port mistakes) Enterprise PR: https://github.com/odoo/enterprise/pull/130698
EU OSS sales are now reported correctly in French PDP Flow 10 by excluding destination-country VAT from French VAT rate checks. This keeps the invoice and accounting VAT intact while reporting the taxable amount in the appropriate non-French VAT category, reducing reporting rejections.
Original PR description
OSS sales are taxed in the customer's Member State but are not subject to French VAT. They must therefore be reported under TNT1, while the Flow 10 Schematron only accepts French VAT rates. Identify taxes generated for the EU OSS scheme through their OSS tag. Keep the destination VAT on the invoice and in accounting, but report the taxable base under TNT1 with a zero tax rate and amount. Continue rejecting unsupported rates for regular taxes and invalid OSS rates. no task id Forward-Port-Of: odoo/odoo#288013
This update fixes screens and menus that could show the wrong layout on phones or hide certain options because they were checking outdated system values. It improves reliability for mobile users and restores expected menu behavior in apps such as Accounting, Documents, Appointments, Spreadsheets, ESG, and Time Off.
Original PR description
Removes depracated `env.isSmall` and `env.debug` and make it throw if used (to prevent forward port mistakes) Community PR: https://github.com/odoo/odoo/pull/287002
Belgian payroll now applies the correct train pass reimbursement rate for employees under Joint Committee 302 from February 2026. This prevents employees from being under-reimbursed because the sector table values already include the legally required calculation.
Original PR description
Previously, the system was applying an additional 80% reduction ratio on top of the CP 302 train allowance values. However, the rates listed in the official CP 302 sectoral table already incorporate the legally applicable 71.8% calculation. Applying an extra 80% factor resulted in an under-reimbursement of train transport costs for employees under Joint Committee 302. **What:** - Added the missing rule parameter value record _`rule_parameter_cp302_train_reimbursement_ratio_2026`_ setting the ratio factor to 1 (100%) effective from February 1, 2026. task-6532036 Forward-Port-Of: odoo/enterprise#131583 Forward-Port-Of: odoo/enterprise#130291
This fix prevents users from opening additional shop floor menu dialogs while a manufacturing order is already loading. It avoids an error that could appear on slower connections, making shop floor navigation more reliable for manufacturing users.
Original PR description
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. *…
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. * On a work order card, click the **gear** icon to open the menu dialog. * Click **Open Manufacturing Order** on a slow network connection. * Before the MO form view finishes loading, quickly click the **gear** icon again and open another dialog (e.g. Log Note). * The MO form view loads, destroying the shop floor component. * Close the Log Note dialog. **Observed behavior:** * An `UncaughtPromiseError: Component is destroyed` error is thrown because the dialog tries to interact with the shop floor component that has already been destroyed by the navigation to the MO form view. **Cause:** * When the user clicks "Open Manufacturing Order", `doAction` is called to navigate to the MO form view, and `props.close()` immediately closes the menu dialog. However, the shop floor component is still visible while the new view is loading. * During this gap, the gear button remains clickable. If the user opens another dialog (e.g. Log Note), that dialog holds a reference to the shop floor component. When the MO form view finishes mounting, the shop floor is destroyed, and closing the stale dialog triggers operations on the destroyed component. **Fix:** * Add an `actionPending` state flag to `MrpDisplayRecord`. When the user selects "Open Manufacturing Order" from the menu dialog, an `onSelect` callback sets `actionPending` to `true`, which disables the gear button and prevents any new dialog from being opened. * The flag is only set for `openMO` (which navigates away and destroys the component), not for other menu actions like Scrap, Add Component, or Log Note which open wizard dialogs and return to the shop floor. opw-6107579 Forward-Port-Of: odoo/enterprise#131538 Forward-Port-Of: odoo/enterprise#123490
This fix ensures rental orders keep track of serial numbers when pickups and returns are handled through stock transfers. It prevents the return wizard from opening without available serial numbers after a partial return, allowing staff to complete subsequent rental returns reliably.
Original PR description
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return…
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return wizard. **Steps to reproduce** - Activate "Rental Transfers" in the settings - Create a rental product P, tracked by serial number - Create two serial numbers for P - Create and confirm a rental order for 2 units of P - Validate the pickup transfer - Partially validate the return transfer without creating a backorder - Open the rental order and click on "Return" -> The return wizard opens without any available serial number and validation fails with a serial number-related error. **Cause** When clicking on "Return", if there is no pending pickup/return transfer: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/models/sale_order.py#L62-L68 the rental return wizard is opened directly: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/models/sale_order.py#L316 No serial number is prefilled in the wizard because `returned_lot_ids` is empty: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L122-L124 This is because `returnable_lot_ids` is empty as well. `returnable_lot_ids` is computed while generating the wizard lines: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L38 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L47-L48 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L99-L106 and `returnable_lots` is empty because both `pickedup_lots` and `returned_lots` are. Those fields are currently only populated through the rental wizard flow: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L42-L43 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L160-L161 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L166-L167 Since this flow uses stock pickings instead of the rental wizard, those fields are never updated, preventing the wizard from determining any returnable serial number. opw-6150305 Forward-Port-Of: odoo/enterprise#127590 Forward-Port-Of: odoo/enterprise#119257
Belgian payroll now correctly handles the Special Social Contribution when generating a 13th month payslip. If there is no regular monthly payslip for the same period, the contribution is set to zero, helping avoid incorrect payroll deductions.
Original PR description
When we generate a 13th month payslip, we need to check if there is a monthly pay payslip in the same period. If not, the Special Social Contribution will be 0. task-6512347
Italian point-of-sale refunds can now be processed from a different trusted POS without receipt printing failures. The system keeps the original printer details with the order, so refund receipts use the correct fiscal printer information.
Original PR description
Steps to reproduce: - Set up two POS configurations and add each to "Trusted POS"; - Connect a different fiscal printer to each POS configuration; - Process an order on POS A; - Refund that order on POS B. **Issue**: The refund receipt fails to print. The system currently transmits the serial number of the active POS configuration's printer instead of the printer that processed the original order. As a result, POS B's printer receives its own serial number alongside order identifiers that do not exist in its local fiscal memory. **Solution**: Store the processing printer's serial number directly on the `pos_order model` to ensure the correct serial number is transmitted during cross-POS refunds. [opw-6499079](https://www.odoo.com/odoo/project/49/tasks/6499079)
Rounded point-of-sale payments are now recorded correctly even when the stock app is not installed. This prevents accounting imbalances when closing PoS sessions, reducing disruption for retailers using cash rounding.
Original PR description
Before this commit: = - The rounding move line creation was moved from point_of_sale to pos_stock while removing the dependency of stock on point_of_sale. - As a result, when pos_stock was not installed, no rounding move lines were created for rounded PoS payments, leading to unbalanced journal entries during session closing. After this commit: = - Restored the rounding move line creation in point_of_sale so that rounded payments are correctly handled. task-6214240 runbot-error-242920 Forward-Port-Of: odoo/odoo#264288
AI agents now manage their URL-based attachments more reliably, so each agent keeps the right linked content separate from others. This helps prevent mix-ups between agents and supports smoother background processing of URL content.
Original PR description
Many2one URL attachments' fixes to ensure each agent has its own URL attachments.
Point of Sale now avoids errors when opening a session if the browser has old cached data for models that were renamed or removed. This helps users resume POS work without needing a manual data reload after module changes or upgrades.
Original PR description
In PR-#[225341](https://github.com/odoo/odoo/pull/225341) we started passing all the models which are cached on the front end directly to the back end, but if the database existed before and the front end cached models which no longer exist, either because the model name changes (such as pos.product.template.snooze -> pos.snooze), or because a module was uninstalled (removing pos_restaurant_appointment), the front end would ask the back end for models which no longer exist, and that would error. When we do the reload data, all the local cache would be deleted and then we could launch the POS. To fix it, now the back end will check whether the model exists before trying to filter on it, and just ignore it if it doesn't exist Task-[6562705](https://www.odoo.com/odoo/project/1737/tasks/6562705) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Inter-company purchase receipts are no longer marked as already picked when they are created from a confirmed sales order. This lets warehouse teams process the receipt normally in the Barcode app and avoids confusion or skipped handling steps.
Original PR description
Issue ----- When confirming a SO, the corresponding PO picking should not have its' MLs set as `picked` to allow treating the transfer in the barcode app. Steps to reproduce ----- - Create 2 companies A & B - Settings > Inter-Company Transactions - Create Purchase Orders - Set the created PO to be "Validated" by default - Create a SO from company A to B - Validate the OUT picking in company A - Open the PO in company B - Go to its' picking and open it in barcode > The line is already picked ----- Ticket: opw-6481828 Forward-Port-Of: odoo/enterprise#131391
New Singapore companies will now be created with the correct accounting configuration for inventory purchases. This ensures price differences between product cost and purchase price are posted to the expected account, improving the accuracy of vendor bills and stock valuation.
Original PR description
Singaporean companies didn't have the anglo saxon accounting enabled. Price difference account was then not hit when buying a product with a different price than the one in the product page. Steps to reproduce: ------------------- * Create a product P * Set the costing method to "Standard Price" and the inventory valuation to "Perpetual (automated)" * Make sure a price difference account is set in the product category * Create a RFQ for P and set a different price than the one in the product page * Confirm the RFQ and receive the product * Create a vendor bill for the RFQ and validate it > Observation: If you check the lines in the bill there is no price difference account hit. Why the fix: ------------ We set anglo saxon accounting to True so that all new companies have the correct setup. opw-6525817 Forward-Port-Of: odoo/odoo#288261