Thursday, October 2, 2025
15 changes · 18.0
Enhancements to existing features
Point of Sale now lets staff mark a terminal payment as completed when Odoo is still waiting for the card terminal response. This gives cashiers a safe fallback when the payment succeeded on the terminal but the system did not update, helping avoid blocked checkouts and unnecessary retries.
Original PR description
Current behavior before PR: If we faced an issue with a terminal payment while the `line.payment_status` being "waitingCard", only possible option for the user would be to "Cancel" the payment and try again or choose another payment method. This is an issue for the cases where the payment went through on the terminal but Odoo didn't update the status for some reason. Desired behavior after PR is merged: We add the possibility to "Force done" while the status is "waitingCard" to avoid blocking the user in such situations and have a possible fallback. opw-4978772 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228406
Resolved issues and error corrections
Fixes an issue where running an action on multiple Documents could create all expected vendor bills but then open only one result. Users are now taken to the full set of created records, making batch document workflows behave as expected.
Original PR description
[FIX] base: run all multi-state actions as multi(record) Context --- In the Documents module, users can select one or more records and run an action on them. Recent changes (ref.1) replaced…
[FIX] base: run all multi-state actions as multi(record) Context --- In the Documents module, users can select one or more records and run an action on them. Recent changes (ref.1) replaced documents.workflow.action with `ir.embedded.actions`, which are linked to `ir.actions.server`. Some actions, such as `ir_actions_server_create_vendor_bill`, are multi-state actions (where "state" is sometimes referred to as "TYPE" in `IrActionsServer.run`). These actions execute dependent actions when triggered. A distinct but related concept is multi-action, which refers to actions defined with a method suffixed `_multi`. These methods are designed to handle multiple records at once. What seem to be a separate concept is a **multi action**. That is an action defined by a method suffixed `_multi`. Such action can handle multiple records at its execution. Reproduce --- - install documents_account - open documents -> finance folder - select two (or more) documents (shift + click) - run action "Create Vendor Bill", bills are created ok for all documents - BUG: you are taken to a from view of a single bill... ... instead of to the list of all created documents, like it used to be in the previous version Root Cause of the Bug --- - When `ir_actions_server_create_vendor_bill` is executed, Odoo searches for the appropriate runner method. - Since `_run_action_multi_multi` does not exist, Odoo defaults to `_run_action_multi`, which is executed in single-record mode. - The term multi in this case refers to the action's state, not the number of records being processed. - Because `_run_action_multi` is not designed for multi-record execution, it is called individually for each record. - This approach works for invoice creation but is inefficient and restricts navigation, as it only opens a single document (`account_create_account_move`) instead of the full list. FIX --- - Treat all server actions with state=multi as multi-record actions. - Pass all active_ids to the runner method to process all selected records in a single execution. References --- (ref.1) a32825ee00f2b330d99113f4d8c1488903fe744e [IMP] documents, *: modernize access rights, sharing, and actions opw-4547250
The French FEC export now excludes invoice note and section rows that are not real accounting entries. This prevents non-accounting information from appearing in official accounting export files and keeps reports cleaner and compliant with expected behavior.
Original PR description
Step to reproduce: - for l10n_fr Localization - Create a customer invoice and add a note or Add a section . - Go to accounting > reporting > FEC - Export FEC (don't exclude 0 lines) Obseravtion: - The journal items with note and section will be included in the FEC Cause: - for Fec report, we consider move_line which do not have account_id linked to it, due to left_join, hence lines with display_type line_note or line_section are included Fix: - use `join` instead of `left_join` - **v17.0, when the behaviour was as expected** https://github.com/odoo/odoo/blob/3d3898b442379d7416da0ee7e363b6587c725218/addons/l10n_fr_fec/wizard/account_fr_fec.py#L194-L196 opw-5079457 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where unassigning and reassigning goods from the reception report could reserve the wrong stock location. Warehouse teams can now reliably link incoming receipts to sales orders without leaving available stock incorrectly blocked.
Original PR description
### Issue: #### Steps to reproduce: 1- Activate routes & locations and enable Reception Report 2- Enable Show reception report at validation from operation type: receipts 3- Create a product with…
### Issue: #### Steps to reproduce: 1- Activate routes & locations and enable Reception Report 2- Enable Show reception report at validation from operation type: receipts 3- Create a product with vendor. Put 2 unit on `WH/Stock/Shelf1` 4- Create a Sales Order for 3 units. 5- Create a PO for 1 unit and validate/receive. 6- On the Reception Report, click Assign to link incoming to sales pick 7- Open the sales pick in a new tab, observe there are 2 moves which first one is 1 and 2nd one is 2 8- On the reception report, click Unassign, then Assign again Back on the Pick, only 1 move (the one with quantity of 2) is reserved; checking availability reserves nothing although stock exists. #### Cause: When unassigning from the Reception Report, the system incorrectly unreserves stock that was already in `Shelf1` instead of unreserving the incoming move which the location_id is `WH/Stock`: User clicks Unassign on the Reception Report. `report_stock_reception.action_unassign()` is invoked. That calls `stock_move._do_unreserve()`. `_do_unreserve()` unpicks quants referenced by the `move.move_line_ids`. At this moment one of the `move_line_ids` points to `WH/Stock/Shelf1`, so `_do_unreserve()` removes the reservation from that `shelf1` quant. Consequence: `shelf1` stock(which should have remained reserved) becomes free. The receipt quant at `WH/Stock` remains reserved/ unavailable. When the user clicks Assign again, the system cannot reserve because it is alreade reserved by another move and therefore it is unavailable. #### Root cause: Now we look earlier in the flow to see why the move had a move_line pointing to `WH/Stock/Shelf1` in the first place. Earlier, in `report_stock_reception.action_assign` in the first assign: We create a new move from current outgoing move: https://github.com/odoo/odoo/blob/35ea3dcb2eeb379c8b1127f0c7b42191853c0bd2/addons/stock/report/report_stock_reception.py#L224-L231 And we link current move_lines to the new move: https://github.com/odoo/odoo/blob/35ea3dcb2eeb379c8b1127f0c7b42191853c0bd2/addons/stock/report/report_stock_reception.py#L245-L259 new_out.move_line_ids now contains move lines for multiple source locations, here in our case `[WH/Stock/Shelf1, WH/Stock]` The loop in above code does not check `move_line_id.location_id` when selecting lines. The first matching line in the iteration can be the `shelf1` one, so the code links the `shelf1` move_line to out instead of the `WH/Stock` move_line, which is a mismatch and causes the out move having different location with its move_line, which later will going to cause problem is unassign as explained. ### Fix: We can sort move_line_ids in a way that which line have the same location as potential ins' dest locations come first as better candidates: ```diff - for move_line_id in new_out.move_line_ids: + matching_locations = potential_ins.location_dest_id + for move_line_id in new_out.move_line_ids.sorted(lambda ml: ml.location_id not in matching_locations): ``` opw-4944047
Scheduled background jobs now refresh their system information before running, so they no longer use outdated data after an app is uninstalled. This prevents worker crashes and console errors that could interrupt automated tasks in multi-worker deployments.
Original PR description
**step to reproduce:** - start a database with worker, use `--max-cron-thread=1 --workers=2` - Add a sample cron, which runs every minute(just so that we can see the status) - install helpdesk -…
**step to reproduce:**
- start a database with worker, use `--max-cron-thread=1 --workers=2`
- Add a sample cron, which runs every minute(just so that we can see the status)
- install helpdesk
- uninstall helpdesk
**Observation**
- traceback in console
```
2025-09-25 06:07:26,389 18450 ERROR ? odoo.service.server: Worker WorkerCron (18450) Exception occurred, exiting...
Traceback (most recent call last):
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/service/server.py", line 1171, in _runloop
self.process_work()
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/service/server.py", line 1270, in process_work
base.models.ir_cron.ir_cron._process_jobs(db_name)
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/addons/base/models/ir_cron.py", line 139, in _process_jobs
registry[cls._name]._process_job(db, cron_cr, job)
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/addons/base/models/ir_cron.py", line 331, in _process_job
now = fields.Datetime.context_timestamp(ir_cron, datetime.utcnow())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
....
....
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/models.py", line 3873, in fetch
fetched = self._fetch_query(query, fields_to_fetch)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/addons/base/models/res_users.py", line 546, in _fetch_query
records = super()._fetch_query(query, fields)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/models.py", line 3965, in _fetch_query
self.env.cr.execute(query.select(*sql_terms))
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/sql_db.py", line 335, in execute
res = self._obj.execute(query, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
psycopg2.errors.UndefinedColumn: column res_users.helpdesk_target_closed does not exist
LINE 1: ...s"."odoobot_state", "res_users"."odoobot_failed", "res_users...
```
Issue:
- traceback occurred, as the system is try to fetch fields related to helpdesk module
which do not exists now after uninstalling it.
- cron in case of workers, use daemon threads [1]
- the uninstalled happened with main thread and registry is updated.
- the daemon thread is unaware of this change.
- the `_process_jobs` uses the registry, without checking if it needs reload
[1]: https://github.com/odoo/odoo/blob/e82fdfaf621f45515b92c891334595250accbfbd/odoo/service/server.py#L582-L587
FIx:
- when assigning the registry, we check if needs a reload or not.
opw-5062313
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#228515This fixes an issue where a protected bank account number field could still be modified after being locked. The change helps preserve bank account data integrity and reduces the risk of unintended payment detail changes.
Original PR description
Before this fix it was possible to update sanitized_acc_number even if it is locked. Forward-Port-Of: odoo/odoo#184736
This fixes a stock calculation issue where outgoing inventory movements could be missed when quantities were computed in strict mode. Businesses using strict stock location checks will see more reliable product availability and inventory figures.
Original PR description
### Issue: Commit ba54310a11d2b702753d4b9b028a62dd00a91467 has altered the location domain for quantities computations. However, the `dest_loc_domain_out` has not been correctly replaced: https://github.com/odoo/odoo/blob/f173c738b1adcf85a80eb641ad307b7cccf17294/addons/stock/models/product.py#L319 Since the returned value used to be negated and is not anymore. This results in out moves being ignored by the `_compute_quantities` in `strict` mode. opw-4997982 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix allows Spanish TicketBAI credit notes to reference original invoices that were issued before the company started using TicketBAI in Odoo. This prevents valid refunds or corrections from being blocked when the original invoice came from a previous system.
Original PR description
…re starting to use Tbai 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
The Point of Sale now ignores keyboard input tied to browser or system shortcuts, such as zooming or tab navigation. This prevents accidental quantities or values from being added to order lines when cashiers use common keyboard shortcuts.
Original PR description
Before this commit, the NumberBuffer was listening to all keyup events. This caused unintended behavior when the user pressed browser/system shortcuts such as: - `Ctrl +` / `Ctrl -` on Windows/Linux (zoom in/out) - `⌘ +` / `⌘ -` on macOS (zoom in/out) - `Alt + <number>` or `Alt + <arrow>` (browser tab navigation, menu accelerators) Because the key itself (e.g. `"+"`, `"-"`, `"1"`) was part of `INPUT_KEYS`, the NumberBuffer captured the event and updated its state leading to unexpected inputs being added to the PoS order lines. opw-4965429 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The manufacturing Bill of Materials overview no longer fails when the maximum producible quantity cannot be scheduled far into the future. Instead, it falls back to the requested quantity, helping users open the overview and continue planning without an unnecessary error.
Original PR description
### Steps to reproduce: 1. Install mrp + purchase 2. Create a new product (A) 1. Add the Buy route on the product 2. Add a vendor line on the Purchase tab 3. Set the quantity on hands to 2000 3.…
### Steps to reproduce: 1. Install mrp + purchase 2. Create a new product (A) 1. Add the Buy route on the product 2. Add a vendor line on the Purchase tab 3. Set the quantity on hands to 2000 3. Create a second product (B) with manufacturing route 4. Create a BoM for this product (B) 1. Add the product (A) as the component with 1 quantity 2. Create a new operation with a duration of 600:00 5. On the product B's page, click Replenish 1. Put 10 quantities to replenish 2. Select the manufacturing route and confirm 6. Go to the BoM and open the BoM overview 7. 'Impossible to plan. Please check the workcenter availabilities.' https://github.com/user-attachments/assets/58697fd9-4e3e-4df6-98e1-5de7e8759715 ### Before this commit: When opening the BoM overview, if the producible quantity for this BoM exceed the quantity we can plan in the 700 following days, an error is displayed. ### After this commit: If the quantity producible cannot be planned, we retry automatically with the requested quantity. opw-5031724
Fixes an issue where rental subscriptions using kit products could fail when closed or reopened after deliveries were validated. Delivered quantities are now recalculated consistently, preventing incorrect return errors and helping rental workflows complete reliably.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Enable rental transfers; 2. have a rental product with a kit BoM; 3. create a subscription order in the Rental app; 4. add the rental product; 5. confirm…
Versions -------- - 18.0+ Steps ----- 1. Enable rental transfers; 2. have a rental product with a kit BoM; 3. create a subscription order in the Rental app; 4. add the rental product; 5. confirm order; 6. validate deliveries; 7. close the subscription. Issue ----- Invalid SQL command, cannot return more than was delivered. Cause ----- When closing or reopening a subscription, the `_compute_qty_delivered` method gets triggered. By default, these methods required the relevant moves to have the same `product_id` as the sale order line. For products with kit BoMs, the move's `product_id` is tied to the BoM instead of the final product, leading to `qty_delivered` getting reset reset to 0 on recompute. This causes an error, as `qty_returned` is non-zero. Solution -------- The `qty_delivered` for these lines was set in the `_action_done` method of `stock.move`. By instead moving this logic into a `_compute_qty_delivered` override, any recompute should have the same result, instead of getting reset to 0. opw-4833280
The payroll document generation process now skips creating a payslip document when the employee has no linked contact. This prevents scheduled payroll PDF generation from failing and helps keep payroll document automation running smoothly.
Original PR description
Currently an error occurs when the **'Payroll: Generate pdfs'** scheduled action runs and tries to create a document for a payslip belonging to an employee who does not have a related partner.…
Currently an error occurs when the **'Payroll: Generate pdfs'** scheduled action runs and tries to create a document for a payslip belonging to an employee who does not have a related partner. **Prerequisites:** - Ensure HR is enabled in `settings>Documents` **Steps to Reproduce:** 1) Install `documents_hr_payroll` module.(with Demo) 2) Navigate to the Employees App. 3) Select any Employee(e.g Abigail Peterson) and open form view. >- click on **contacts** smart button. >- Delete that Record 4) Create a confirmed Payslip for the selected Employee(e.g Abigail Peterson). 5) Activate Developer mode and navigate to schedule Actions. >- Search for 'Payroll: Generate pdfs'. >- Run Manually. Error: `NotNullViolation: null value in column 'partner_id' of relation 'documents_access' violates not-null constraint` Root Cause: When the partner is deleted, the value received from `_get_document_partner` at [1] is `False`, which later on tries to create the `documents.access` record for the new document, it fails because no partner is available to assign access rights, resulting in the error. Solution: This commit prevent Error by ensuring `_check_create_documents` method doesn't allow document creation without valid partner. [1]: https://github.com/odoo/enterprise/blob/99a8d83edb42f172d0dd35c91743fa0c9653dcbb/documents_hr_payroll/models/hr_payslip.py#L20C1-L21 sentry-6814524392
Danish banks were rejecting some ISO 20022 payment files because a required clearing instruction was missing. This fix lets administrators configure the needed clearing code so affected payment files can be accepted, while leaving files unchanged when no code is configured.
Original PR description
The denmark banks were refusing ISO20022 documents because there was a missing field: "//PmtInf/PmtTpInf/LclInstrm/Cd" or "//PmtInf/CdtTrfTxInf/PmtTpInf/LclInstrm/Cd". One of those field should be filled by either 'ONCL' or 'SDCL' which means 'Over Night Clearing' or 'Same Day Clearing'. To fix this we added a config parameter with a key: account_iso20022.local_instrument_code where we can set OCNL or SDCL to add the required field to the iso document. If nothing is set, the field will not be added. opw-5073076
Field service sales order lines now recalculate their prices when a task's warranty status changes. This prevents prices from incorrectly staying at zero after warranty coverage is removed, helping ensure customers are billed accurately.
Original PR description
### Steps to reproduce:
- Create a sales order linked to the customer
- Assign a customer (partner) to the task and link the task to the sales order
- Create a sales order line for a product and link it to the task
- Verify the price unit matches the product's list price by default
- Set the task as under warranty
- Add or remove an item from SOL
- Verify the price unit is set to 0.0 in the sales order line
- Unset the warranty status
- Add an item to the SOL
### Cause:
When setting the task as under warranty we modify the price of each SOL to 0.0 but when unset the warranty option we try to fetch the prices from the SOL which we already set it to 0.0
### Fix:
Backporting https://github.com/odoo/enterprise/pull/85492/commits/8615fad5b75d32483b25cf9b1525883e7a730fac to check when writing on the under_warranty value we recompute the SOL prices
opw-4579404Checkout now handles external tax calculation errors more gracefully for Brazilian websites. Instead of leaving shoppers on an endless loading screen, the process can continue and show the relevant issue at the proper validation step.
Original PR description
**Issue** When buying products in the Brazilian localization, certain errors in external tax calculation were not properly caught by the frontend. This caused the checkout to hang indefinitely with…
**Issue** When buying products in the Brazilian localization, certain errors in external tax calculation were not properly caught by the frontend. This caused the checkout to hang indefinitely with infinite loading. Examples include missing NCM codes or IAP service failures due to invalid addresses. **Steps to Reproduce** 1. Install Brazilian localizations (l10n_br, l10n_br_avatax, l10n_br_edi). 2. Configure Avatax Transfer API credentials (API ID and Key). 3. Create a website with a Brazilian company. 4. Add a product to the cart and proceed to checkout. 5. Choose a delivery method and observe that the UI gets stuck loading. **Root Cause** The `_order_summary_values` method in `website_sale_external_tax` called `_get_and_set_external_taxes_on_eligible_records()`, which could raise exceptions (e.g., IAPServerError). These exceptions were not handled, so they propagated to the frontend as generic RPC errors. The frontend has no built-in mechanism to display these exceptions as user-friendly messages, resulting in infinite loading. **Fix** Wrap the external tax calculation in `_order_summary_values` and catch `UserError`. Instead of letting the exception propagate as a generic RPC error, attach the error message to the result dictionary under `external_tax_error`. This prevents the frontend from hanging while still making the underlying problem visible in the next checkout step, where validation errors are properly handled and shown to the user. Opw-5052078