Thursday, July 31, 2025
27 changes · saas-18.4
Enhancements to existing features
HR screens and labels now use “employee record” instead of “version,” making the wording clearer for everyday users. This improves the employee management experience by using language that better matches business expectations.
Original PR description
In this PR, we renamed the version into employee record for a better UX. Related task: 4921404. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The wording previously shown as “version” has been renamed to “Employee Record” across HR and payroll screens. This makes the employee information easier to understand and should reduce confusion for users working with contracts, salary, payroll, and Belgian Dimona workflows.
Original PR description
In this PR, we renamed the version to 'Employee Record' for a better UX. Related task: 4921404.
Point of Sale users can now see whether an IoT Box is connected locally, online, or offline. This makes it easier for store staff to understand hardware connectivity at a glance and react quickly when devices are unavailable.
Original PR description
We now show local/online/offline IoT Box status in pos. Community PR: https://github.com/odoo/odoo/pull/221255 Task: 4978644
The Belgian POS blackbox flow is clearer and easier to use, with updated wording, better clock-in guidance, and simple visual status indicators for users. Installing the blackbox module from the IoT app now refreshes the page automatically, reducing confusion during setup.
Original PR description
- renamed "Social security identification number (INSZ or BIS)" -> "National Register Number", - added page reload after installing module "pos_blackbox_be" from iot app, - improved message "User must be clocked in" to explain why and how to do it, - replaced the clocked (In)/(Out) status by a green/red icon on the user. Task: 4978644
Resolved issues and error corrections
When products valued by lot are revalued, the lot's standard price now updates to match the increase or decrease. This keeps inventory costing information consistent and helps avoid misleading valuation data in stock reports.
Original PR description
### Steps to reproduce 1. Create a product with valuation by lot in AVCO 2. Purchase 10 quantity and validate the transfer 3. In the valuation report, group by product and revaluate the product ### Before this commit The lot is correctly revaluated, but its standard price is not updated ### After this commit The standard price is updated to reflect the value increase/decrease. opw-4890361 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221144 Forward-Port-Of: odoo/odoo#219648
This fix ensures manufacturing orders for serial-tracked products correctly set the finished quantity to one when production starts. This helps quality checks and production workflows use the right quantity for items that must be handled one at a time.
Original PR description
This commit update the finished move quantity of a production of a serial tracked product to 1 when set the quantity producing (always to 1 in case of a serial tracked product) This is mainly mandatory in case the production need to process quality checks. Task : 4575193 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#214985 Forward-Port-Of: odoo/odoo#206109
Point of Sale now correctly lets staff sell products using existing serial or lot numbers when the operation is configured not to create new ones. This prevents blocked sales and helps keep inventory tracking accurate for serialized or lot-tracked products.
Original PR description
After commit https://github.com/odoo/odoo/commit/cb31a37508d32110731ad61b04d5d05dc7b31825, when the PoS picking type was configured to use existing lot numbers and not creating new ones, it was not possible to correctly add products with existing lot numbers. opw-4974345 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220866
Website carousel slides now work correctly while editing translations. This prevents errors when users click carousel arrows in translation mode, restoring expected website editing behavior.
Original PR description
*: html_builder Since the website builder refactoring [1], carousel snippets could no longer slide when in translation mode - clicking the chevrons triggered a traceback. This commit fixes the issue and restores expected navigation behavior. [1]: https://github.com/odoo/odoo/commit/9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2
Odoo Discuss now switches more quickly to its backup call routing when a direct peer-to-peer connection is unlikely to recover. This reduces waiting time and helps users reconnect to voice or video calls faster when no TURN server is available.
Original PR description
Before this commit, falling back to the SFU in case of p2p connection issue would take 2 recovery cycles (±10s), which can be a bit long. This commit makes the fallback happen faster if the client does not have TURN servers, which indicates that the connection is unlikely to be recoverable if it failed. Forward-Port-Of: odoo/odoo#206411
When a product is archived or unpublished after being added to a cart, it is now removed from customer carts before checkout can be completed. This prevents customers from accidentally buying products that are no longer available for sale.
Original PR description
Fix issue where customers could complete purchases of products that where archived or unpublished after being added to cart but before checkout completion. => Step to reproduce bug : - Install website_sale. - Add a product to the cart. - (In an other window) archive the product. - finish the buy from the cart. (don't reload the cart or the product will be gone) => Cause: The bug originate from: https://github.com/odoo/odoo/blob/2d7bb960b00bfeae3e6ab8c0367237f3b08271cb/addons/website_sale/controllers/main.py#L1781-L1793 There is no check up during the last part of the transaction to verify if the product is still available. => Fix: Erase from the product from all cart when it's archived opw-4829872 Forward-Port-Of: odoo/odoo#220656 Forward-Port-Of: odoo/odoo#213656
Users can now add filters in spreadsheet dashboards without triggering an error. The change replaces a misleading link-style control with a proper button, preventing the system from treating the action as page navigation.
Original PR description
steps: - Install "spreadsheet_dashboard" with demo data - Open filter - Click Add Filter - Traceback The problem is due to the fact that initially the button is a <a> containing a href="#" which makes the code (popover.js) believe that a navigation is going to take place. which causes unexpected behavior, such as the fact that in this case we expect to receive a valid target element in the event causing the clickAway (pointerdown, blur or popstate), since it's a popstate, it crashes. The fix consists in replacing the a tag with a button tag, since there's no point in having an a href="#" tag. opw-4964327
This fix prevents Odoo Inventory from creating duplicate stock quantity records when moving entire packages while other packaged products are reserved. It helps keep inventory counts accurate and avoids confusing or incorrect stock data after package transfers.
Original PR description
### Steps to reproduce: - In the settings enable "packages" and Multi-Step Routes - Create a 3 storable products: P1, P2, P3 - Put on hand quantities for each of them: - 1 x P1 in PACK001 in stock -…
### Steps to reproduce:
- In the settings enable "packages" and Multi-Step Routes
- Create a 3 storable products: P1, P2, P3
- Put on hand quantities for each of them:
- 1 x P1 in PACK001 in stock
- 1 x P2 in PACK001 in stock
- 1 x P3 in PACK002 in stock
- Create and confirm a delivery with 3 moves:
- 1 x P1
- 1 x P2
- 1 x P3
- Go to Inventory > Configuration > Warehouse Management > Operation type
- Modify internal transfers to "Move entire packages"
- Create and confirm and internal transfer for PACK001 from stock to the sublocation stock/shelf1
- Mark the package as done and validate the transfer
#### > You end up with 2 quants for PACK002 in stock
### Cause of the issue:
When validating the internal transfer for PACK001, we launch an `_action_done` on the moves lines of the internal transfer. In particular, during this action done, a `quant_cache` will be set for to fetch and use the quants for P1 and P2:
https://github.com/odoo/odoo/blob/cb1c761777e84d96f82c4f754586795509ce1b3d/addons/stock/models/stock_move_line.py#L679-L681 https://github.com/odoo/odoo/blob/cb1c761777e84d96f82c4f754586795509ce1b3d/addons/stock/models/stock_quant.py#L933-L949 This cache is correctly use in order to update our move lines during the `synchronize_quant` that will follow:
https://github.com/odoo/odoo/blob/cb1c761777e84d96f82c4f754586795509ce1b3d/addons/stock/models/stock_move_line.py#L684-L692 However, they are not in the `_free_reservation` because this call will reassign the move line and then `_check_entire_pack` for the entire picking:
https://github.com/odoo/odoo/blob/cb1c761777e84d96f82c4f754586795509ce1b3d/addons/stock/models/stock_move.py#L1980-L1981 In particular, it will update the reservation for the move related to P3. But, since the `quant_cache` is taken from the context and did not change it can not find the quants related to P3 and a new quant will be created in addition to the already existing one: https://github.com/odoo/odoo/blob/82639728f2bcb4e7786f120de2aeba3f5fbab209/addons/stock/models/stock_quant.py#L1055 https://github.com/odoo/odoo/blob/82639728f2bcb4e7786f120de2aeba3f5fbab209/addons/stock/models/stock_quant.py#L1101
opw-4922032
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#219049This fix makes the website editor better preserve which content blocks are active or inactive when users apply changes and use undo or redo. It removes older workaround behavior so editing actions replay consistently, reducing confusing results while building pages.
Original PR description
[FIX] html_builder, website: allow to ask to deactivate the containers Commit [1] made it so an option can ask to activate the containers of a given element after adding its step. Logic was also…
[FIX] html_builder, website: allow to ask to deactivate the containers Commit [1] made it so an option can ask to activate the containers of a given element after adding its step. Logic was also added to properly restore these containers on undo/redo. This commit adds the logic to also ask to deactivate the containers, as this behavior should also be restored on undo/redo (if an option asks to deactivate the containers, then undo and redo, the containers should be deactivated after replaying the option). [1]: https://github.com/odoo/odoo/commit/203a7af2c2b27c02be7b201f5c707f46caa34573 task-4367641 --- [FIX] html_builder, website: review the calls to `updateContainers` Since commit [1] (and the previous commit of this PR), when an operation wants to activate another target, it should use `setNextTarget`. It guarantees that the target is activated at the right time and that it will correctly be restored on undo/redo. Before these commits, this behavior was achieved by using a hack, by calling `addStep` and then `updateContainers` in the `apply` of options (so before calling the `addStep` post apply, which would then do nothing as there is no mutation anymore). This commit removes this hack use, as a follow-up of the mentionned commits. This commit also adds the missing calls to `setNextTarget` that were not added back with the refactoring. This was done by looking where the `activate_snippet` event of the old code was triggered. This ensures that the behavior stays the same as before the refactoring. [1]: https://github.com/odoo/odoo/commit/203a7af2c2b27c02be7b201f5c707f46caa34573 task-4367641
This fixes a website builder issue where users could undo changes after a failed save, causing the page to show one thing while saving another. The builder now clears undo history when saving and warns appropriately after a failed save, reducing the risk of confusing or incorrect website edits.
Original PR description
In case of error during the save, the website builder stays open for the user to fix their changes, this was implemented in 9b7f06f53e71ea4a6db5168fd3e019406fc3a82f. Unfortunately, this enables to…
In case of error during the save, the website builder stays open for the user to fix their changes, this was implemented in 9b7f06f53e71ea4a6db5168fd3e019406fc3a82f. Unfortunately, this enables to user to undo changes that were saved. This is not well handled by the builder, which may not save what the user see after undo (for example if they undid the first change of a field, the `o_dirty` mark is removed and the field won't be saved again) Steps to reproduce: - On `/blog`, open website builder - Change the title of a blog post - Change a date to something invalid - Click on save - Close the dialog about the failure to save because of the date - Undo everything (the change to the date and the title) - Click on save - Bug: the change on the title is still present To prevent this, the history is cleared on save, and a flag marking the last save as failed is kept by the builder to prompt the user if they want to discard unsaved changes. Resetting the history on save makes the condition added by 30bbe413f1122bf243eb6e073be6fa19dddf984a redundant, therefore it is removed task-4367641
Fixes an issue where connected hardware devices were not sent correctly right after pairing with a database. The update ensures the latest pairing token is used, reducing setup friction before the next restart.
Original PR description
Since the PR odoo/odoo#218109, the send_all_devices logic was refactored to always send whenever something changes. However, there was a bug introduced due to the fact the token is saved at start-up and never updated. This caused the devices to not get sent correctly immediately after pairing with a DB (in the time before checking out and restarting). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221250 Forward-Port-Of: odoo/odoo#221178
Fixes an issue where shoppers could see an error after starting payment, using the browser back button, and changing product quantities in the cart. The cart now handles this empty-cart situation gracefully, improving checkout reliability and avoiding a disruptive crash.
Original PR description
This error occurs when attempting to update the quantity in the cart. Steps to Reproduce: --- - Install the `website_sale` module - Activate `Demo` payment provider - Go to Website > Shop > Add a product to Cart > View cart - Pay with Demo > Pay - Click the back button(chrome navbar)(Instantly) - Change the quantity for the product Traceback: --- ValueError: Expected singleton: sale.order() At [1], this error occurs because `order_sudo` is empty. This happens when there are no products in the cart — typically because, upon clicking`Pay`, a sale order is created for the product, and when the user navigates back, the cart is empty. [1]- https://github.com/odoo/odoo/blob/a8a7a26dbda046db6f679bc29940add510e34485/addons/website_sale/controllers/cart.py#L248 sentry-5682671428 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#206000
This fixes how failed quantity-based quality checks move stock into failure locations, ensuring related stock moves are split correctly when needed. It helps prevent inventory routing and valuation problems caused by stock lines ending up in locations that do not match their parent move. It also blocks an incompatible quality check setup for manufacturing orders to avoid invalid stock splitting.
Original PR description
In case of 'quantity' control per quality point. If a complete stock move line is sent to a failure location. The stock move was not split. We could have a stock move line going to a location that is not child of the location of the corresponding move. This can lead issues in case of push_rules or stock valuation. Task: 4575193 Forward-Port-Of: odoo/enterprise#88040 Forward-Port-Of: odoo/enterprise#81275
Fixed an issue in the Barcode app where scanning certain lot numbers during receipts could store an invalid value and then crash the workflow. This helps warehouse users continue receiving tracked products reliably when using existing lots and consignment settings.
Original PR description
## How to reproduce: https://github.com/user-attachments/assets/bf44f9fd-0402-4d70-8b55-5baf192d42e8 - Enable Consignment - On Receipt operation type, enable 'Use existing lots' - Create product P,…
## How to reproduce:
https://github.com/user-attachments/assets/bf44f9fd-0402-4d70-8b55-5baf192d42e8
- Enable Consignment
- On Receipt operation type, enable 'Use existing lots'
- Create product P, tracked by lot
- Create lot SN-001 & SN-002
- Add 1 unit on hand with lot SN-001
- Create Receipt for 10 units of P -> Confirm
- Open receipt on Barcode App
- Scan "SN-002" => 'undefined' value added to 'dbQuantCache'
- Scan "SN-001" => Uncaught Promise > quantsByLocation is not iterable (cannot read property undefined)
---
## Test result without fix:
```
2025-07-18 09:30:33,801 20801 ERROR oes_test_18 odoo.addons.stock_barcode.tests.test_barcode_client_action_picking: FAIL: TestPickingBarcodeClientAction.test_barcode_lazy_cache_scan_two_lots
Traceback (most recent call last):
File "/home/odoo/projects/odoo-src/multiverse/src/18.0/enterprise/stock_barcode/tests/test_barcode_client_action_picking.py", line 3508, in test_barcode_lazy_cache_scan_two_lots
self.start_tour(url, 'test_barcode_lazy_cache_scan_two_lots', login='admin')
File "/home/odoo/projects/odoo-src/multiverse/src/18.0/odoo/odoo/tests/common.py", line 2264, in start_tour
return self.browser_js(url_path=url_path, code=code, ready=ready, timeout=timeout, success_signal="tour succeeded", **kwargs)
File "/home/odoo/projects/odoo-src/multiverse/src/18.0/odoo/odoo/tests/common.py", line 2235, in browser_js
self.fail('%s\n\n%s' % (message, error))
AssertionError: The test code "odoo.startTour('test_barcode_lazy_cache_scan_two_lots', {"stepDelay": 0, "keepWatchBrowser": false, "debug": false, "startUrl": "/odoo/147/action-stock_barcode.stock_barcode_picking_client_action", "delayToCheckUndeterminisms": 0})" failed
TypeError: quantsByLocation is not iterable (cannot read property undefined)
at LazyBarcodeCache.getQuants (http://127.0.0.1:8565/web/assets/3d6bda7/web.assets_web.min.js:21482:279)
at BarcodePickingModel._processBarcode (http://127.0.0.1:8565/web/assets/3d6bda7/web.assets_web.min.js:21748:631)
at async http://127.0.0.1:8565/web/assets/3d6bda7/web.assets_web.min.js:21661:75
```
OPW-4942192
Forward-Port-Of: odoo/enterprise#90828
Forward-Port-Of: odoo/enterprise#90492Users can now open the map view for warehouse transfers even when batch transfer features are not enabled. This prevents an error that blocked access to Receipts, Delivery Orders, and similar stock operation map views.
Original PR description
When a user without enabling 'Batch, Wave & Cluster Transfers' from settings, tries to open the map view for any stock transfer operations (e.g., Receipts, Delivery Orders), a error is raised.…
When a user without enabling 'Batch, Wave & Cluster Transfers' from settings, tries to open the map view for any stock transfer operations (e.g., Receipts, Delivery Orders), a error is raised. **Steps to Reproduce:** - Install Inventory App. - Navigate to 'Receipts' or 'Delivery Orders'. - Switch to map view. **Error:** `ValueError: Invalid field 'batch_sequence' on model 'stock.picking'` **Root Cause:** Since [this commit](https://github.com/odoo/enterprise/pull/78373/commits/fddb39104d675af2784559fe2f7cb28f8dc6120b), the `stock.picking.view.map` view has a hardcoded `default_order` attribute that sorts by `batch_sequence` as shown at [1]. This field is only added to the `stock.picking` model when the `stock_picking_batch` module is installed. This creates an invalid view definition, where this optional module is not present, causing an error. **Solution:** This commit resolves the issue by removing the `default_order='batch_sequence'` from the stock picking map view at [1]. This ensures the map view no longer depends on the `stock_picking_batch module`. [1]- https://github.com/odoo/enterprise/blob/5e0380513899f199340620d8ce17eff5b5b6aec3/stock_enterprise/views/stock_picking_map_views.xml#L8 sentry-6732756118
This fixes an issue where some important Studio customization data could be left out during export. Exports now keep required fields for views, automations, approvals, attachments, and related customizations, helping ensure Studio changes can be transferred reliably.
Original PR description
If you create a **StudioExportModel** with a model that we always export (for studio customizations, i.e. ir.ui.view) then the excluded_fields field gets computed. Before this commit, the _compute_excluded_fields method of the StudioExportModel model could have excluded some fields we would like to export. This commit fixes that. **List of fields we should export but by default were excluded:** - "base.automation": "action_server_ids" - "ir.model.fields": "selection" - "studio.approval.rule": ["approver_ids", "can_validate"] - "ir.ui.view": "arch" - "ir.attachment": "datas" task-4866474 Forward-Port-Of: odoo/enterprise#91105 Forward-Port-Of: odoo/enterprise#88125
Kitchen ticket printing through connected IoT devices now works correctly when the usual connection path needs to fall back to websockets. Point of Sale also loads the required IoT devices more reliably, preventing checkout staff from seeing errors when configured kitchen printers have not changed recently.
Original PR description
Due to a missing `iot_id` field when the `DeviceController` for kitchen printers is instantiated, the websocket fallback does not work. This results in kitchen tickets failing to print even when regular receipts are working correctly. The fix is to provide the full IoT device model to the `DeviceController` constructor, as is done elsewhere. To do so we now pass the `device_id` field for the preparation printer model from the backend. We also ensure IoT devices/boxes are loaded even with a 'limited' load. This is because of an issue where an IoT device is added to the PoS config, but because the device itself has not be written to recently, the PoS doesn't load it and you get a traceback in the frontend. Forward-Port-Of: odoo/enterprise#91260
Installing Payroll on a new Australian database no longer crashes when pay schedule information is initially missing. The system now safely defaults the pay schedule to monthly, helping new payroll setups complete smoothly.
Original PR description
When installing the payroll app with a new db initialized in Australia, we would get a traceback because the schedule pay is False at some point. This was due to the compute of schedule pay which did not handle the case where the structure type is not set. This fixes the issue by checking if the structure type is set to set the schedule pay and adding a default value to monthly. Ticket: 4974520
Mexican POS global invoices now use the issuing address set on the sales journal when available, instead of defaulting to the company address. This ensures the official XML shows the correct place of issue, helping businesses avoid incorrect tax document details.
Original PR description
Steps to reproduce: [l10n_edi_extended] - setup up a mexican company - create a journal in which you define an issued address (different from your company) - setup your pos with newly created journal - Open a pos session - add a product - pay in cash with no customer - in the backend go into the orders - select the newly created order in the list view and click on the action "create global invoice" - in the order > cfdi: download the created xml Issue: The "Lugar de expedicion" will have the zip code of the company and not from the issued address one Cause: We only check for issue adress in account_move but not from orders. Global invoice is not only for invoices but also to account for sale (orders) made with petty cash Solution: We don't want to create a bridge module only for that. We check if the field is defined on `account.journal` opw-4802389 Forward-Port-Of: odoo/enterprise#86545
Payslip PDFs now correctly respect the salary structure setting to hide the basic wage. This prevents confidential or unnecessary wage details from appearing when payroll teams have chosen to exclude them.
Original PR description
After this commit: odoo/enterprise@9dceed0896ce5089bccbc9cc2ce1e8c4b13f0048…
After this commit: odoo/enterprise@9dceed0896ce5089bccbc9cc2ce1e8c4b13f0048 [diff](https://github.com/odoo/enterprise/commit/9dceed0896ce5089bccbc9cc2ce1e8c4b13f0048#diff-de4a628e7837c273b67d71f93efab85b6a9ee957ea702f502066ebcc632a76cbL64) The condition that handles hiding the basic wage on the payslip was not added —possibly it was missed. That’s why the "Hide basic on PDF" feature doesn’t work, regardless of whether it’s enabled, as the necessary condition is missing in the template. Steps to reproduce (on runbot): - In a v18 runbot, open any payslip and go to the salary structure. Enable the "Hide basic on PDF" option. - Return to the payslip and print it. - You’ll see that the basic wage is still printed on the payslip. **Before Fix:** <img width="669" height="238" alt="payslipbefore" src="https://github.com/user-attachments/assets/2fce67a2-19d8-45d8-88fa-4fc6a1767e68" /> **After Fix:** <img width="683" height="289" alt="payslipafter" src="https://github.com/user-attachments/assets/adcb0104-9c4e-4a35-ba78-b3f278f6bfda" /> opw-4953831 Forward-Port-Of: odoo/enterprise#90798
The signing template screen is easier to use: edit buttons now take users directly to the right field, and unnecessary edit icons are hidden when only viewing a template. A document menu display issue was also corrected, making the template experience cleaner and more reliable.
Original PR description
Improved the sign_template_sidebar view by enabling pencil buttons to focus corresponding input fields for editing, and hidden the edit icons in template visualization mode for a cleaner experience. Additionally, fixed the document menu button to ensure proper display. task-4908825
Tax prediction now uses the correct accounting entry when suggesting taxes. This helps prevent failed or missing tax predictions, improving accuracy for accounting workflows.
Original PR description
Previously, when _predicted_field was invoked from _predict_specific_taxes, self did not have an associated move_id. As a result, _build_predictive_query was unable to construct the correct query, causing the prediction logic to fail and return False. With this fix, the correct move_id is passed through the context and later retrieved in _predicted_field. This ensures that the prediction logic uses the intended move_id and functions as expected. **task**-4943015 Community PR - https://github.com/odoo/odoo/pull/219911 Forward-Port-Of: odoo/enterprise#91224
The Italian Libro Giornale PDF report now shows long descriptions in the Name column without cutting them off. Column spacing has also been stabilized, making the exported report easier to read and more reliable for accounting review.
Original PR description
Issue: In the Libro Giornale report (PDF), long descriptions in the 'Name' column were getting cut off, and column spacing appeared inconsistent in the generated PDF. These issues reappeared due to recent layout changes from commit https://github.com/odoo/enterprise/commit/233e82cf4e6908502a580be4bcd77fadd2aada53, which unintentionally removed previous fixes made to handle such cases. Fixes Applied: - Reintroduced the `o_overflow_name` class on the 'Name' column to ensure long descriptions wrap correctly and are not truncated in the PDF export. - Applied the `o_fixed_column_width` class to the 3rd column (currently 'Account Code') to resolve inconsistent spacing between columns caused by `wkhtmltopdf`. Forward-Port-Of: odoo/enterprise#91231