Daily updates from Odoo
Tuesday, August 26, 2025
15 changes · 18.0
Enhancements to existing features
The updated UBL BIS3 electronic invoice generation helpers are now enabled by default, improving consistency with the newer invoice creation process. Businesses can still opt out if needed by changing the related configuration setting.
Original PR description
In 0f3a9dee5cf15 we back-ported the new refactored helpers for UBL BIS3 generation to 18.0. However the new helpers would be used only if the `ir.config.parameter` `account_edi_ubl_cii.use_new_dict_to_xml_helpers` was set to True. This commit switches the new helpers on by default in 18.0 -> 18.3, but they can still be switched off by setting that parameter to False. task-none
The shop floor now remembers the user’s last selected work center when they leave and return using breadcrumbs. This keeps the view consistent while preserving the existing behavior when opening shop floor from Manufacturing work centers.
Original PR description
Description of the issue/feature this PR addresses: Incoherent selection of workcenters when using the breadcrumbs to come back to the shopfloor app:…
Description of the issue/feature this PR addresses: Incoherent selection of workcenters when using the breadcrumbs to come back to the shopfloor app: https://drive.google.com/file/d/1C1nVdDHgCss7s7zyXDOpbMj0k79HlJBH/view?usp=drivesdk Current behavior before PR: When leaving the shopfloor app via a WO (WO setting -> Open MO), we set the a **context flag workcenter_id** in the the currentCaller.action.context to save the selected workcenter for breadcrumb logic. The same **context flag workcenter_id** is used in the Manufacturing/workcenters view, when clicking on a workcenter. However, the intended use of the **workcenter_id flag** is different: - 1 From Manufacturing: Open shop floor with **only** workcenter_id selected + visible (no other workcenters visible). - 2 From Shopfloor breadcrumb : Go to shop floor with all previous workcenters same as when leaving. Additionally the current logic for setting the workcenter_id flag from the MrpDisplay record currently handles only the selection of isMyWO ([PR](https://github.com/odoo/enterprise/pull/52258)) Desired behavior after PR is merged: Keep the same behavior when coming from Manufacturing/workcenters ([PR](https://github.com/odoo/enterprise/pull/67318)) but make sure the user come back to same view when leaving shopfloor and coming back via breadcrumbs. task: [4629641](https://www.odoo.com/odoo/project/966/tasks/4629641) I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr)
Resolved issues and error corrections
Sales order line prices now correctly refresh when a quantity change qualifies for a different pricelist rule. This helps businesses avoid incorrect customer pricing and reduces the need for manual price updates or pricelist switching.
Original PR description
> [!Note] > This PR unreverts fc6b9ed22728 with a minor modification to ensure one `res.currency` record to compare amounts. **Steps to reproduce**: 1. Install the `sale` module. 2. Enable…
> [!Note] > This PR unreverts fc6b9ed22728 with a minor modification to ensure one `res.currency` record to compare amounts. **Steps to reproduce**: 1. Install the `sale` module. 2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`. 3. Create two pricelists: - Pricelist A with two fixed-price rules: - 0.75 for quantity ≥ 0 - 0.50 for quantity ≥ 1000 - Pricelist B with a -10% discount applied to Pricelist A. 4. Create a Sales Order using Pricelist B. 5. Add a product to the order line. 6. Increase the quantity to 1000. **Observed behavior**: - The unit price does not update according to the pricelist rule for quantity ≥ 1000. - If you switch the pricelist to another and then back again, the `Update prices` button appears and correctly updates the price. **Root cause**: - The price is not recomputed when the quantity changes because the `price_unit` is not updated because it does not match the `technical_price_unit`. - Since e1b22257a714, `price_unit` is rounded (2 decimals), but `technical_price_unit` is not. This causes a mismatch in comparison logic due to rounding differences. **Solution**: - Replace direct float comparison with `currency_id.compare_amounts()` to ensure proper comparison with rounding precision. opw-4944644
This fix ensures that changing a product's unit of measure on a sales quotation recalculates the unit price every time, not just the first time. It prevents incorrect pricing when sales teams adjust units repeatedly, keeping quotation amounts accurate.
Original PR description
Problem: When the user changes the UOM on a product more than once, the unit price no longer recomputes. The technical_price_unit and the price_unit are out of sync in which the uom change gets recognized as a manual change from the user. Thus, it no longer recomputes the unit price. Purpose: The unit price should always recompute when the uom is simply being modified more than once. Steps to reproduce on Runbot 18: 1. Install Sales and accounting 2. Enable Units of Measure in Settings > Sale 3. Create a product, Soda, whose units is L 4. Create a quotation and add the product Soda 5. Change the uom on the line for the first time --> price_unit changes 6. Change the uom on the line for the second time --> price_unit does not change opw-4998017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where dropshipped product backorders could record inventory valuation amounts for the full original order instead of only the delivered backorder quantity. Businesses using FIFO or average costing with dropshipping will now see more accurate valuation entries after partial deliveries and vendor bills.
Original PR description
…order dropship **Problem:** when the backorder of the delivery (with a bill) of a dropshipped fifo/avco product is validated, the svl created don't have the right values **Steps to reproduce:** -…
…order dropship **Problem:** when the backorder of the delivery (with a bill) of a dropshipped fifo/avco product is validated, the svl created don't have the right values **Steps to reproduce:** - create a new product, with dropship and buy routes - in the purchase tab select "on ordered quantities" - add a vendor with a price of 10 - create a new quotation for a quantity of 10 - confirm and confirm the purchase order - click on "create bill" and confirm it - go back to the PO and click on the "dropship" smart button - change the quantity to 5, validate and create backorder - go back to the PO, click on the "dropship" smart button and select the picking of the backorder (with status ready) - validate - click on the "valuation smart" button **Current behavior:** the svl created for the backorder have a value of 100 and -100 **Expected behavior:** it should be 50 and -50 **Cause of the issue:** inside _get_dropshipped_svl_vals _get_price_unit is called https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/stock_account/models/stock_move.py#L219 because we created a bill and it's a backorder line.qty_invoiced is higher than received_qty and this condition is true https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/purchase_stock/models/stock_move.py#L51 but because it's a dropship there is as much positive svl as negative svl linked to the move so receipt value is null https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/purchase_stock/models/stock_move.py#L56-L63 and remaining value will be 100 instead of 50 (receipt value should have been 50) https://github.com/odoo/odoo/blob/f7c8cc76f15bc6e974969fb4ab4a93654443b973/addons/purchase_stock/models/stock_move.py#L80 **fix** the negative svl from the dropshipped move should not impact receipt value opw-4888827 Forward-Port-Of: odoo/odoo#216899
The spreadsheet component was updated to the latest version, bringing fixes for menu item alignment and Excel copy-paste behavior. This improves day-to-day spreadsheet usability and reduces formatting or interaction issues for users working with imported Excel data.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/7ad0e33f4 [REL] 18.0.42 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/7ad0e33f4 [REL] 18.0.42 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/95353174b [FIX] menu: Fix menu item alignment [Task: 5028721](https://www.odoo.com/odoo/2328/tasks/5028721) https://github.com/odoo/o-spreadsheet/commit/c3b56522c [FIX] Figure: icon of the menu item is not vertically aligned [Task: 4992687](https://www.odoo.com/odoo/2328/tasks/4992687) https://github.com/odoo/o-spreadsheet/commit/313784f22 [FIX] clipboard: fix copy-paste from Excel [Task: 4730469](https://www.odoo.com/odoo/2328/tasks/4730469) Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya <rmbh@odoo.com> Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
This fixes a point-of-sale restaurant issue where staff could not add or adjust a tip once an order had already been invoiced. Businesses can now record tips correctly in this scenario, helping keep customer payments and accounting entries accurate.
Original PR description
In e3c95b9e34388bd059bbe41665ba3d62de0acab5, we make sure to update the payment_line.amount when tipping, for the accounting line to work properly. However, updating the amount on a payment line is only allowed if the order state is not 'done' or 'invoiced', which means, if a user tries to tip an 'invoiced' order, it doesn't work!! Here, we make an exception that allows updating the amount on the payment line of a tipped order in 'invoiced' state. opw-4736154
Refunds for lot-valued products in Point of Sale now correctly complete the related stock transfer when the session is closed. This prevents refund operations from leaving inventory documents stuck and helps keep stock and valuation records accurate.
Original PR description
When refunding a product that was lot valuated, the picking would not be validated automatically. Steps to reproduce: ------------------- * Create a product tracked by lot, and valuated by lot * Open PoS and create an order with this product * Validate the order and create a refund for it * Validate the refund * Close the session, and go to the picking of the session > Observation: The picking is not validated automatically. Why the fix: ------------ It was happening because the line that was put to 0 here (https://github.com/odoo/odoo/blob/eab97bed9c55a9057c7af7450ae1a09c6383a7b5/addons/point_of_sale/models/stock_picking.py#L249) has no lot assigned and should be deleted instead of just put to 0 quanity. It would then raise an error here (https://github.com/odoo/odoo/blob/2d933b83613ad52d76ab457201adecac6fcf184b/addons/stock_account/models/stock_move_line.py#L94) and cancel the validation of the picking. opw-4769042
Odoo now avoids reusing archived supplier bank accounts when importing electronic vendor bills with bank details. This prevents duplicate bank account errors that could block bill creation and interrupt accounts payable processing.
Original PR description
### Issue When receiving vendor bills that include bank details, if the partner has archived bank accounts, Odoo may attempt to update them. This leads to a duplicate key violation on…
### Issue
When receiving vendor bills that include bank details, if the partner has archived bank accounts, Odoo may attempt to update them. This leads to a duplicate key violation on `res_partner_bank` when the same account number already exists for the partner.
#### Affected versions
16.0 and later
#### Error example
```bash
2025-07-08 13:36:52,942 204 INFO server-dummy odoo.addons.mail.models.mail_thread: Routing mail from "Client Name" <erp@odoo.com> to "M7- Odoo V17" <purchases@test.odoo.com>,purchases@test.odoo.com with Message-Id <*****.****.*****-****-*****-****.****@******>: direct alias match: ('account.move', 0, {'company_id': 1, 'move_type': 'in_invoice', 'journal_id': 10}, 1, mail.alias(6,))
2025-07-08 13:36:52,946 204 INFO server-dummy odoo.addons.mail.models.mail_thread: Primary email missing on account.move
2025-07-08 13:36:53,576 204 ERROR server-dummy odoo.sql_db: bad query: UPDATE "res_partner_bank" SET "acc_holder_name" = 'M7 GROUP INC.', "company_id" = NULL, "has_iban_warning" = false, "has_money_transfer_warning" = false, "sanitized_acc_number" = '1234567', "write_date" = '2025-07-08T13:36:52.897826'::timestamp, "write_uid" = 1 WHERE id IN (63)
ERROR: duplicate key value violates unique constraint "res_partner_bank_unique_number"
DETAIL: Key (sanitized_acc_number, partner_id)=(1234567, 3524) already exists.
2025-07-08 13:36:53,576 204 ERROR server-dummy odoo.addons.account.models.account_move: Error importing attachment 'factur-x.xml' as invoice (decoder=_import_invoice_ubl_cii)
Traceback (most recent call last):
File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 3219, in _extend_with_attachments
with self.env.cr.savepoint():
File "/home/odoo/src/odoo/odoo/sql_db.py", line 85, in __exit__
self.close(rollback=exc_type is not None)
File "/home/odoo/src/odoo/odoo/sql_db.py", line 89, in close
self._close(rollback)
File "/home/odoo/src/odoo/odoo/sql_db.py", line 113, in _close
self._cr.flush()
File "/home/odoo/src/odoo/odoo/sql_db.py", line 137, in flush
self.transaction.flush()
File "/home/odoo/src/odoo/odoo/api.py", line 879, in flush
env_to_flush.flush_all()
File "/home/odoo/src/odoo/odoo/api.py", line 739, in flush_all
self[model_name].flush_model()
File "/home/odoo/src/odoo/odoo/models.py", line 6362, in flush_model
self._flush(fnames)
File "/home/odoo/src/odoo/odoo/models.py", line 6464, in _flush
model.browse(ids)._write(vals)
File "/home/odoo/src/odoo/odoo/models.py", line 4548, in _write
cr.execute(SQL(
File "/home/odoo/src/odoo/odoo/sql_db.py", line 332, in execute
res = self._obj.execute(query, params)
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "res_partner_bank_unique_number"
DETAIL: Key (sanitized_acc_number, partner_id)=(1234567, 3524) already exists.
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#224071
Forward-Port-Of: odoo/odoo#223873Sales order lines now recalculate unit prices correctly when quantity changes trigger a different pricelist rule. This prevents customers from seeing or being charged outdated prices when volume-based pricing should apply.
Original PR description
**Steps to reproduce**: 1. Install the `sale` module. 2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`. 3. Create two pricelists: - Pricelist A with two fixed-price rules: -…
**Steps to reproduce**: 1. Install the `sale` module. 2. Enable `Pricelists` under `Settings > Sales > Pricing > Pricelists`. 3. Create two pricelists: - Pricelist A with two fixed-price rules: - 0.75 for quantity ≥ 0 - 0.50 for quantity ≥ 1000 - Pricelist B with a -10% discount applied to Pricelist A. 4. Create a Sales Order using Pricelist B. 5. Add a product to the order line. 6. Increase the quantity to 1000. **Observed behavior**: - The unit price does not update according to the pricelist rule for quantity ≥ 1000. - If you switch the pricelist to another and then back again, the `Update prices` button appears and correctly updates the price. **Root cause**: - The price is not recomputed when the quantity changes because the `price_unit` is not updated because it does not match the `technical_price_unit`. - Since PR (https://github.com/odoo/odoo/pull/213912), `price_unit` is rounded (2 decimals), but `technical_price_unit` is not. This causes a mismatch in comparison logic due to rounding differences. **Solution**: - Replace direct float comparison with `currency_id.compare_amounts()` to ensure proper comparison with rounding precision. opw-4944644
Point of Sale now keeps automatic receipt printing working when a store is offline but still connected to its local receipt printer. This prevents staff from having to manually print receipts during internet outages and keeps checkout operations consistent.
Original PR description
Steps to reproduce: 1. Configure a POS to use a receipt printer with automatic receipt printing. 2. Confirm that the receipt is printed automatically after a order is made as expected. 3. Disconnect from the internet so that POS continues in Offline mode (but ensure you still have access to the receipt printer on the local network). 4. Make an order in offline mode. EXPECTED: The receipt is printed automatically as before ACTUAL: The receipt is not printed. The fix is to still run the `afterOrderValidation` method in offline mode, as previously it was being bypassed and the receipt screen being shown directly. task-4946305 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes a problem where changing the quantity on a subcontracted receipt could block validation when component lots or serial numbers were required. Users are guided to update quantities through the proper wizard and can access related production records when component details need attention.
Original PR description
Issue ----- The problem is when a subcontracted product has a component tracked by lots. Creating a receipt for the subcontractor, marking it as Todo then changing the quantity leads to the reception…
Issue
-----
The problem is when a subcontracted product has a component tracked by lots. Creating a receipt for the subcontractor, marking it as Todo then changing the quantity leads to the reception being impossible to validate because the lots for the components cannot be set from the move.
Steps to reproduce
-----
- Create a product (Comp1)
- Tracked by lots
- Create a product (Prod1)
- Add a BoM - Subcontracted - Flexible consumption - Set Comp1 as consumable
- Create a receipt for 2 Prod1
- Mark as Todo
- Set Quantity to 3
- Save
- Try to validate the receipt
Situation
-----
Before changing the quantity, the user has 2 buttons ("Record components" and the move's hamburger) which open the "Subcontract" wizard. This wizard is where they can set a lot/serial for the products.
When they change the quantity of the move, the inverse method of quantity is called
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/stock/models/stock_move.py#L170-L171
This method is overridden in the mrp_subcontracting module
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/stock_move.py#L75
The part that's important to our use case is
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/stock_move.py#L81-L82
Recording components leads us to create a backorder production
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/mrp_production.py#L90-L91
In our specific use case, this is problematic because the subcontract wizard loads the form of the last production
https://github.com/odoo/odoo/blob/74a8334558bf86c07c0d68090a9126911867ef42/addons/mrp_subcontracting/models/stock_move.py#L245
The user has no way to access the previous production which lacks lot/serial (other than opening the MO itself). Obviously, we don't want to mess with this flow, but there are 2 things we can do:
1. Avoiding weird cases such as this one by forcing the user to change the quantity through the appropriate wizard
2. Providing a link to the mrp.production once some production has been recorded
For the first point, the stock.move model already has a field we can use
https://github.com/odoo/odoo/blob/8c8449f51d5e327ccd2e4bb7c3c4868d51c6d619/addons/stock/models/stock_move.py#L180
We can just override the compute to fit our use case.
For the second point, there is already a button for this. The problem is that its display condition was changed in 9ca1064 to only show once the move is picked. This fix was a bit of an over correction because we also want to show the button for unpicked moves for which a production has been recorded.
-----
Ticket:
opw-4751896Recurring invoices are now created for subscriptions with timesheet-delivered services even when the original sales order quantity or recurring value is zero. This prevents valid billable work from being incorrectly treated as a free renewal and skipped during automated invoicing.
Original PR description
### Steps to reproduce: - Install Helpdesk, Sale Subscription apps - Create a service recurring product and set its invoicing policy as 'Based on Timesheets' - Create a SO with the created product and set the qty to 0 - Create a Helpdesk ticket and link it to the SO - Record some timesheets in this SO - Run the cron for generating recurring invoices - Notice no invoice will be created for the SO and it will be considered as free renewal ### Cause: When trying to create a recurring invoice we check if the invoice that will get generated is free by checking the MRR and the total amount of the SO and if one of them are 0 we will flag this invoice as free so we won't generate it ### Fix: We check if the order lines to be invoiced is invoiced based on delivery and they have delivered quantity already and if so we create the invoice even if the MRR and the total amount is equal 0 opw-4990478
Quality IoT setups can now distinguish between multiple connected cameras, allowing more than one camera to be used at the same time. Existing camera configurations are preserved through a temporary compatibility identifier, and camera communication is made more reliable by avoiding websocket errors.
Original PR description
Due to an issue with the `CameraInterface`, the same identifier would be chosen for any connected camera (`camera-2`), meaning only one camera could be used at once. To fix this, the `camera.id`…
Due to an issue with the `CameraInterface`, the same identifier would be chosen for any connected camera (`camera-2`), meaning only one camera could be used at once. To fix this, the `camera.id` property is used as the identifier instead. The `libcamera` documentation says the following: > The camera ID is a free-form string that identifies a camera in the > system. IDs are guaranteed to be unique and stable: the same camera, > when connected to the system in the same way > (e.g. in the same USB port), will have the same ID across both > unplug/replug and system reboots. However, we will also still return the last camera with the `camera-2` identifier, so that existing device configurations in the backend don't get lost. In master we will remove this legacy identifier. You can see the legacy camera with the others in the list below: <img width="801" height="385" alt="image" src="https://github.com/user-attachments/assets/6f3a6408-bcb4-46b0-980e-b5a8881f6df0" /> In addition, another small fix was made to the `CameraDriver` to ensure a string is sent rather than raw bytes, this prevents a traceback when communicating over the websocket. task-4792552 Forward-Port-Of: odoo/enterprise#93076
Users can now duplicate multiple appointment bookings at the same time from the list view without triggering an error. This removes a blocker for staff managing several bookings and makes appointment administration smoother.
Original PR description
This error occurs when users attempt to duplicate multiple bookings within an appointment. Steps to reproduce: --- - Install `appointment` module - Select an appointment (ie. Dental Care) - Click on New and make 2 new bookings - Go to list view > Select both records > Duplicate Traceback: --- `ValueError: Expected singleton: calendar.event(5, 8)` This happened because the `copy()` method in `calendar.event` assumed a single record, but in list view, users can select and duplicate multiple records at once. Reference commit: https://github.com/odoo/enterprise/commit/6e85fff3d9fce23f8591e6bb3340749c889c9934 Done for single record.