Daily updates from Odoo
Tuesday, November 4, 2025
202 changes
15 changes
Enhancements to existing features
This update refreshes the QR-code URLs sent to Avalara when issuing Brazilian NFC-e invoices. It prevents invoice errors caused by outdated links, helping sales operations continue smoothly in states that changed their official QR-code addresses.
Original PR description
In This PR:
- Several states have updated their NFC-e QR-code URLs, which caused errors when issuing invoices due to invalid or outdated links. This commit updates the 'nfceQrCode' parameter in Avalara requests ('calculate-tax' and 'submit-invoice-goods') to ensure the correct QR-code links are used.
task- 5115845
Forward-Port-Of: odoo/enterprise#95726This change greatly speeds up the process of changing a contract template on a pending job offer. It reduces unnecessary database work so the action completes in milliseconds instead of minutes on large databases, improving responsiveness for HR teams.
Original PR description
Description ----------- - Fix performance regressions due to breaking the prefetcher via `[0]` indexing of `hr.version` and batch `write`. - Evaluate only the current employees contracts in `_get_contract_versions` for an *onchange* context, else the `hr. version` for all employees are fetched and evaluated, leading to significant overhead downstream. - Add missing index for `_remove_work_entries` Benchmark --------- On a database in 19.0, with ~10k employees, ~30k versions and ~5M work-entries, the onchange triggered when changing the contract template on a pending offer for a new lambda employee took: | | Before | After | |-------------|--------|--------| | Query Count | 107k | 349 | | Time | 2.9min | ~300ms | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
When users prepare a document for signing, placeholder text for selection fields will now appear correctly. This makes the signing form clearer and helps signers understand what should be entered or selected.
Original PR description
To reproduce: ============= - upload a document to sign and add a selection field on it - set a placeholder for the selection field - open the document to sign -> the placeholder is not displayed Problem: ======== the placeholder is not displayed because there is no option holding the placeholder value. Solution: ========= Add an option at the beginning of the select options to hold the placeholder value. opw-5140676 Forward-Port-Of: odoo/enterprise#97887
This fix ensures that when a barcode is scanned in the product view, Odoo uses the complete barcode instead of only part of it. It prevents incorrect search results and makes barcode-based product lookup more reliable for users.
Original PR description
Issue ----- When scanning a barcode in the product view, the search is made using only part of the barcode. Steps to reproduce ----- - Open the product view - Scan a barcode (eg 1234567890) > The search might only contain 12345678, 123456 or actually the full barcode Cause ----- When scanning a barcode, we receive all of the barcode characters followed by newline. When we receive the newline, we select the first item in the dropdown. The problem is that the search input changed but it hasn't been reflected yet in the items (a rendering is scheduled but hasn't been applied to the DOM yet). ----- Ticket: opw-4874425 Forward-Port-Of: odoo/odoo#233245 Forward-Port-Of: odoo/odoo#232270
This update ensures that component lines removed in the subcontracting wizard are fully deleted, instead of staying behind as hidden records. It prevents confusing leftover inventory entries and keeps production and reporting data accurate.
Original PR description
Issue ----- Removing a line using the subcontracting wizard does not delete the line in DB, there is a "phantom" ML. Steps to reproduce ----- - Create a subcontracted product with 2 components - Add…
Issue ----- Removing a line using the subcontracting wizard does not delete the line in DB, there is a "phantom" ML. Steps to reproduce ----- - Create a subcontracted product with 2 components - Add one of each component in subcontractor's stock - Create a PO for the finished product and confirm it - Go to the production - Open the "Record components" wizard - Set quantity then remove the second line - Confirm production (don't update consumption) - Go to Inventory > Reporting > Moves History and remove the "Done" filter > There is a pending move in the report Cause ----- When saving the wizard's changes, we call a write on the production's `move_line_raw_ids` field to remove delete the line. The field is a simple compute, so we go through its' inverse method https://github.com/odoo/odoo/blob/be3a4283c383d187570f5a73f337030e6ae9d05c/addons/mrp_subcontracting/models/mrp_production.py#L34-L46 The problem is that we populate `line_by_product` using the values present in `move_line_raw_ids` from which we just removed the line. This means that when we do `move.move_line_ids = line_by_product.pop(move.product_id, self.env['stock.move.line'])` we replace the value of `move_line_ids` with only the remaining ones, which means we unlink the move line (*from the move*). Because the inverse field (`move_id` of the SML) is not set as `ondelete='cascade'`, the link is broken but the line remains in db. https://github.com/odoo/odoo/blob/f173c738b1adcf85a80eb641ad307b7cccf17294/odoo/fields.py#L4311-L4322 We cannot change the field to `ondelete='cascade'` as such a change would not be stable. Solution ----- Keep reference of the lines to be removed in order to delete them once `move_line_ids` has been updated. ----- Ticket: opw-4817397 Forward-Port-Of: odoo/odoo#233626 Forward-Port-Of: odoo/odoo#229310
The website loading progress bar now uses the brand primary color instead of black. This makes it easier to see in dark mode and keeps the interface more consistent with the rest of the website design.
Original PR description
This commits changes the website loader progress bar color, from black to `$primary`. This provides a better contrast in dark mode as well as better consistency. task-5170115 | Before | After | |--------|--------| | <img width="1920" height="1186" alt="image" src="https://github.com/user-attachments/assets/cd9525cf-b9d6-40dd-9ffb-ed0027020ab5" /> | <img width="1920" height="1172" alt="image" src="https://github.com/user-attachments/assets/3f7d9a4b-4a3e-4fbd-a1be-826c898466cd" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#232875
This change stops users from typing into or moving around decorative page elements like background shapes, filters, and parallax effects. It helps keep page layouts stable and avoids odd visual glitches when editing website content.
Original PR description
WIP
This update fixes an issue where removing a main product image could appear to succeed before the change was fully saved, causing test failures and unreliable behavior. It also simplifies how the test image is loaded, making the process more stable and less prone to delays.
Original PR description
Versions -------- 18.0+ Issue ----- The `test_website_sale_add_and_remove_main_product_image_no_variant` and `test_website_sale_remove_main_product_image_with_variant` tours fail because the main…
Versions -------- 18.0+ Issue ----- The `test_website_sale_add_and_remove_main_product_image_no_variant` and `test_website_sale_remove_main_product_image_with_variant` tours fail because the main product image is not removed as expected after the tour completes. Cause ----- Both tours assume that once the product `<img>` element is removed from the DOM, the action is fully completed. The tour then ends, and the remaining Python code verifies the result. However, this assumption can lead to issues. If the save request takes longer than expected, the Python code may execute prematurely and fail. Solution -------- Add a step at the end of both tours to wait for the `<img>` element to be fully saved and updated in the preview DOM. Additionally, during debugging, it was observed that using an alias URL (i.e., a redirect) to an `ir.attachment` could introduce further issues or slow down the test due to the server fetching the image with a remote call. To address this, this commit replaces the alias URL with a simple binary attachment. opw-5159593 runbot-163025 runbot-163615 Forward-Port-Of: odoo/odoo#233978
This update adjusts the order of steps in the website wishlist test so the wishlist count has time to refresh before the tour continues. It helps prevent random test failures and makes the automated checks more stable.
Original PR description
Modify the steps order to make sure the wishlist quanity has enough time to get updated runbot-229616 Forward-Port-Of: odoo/odoo#233998
Guests who have not been online for the past 12 hours will no longer receive notifications when a call starts. This reduces unnecessary alerts and helps prevent confusion for people who are no longer actively connected.
Original PR description
With this commit, guests who haven't been online in the last 12 hours will not be notified of a call starting. task-5136330 backport of https://github.com/odoo/odoo/pull/230337 Forward-Port-Of: odoo/odoo#233669 Forward-Port-Of: odoo/odoo#233221
This change keeps scrap orders consistent when the product is changed. If the new product does not use a BoM, the system now clears the BoM value instead of leaving an outdated one behind, preventing the scrap quantity from being set to zero by mistake.
Original PR description
Problem: When a user changes the product on a scrap order, the bom_id field does not get updated. If they update the product from a product that has BoM to a product that doesn’t have one, then the…
Problem: When a user changes the product on a scrap order, the bom_id field does not get updated. If they update the product from a product that has BoM to a product that doesn’t have one, then the bom_id field is hidden and remains set. This will cause the scrap quantity to be set to 0 when they validate the scrap. However, the product move actually happens for the correct quantity causing an inconsistency. Purpose: This will either set the bom_id field to False if the new product doesn’t have a valid BoM, or it will update it to the first available BoM. Steps to Reproduce on Runbot: 1. Create a scrap order for a product that has a kit type BoM and set the kit field. 2. Change the product to a product without a kit type BoM. 3. Validate the scrap order. 4. Observe the quantity field is set to 0, but there are product moves for the correct quantity. opw-5122880 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234050 Forward-Port-Of: odoo/odoo#231937
This change makes uploaded website videos compatible with content sanitization, so pages can still be edited later by users with restricted permissions. It prevents a situation where a video added by an admin could make the page appear uneditable for other users.
Original PR description
Steps to reproduce the current behaviour: - Update the DEMO user to be a website "restricted editor" and sales "admin" who cannot bypass HTML field sanitization. - As ADMIN, add a YouTube video to a…
Steps to reproduce the current behaviour: - Update the DEMO user to be a website "restricted editor" and sales "admin" who cannot bypass HTML field sanitization. - As ADMIN, add a YouTube video to a product page > Save. - As DEMO, try to update the content on the product page > You cannot (a dialog informs you that you cannot edit the content because an admin edited it previously). Explanation: Starting from [1], an HTML field can be flagged as `sanitize_overridable` which allowed users with the `base.group_sanitize_override` group to skip the HTML field sanitize process. If such users added some content that is not considered "sanitize friendly" (e.g. YouTube iframe), a restricted user won't be allowed to add content in the fields, since the sanitizer will remove the original content from the DOM. For this case, the code from [2] added an implementation to consider the field as none editable and warn the user once he tries to update it. Implementation: The goal of this commit it to fix the current limitation for video upload that currently prevents non admin users to edit a website record once an admin adds a video on it... The idea of the fix is the following: - We already have a technical fallback when uploading a video to save the iframe `src` to an attribute: `data-oe-expression`. - The public widget is now destroying the video iframes so they are never saved in the DOM. - A non-lazy code will build the iframes immediately on page load. - The public widget can always create the iframes if they are not already created (for compatibility). [1]: https://github.com/odoo/odoo/commit/cf844e34dd0ce4830eb99fd0fa5b6b9cb58c867c [2]: https://github.com/odoo/odoo/commit/cb80c15d3db49ede3c93171abcaa9064b88822c6 task-3757205 Forward-Port-Of: odoo/odoo#232871 Forward-Port-Of: odoo/odoo#175717
This update helps the system notice broken browser connections much sooner when the network is slow or unstable. As a result, users are less likely to experience long pauses where messages stop arriving without warning.
Original PR description
When a TCP connection is not closed cleanly, it can take minutes to detect a closed WebSocket connection. During this time, no messages are received. This can happen in slow or unstable network conditions. Browsers do not expose WebSocket ping/pong mechanisms. To detect dead connections quickly, periodic application level messages are sent if no messages were either sent or received within a minute. This approach ensures quicker detection compared to relying on the OS TCP timeout, which is typically set to a high value. X-original-commit: d043e12 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#234275
Fixed an issue where checkout could get stuck loading when external tax checks failed during Brazilian sales. Instead of freezing, the system now captures the problem and shows it in the next checkout step so customers can continue or correct the issue.
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 Forward-Port-Of: odoo/enterprise#96213 Forward-Port-Of: odoo/enterprise#95045
The mail system now checks only real emails when looking for repeated sender loops. This avoids incorrectly blocking a customer’s next email when other non-email messages from the same author had already increased the count.
Original PR description
When detecting loops with _detect_loop_sender if the count of these messages exceeds the LOOP_THRESHOLD, the next email from that user is blocked, even if the number of new emails alone hasn't yet crossed the threshold due to mail messages that are not email triggering the loop detection. This happens because it searches for messages in the mail.message model that share the same model name and author irrespective of the message type. To correct this, the function's search criteria must be modified to explicitly filter for messages where the message_type is set to 'email'. opw-5122962 Forward-Port-Of: odoo/odoo#232026
20 changes
Resolved issues and error corrections
Datetime fields now display the Arabic meridiem marker for afternoon and evening times when needed. This prevents 11 PM values from being shown as plain 11:00 and then being misread as 11 AM when edited again.
Original PR description
When the database language is set to Arabic, all datetime fields across the system incorrectly displayed PM (afternoon/evening) times without the Arabic meridiem marker (م), causing times to appear…
When the database language is set to Arabic, all datetime fields across the system incorrectly displayed PM (afternoon/evening) times without the Arabic meridiem marker (م), causing times to appear ambiguous and be parsed incorrectly as AM times when re-read from the input.
Issue:
------
- Switch to Arabic Language
- Enter 11:00 PM in any datetime field (attendance, calendar, etc.)
- System correctly stores it as 23:00 (hour 23 in 24-hour format)
- When displaying back to the user, the formatter uses shortTimeFormat which is configured as "hh:mm" (without the 'a' meridiem token)
- Display shows: "١١:٠٠" (11:00 with no م marker)
- When the field loses focus, parseDateTime tries to parse using format "hh:mm:ss a" (expects meridiem marker)
- Since no marker is present, Luxon defaults to AM
- Time gets changed from 23:00 (11 PM) to 11:00 (11 AM)
Root Cause:
-----------
The formatDateTime function uses different time formats depending on whether seconds should be displayed:
- When showSeconds = false: uses localization.shortTimeFormat ("hh:mm")
- When showSeconds = true: uses localization.dateTimeFormat (...hh:mm:ss a)
The shortTimeFormat is missing the 'a' token for meridiem marker, but the parser always expects it when timeFormat includes 'a'. This creates a mismatch between formatting and parsing.
Solution:
---------
Modified formatDateTime() to detect when shortTimeFormat uses 12-hour format (h/hh tokens) but is missing the meridiem marker ('a' token). In such cases, append ' a' to the format string before formatting.
This ensures 12-hour times include the meridiem marker which Luxon correctly outputs for each locale (م for PM in Arabic, PM in English), making times unambiguous and allowing them to be parsed correctly.
The fix only affects 12-hour formats missing the meridiem marker, and does not modify 24-hour formats (H/HH tokens), preserving existing behavior for formats that intentionally use 24-hour display.
opw-5137828This update fixes a failing rental test that depended on demo accounting and stock settings. It now runs correctly in clean environments, which helps keep automated testing reliable and prevents false failures during builds.
Original PR description
The test was failing in no-demo environments because it relied on accounting and stock configurations that were not present. When the test attempted to set property_valuation = 'real_time' on the product category, it triggered a ValidationError because the related stock accounts had not been properly set up for the test's transaction context. runbot-error-230417 Forward-Port-Of: odoo/enterprise#97935 Forward-Port-Of: odoo/enterprise#92292
This fix makes placeholder text visible again when users open a document to sign and a selection field has been configured. It improves clarity for signers and helps prevent confusion when completing documents.
Original PR description
To reproduce: ============= - upload a document to sign and add a selection field on it - set a placeholder for the selection field - open the document to sign -> the placeholder is not displayed Problem: ======== the placeholder is not displayed because there is no option holding the placeholder value. Solution: ========= Add an option at the beginning of the select options to hold the placeholder value. opw-5140676 Forward-Port-Of: odoo/enterprise#97887
This update prevents a stopped ringtone from starting again when someone presses the play/pause key on their headset or keyboard. It helps avoid unexpected sound after a call has already ended, improving the user experience and preventing confusion.
Original PR description
Before this commit, users can resume "stopped" ringtones by pressing the Media Play/Pause key of their keyboard/headphones, even after the call has ended. After this commit, stopping the ringtone clears the audio source, effectively preventing it from being resumed. Task-5222704 opw-5186087 Forward-Port-Of: odoo/enterprise#98660
This update makes the website shop tests more reliable when removing a product’s main image. It ensures the test waits until the image save is fully complete, preventing occasional false failures, and simplifies how test images are loaded to avoid slow redirects.
Original PR description
Versions -------- 18.0+ Issue ----- The `test_website_sale_add_and_remove_main_product_image_no_variant` and `test_website_sale_remove_main_product_image_with_variant` tours fail because the main…
Versions -------- 18.0+ Issue ----- The `test_website_sale_add_and_remove_main_product_image_no_variant` and `test_website_sale_remove_main_product_image_with_variant` tours fail because the main product image is not removed as expected after the tour completes. Cause ----- Both tours assume that once the product `<img>` element is removed from the DOM, the action is fully completed. The tour then ends, and the remaining Python code verifies the result. However, this assumption can lead to issues. If the save request takes longer than expected, the Python code may execute prematurely and fail. Solution -------- Add a step at the end of both tours to wait for the `<img>` element to be fully saved and updated in the preview DOM. Additionally, during debugging, it was observed that using an alias URL (i.e., a redirect) to an `ir.attachment` could introduce further issues or slow down the test due to the server fetching the image with a remote call. To address this, this commit replaces the alias URL with a simple binary attachment. opw-5159593 runbot-163025 runbot-163615 Forward-Port-Of: odoo/odoo#233978
This change ensures delivery fees on subscription invoices are not reduced when a prorated invoice is created. It matters because shipping charges should remain a fixed cost, even when the rest of the subscription amount is adjusted for the billing period.
Original PR description
Version - 18.0 Steps to reproduce: 1. Create a subscription with delivery product. 2. Select align to calendar in the recurring plan 2. Add shipping method by assigning a delivery product with recurring_invoice. 3. Create an invoice with prorated Issue: - Delivery products are considered service-type products and their price was prorated in invoice. Cause: - The proration logic treated delivery lines like normal recurring service products, instead of keeping their fixed charge. Solution: - Exclude delivery products from proration by setting their period ratio to 1. Co-authored-by: Darshan Patel dvpa@odoo.com Co-authored-by: Federico Braidi brfe@odoo.com task-4662188 Forward-Port-Of: odoo/enterprise#98622 Forward-Port-Of: odoo/enterprise#91133
The website loading progress bar now uses the primary brand color instead of black. This makes it easier to see in dark mode and creates a more consistent look across the website.
Original PR description
This commits changes the website loader progress bar color, from black to `$primary`. This provides a better contrast in dark mode as well as better consistency. task-5170115 | Before | After | |--------|--------| | <img width="1920" height="1186" alt="image" src="https://github.com/user-attachments/assets/cd9525cf-b9d6-40dd-9ffb-ed0027020ab5" /> | <img width="1920" height="1172" alt="image" src="https://github.com/user-attachments/assets/3f7d9a4b-4a3e-4fbd-a1be-826c898466cd" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#232875
This update makes the wishlist test flow more reliable by adjusting the order of steps so the wishlist count has time to refresh. It also ensures the wishlist starts empty before the tour continues, reducing random test failures without changing customer-facing features.
Original PR description
Modify the steps order to make sure the wishlist quanity has enough time to get updated runbot-229616 Forward-Port-Of: odoo/odoo#233998
The website now uses the standard redirect utility when sending users to a URL after a rental search action. This makes navigation more reliable and reduces the chance of redirect issues on rental-related pages.
Original PR description
Community PR: https://github.com/odoo/odoo/pull/233842 Forward-Port-Of: odoo/enterprise#98686 Forward-Port-Of: odoo/enterprise#98492
Customers can no longer cancel a self-order once it has been sent to the kitchen display. This avoids mismatches between the backend and the kitchen screen and ensures cancellations follow the proper in-store process.
Original PR description
Currently, it is possible to cancel orders that have been sent to the kitchen display. However when doing so, the kitchen displayd does not receive any information about the cancellation. Steps to reproduce: ------------------- - Modify restaurant and enable self ordering - Open self an place an order (not paid but sent to kitchen) - Go back to "My orders" and cancel it > Order is cancelled in backend but not in the kitchen display Why the fix: ------------ When an order is sent to the kitchen the only way to cancel it should be by going to the register. Therefore now, if an order is present on the kitchen display we will not show the cancel button. opw-5030223 Community: https://github.com/odoo/odoo/pull/229039 Forward-Port-Of: odoo/enterprise#95770
This update fixes how customers are sent to the correct page after certain webshop actions, such as cart updates, product options, wishlist actions, and reorder flows. It helps ensure users consistently land on the intended URL instead of seeing broken or unexpected navigation.
Original PR description
Enterprise PR: https://github.com/odoo/enterprise/pull/98492 Forward-Port-Of: odoo/odoo#234164 Forward-Port-Of: odoo/odoo#233842
Customers can no longer cancel a self-order once it has been sent to the kitchen display. This avoids situations where the order is removed in the system but the kitchen is never informed, helping staff keep orders consistent and reducing confusion.
Original PR description
Currently, it is possible to cancel orders that have been sent to the kitchen display. However when doing so, the kitchen displayd does not receive any information about the cancellation. Steps to reproduce: ------------------- - Modify restaurant and enable self ordering - Open self an place an order (not paid but sent to kitchen) - Go back to "My orders" and cancel it > Order is cancelled in backend but not in the kitchen display Why the fix: ------------ When an order is sent to the kitchen the only way to cancel it should be by going to the register. Therefore now, if an order is present on the kitchen display we will not show the cancel button. opw-5030223 Enterprise: https://github.com/odoo/enterprise/pull/95770 Forward-Port-Of: odoo/odoo#229039
When a user changes the product on a scrap order, the related Bill of Materials is now refreshed automatically. This prevents the scrap quantity from being reset incorrectly and avoids mismatches between what users see and what is actually processed.
Original PR description
Problem: When a user changes the product on a scrap order, the bom_id field does not get updated. If they update the product from a product that has BoM to a product that doesn’t have one, then the…
Problem: When a user changes the product on a scrap order, the bom_id field does not get updated. If they update the product from a product that has BoM to a product that doesn’t have one, then the bom_id field is hidden and remains set. This will cause the scrap quantity to be set to 0 when they validate the scrap. However, the product move actually happens for the correct quantity causing an inconsistency. Purpose: This will either set the bom_id field to False if the new product doesn’t have a valid BoM, or it will update it to the first available BoM. Steps to Reproduce on Runbot: 1. Create a scrap order for a product that has a kit type BoM and set the kit field. 2. Change the product to a product without a kit type BoM. 3. Validate the scrap order. 4. Observe the quantity field is set to 0, but there are product moves for the correct quantity. opw-5122880 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234050 Forward-Port-Of: odoo/odoo#231937
This fix prevents the system from trying to clean reservations for kit products in situations where that can trigger an error. As a result, users can open and manage inventory quantities normally without being blocked by this issue.
Original PR description
Since this commit: 766ec99 We try to clean reservations because, for some reason, there could be a discrepancy between the sum of “stock.move.line” and the quantity/reserved quantity on…
Since this commit: 766ec99 We try to clean reservations because, for some reason, there could be a discrepancy between the sum of “stock.move.line” and the quantity/reserved quantity on “stock.quant”. However, there are cases where a user creates a storable product, updates its quantity, and then uses it in a “stock.move.line”, confirms it, and later changes the product type to a kit. So, when trying to clean the reservations for these “stock.move.line”, a user error occurs because the system attempts to create a quant for a kit-type product: https://github.com/odoo/odoo/blob/c07778bbce4311c142bd8e2ce3013998d4f126ae/addons/mrp/models/stock_quant.py#L6-L11 As a result, each time users try to access the quant list, clean_reservation is triggered, causing a user error that prevents them from modifying the quantity of any quant. Solution: For kits, we can skip cleaning their quant to avoid unnecessary errors. This is a manual forward-port of #200595 opw-4625002 opw-4624008 opw-4621175 opw-4625465 opw-4621504 opw-4623523 opw-4621508 opw-4623329 opw-4629386 opw-5179369
The chat bubbles on mobile now stay in place when tapped instead of briefly moving down. This makes the chat experience smoother and avoids a distracting visual jump in Discuss and on website pages.
Original PR description
**Description of the issue/feature this PR addresses:** when clicking on chat bubble in mobile, the chat bubbles were moving down temporarily **Current behavior before PR:** when clicking on chat…
**Description of the issue/feature this PR addresses:** when clicking on chat bubble in mobile, the chat bubbles were moving down temporarily **Current behavior before PR:** when clicking on chat bubble in mobile, the chat bubbles were moving down temporarily. this happens because in some contexts, the chat hub bubbles are lift up, like in discuss app and at bottom of website page. This was done with a `transform: translateY()` but when the button was being clicked the chat bubble temporarily resets its unlifted position, as if no `transform: translateY()` was in effect. **Desired behavior after PR is merged:** This fixes the issue by using `bottom` CSS style rule. Chat hub bubbles part has a bottom value, the lift up is now designed to combine with the static bottom value, thus bubbles part stay at the desired position even when being clicked. Backport of #225757 task-[4914438](https://www.odoo.com/odoo/project/1519/tasks/4914438) Before  After  --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change ensures customers receive the expected email when an order status update comes back from Gelato. It helps keep buyers informed automatically and reduces missed notifications in the order process.
Original PR description
Fix not sending the email to customer, when order status update was received from Gelato. opw-4962878 Forward-Port-Of: odoo/odoo#233587
This fixes a stock issue where items with a lot or serial number could be incorrectly balanced against an untracked quantity instead of the correct lot. As a result, inventory remained inconsistent after barcode deliveries and later receipts; the correction keeps stock levels tied to the proper lot, which improves traceability and prevents stock mismatches.
Original PR description
Uecase to reproduce: - Create a quant with a product and 10 lot A - Create a delivery order - Open barcode - In barcode, deliver the product with lot C Current behavior: You have 2 quants: - 10 lot A - -1 without lot Expected behavior: - 10 lot A - -1 lot C It happens because the code try to balance negative quant for lot/sn in a stack of quants without lot/sn for the product. However in this case the barcode create a quant without quantity and without lot. In this case the system wants to update it due to an incorrect condition. It's an issue since in later receit with the correct lot. The quant will never be balanced and it will result with - -1 without - 1 lot C 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#231853
We fixed an issue where checkout could get stuck loading if an external tax check failed during order summary updates. Instead of freezing, the problem is now captured and surfaced so the customer can continue and see a clear message in the next checkout 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 Forward-Port-Of: odoo/enterprise#96213 Forward-Port-Of: odoo/enterprise#95045
This change fixes an error in hardware driver certificate checks when comparing certificate expiration dates. It ensures the system uses matching date formats, preventing crashes during certificate validation and keeping connected hardware services working reliably.
Original PR description
Before this commit, datetime.now() was compared to cert.not_valid_after_utc, leading to an error because we compare offset-naive and offset-aware datetimes After this commit, we set an offset-aware datetime.now() if we use not_valid_after_utc Issue introduced in #234005 opw-5237595 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Code cleanup and technical improvements
The way Odoo prepares values for product revaluation was moved into a separate method. This does not change the core behavior, but it makes the process easier for custom addons to adapt without modifying standard code.
Original PR description
This allows to make it hookable by custom addons This was split from https://github.com/odoo/odoo/pull/160527 cc @pfertyk @sys-odoo @Whenrow --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230265 Forward-Port-Of: odoo/odoo#228204
37 changes
New functionality added to Odoo
This change adds a new module to correct and separate Peppol-related tax field handling in invoice export files. It helps Odoo generate UBL documents that better match the official standard, reducing issues with tax allowance charges and related codes.
Original PR description
The new module contains fixes for bugs that were pushed to 19.0 in the `account_peppol_advanced_fields` module. Task: 4963157
Enhancements to existing features
Pakistan payroll tax rules have been updated with the new 2026 bracket values. This helps ensure employee payslips and payroll calculations stay accurate and aligned with the latest local tax requirements.
Original PR description
Tax brackets for pakistan localization has been updated to include the new values for 2026. Forward-Port-Of: odoo/enterprise#98345
This change adds a shared set of helper methods for accounting tests, making it easier to create invoices, sales orders, reversals, and other common test records. It helps establish a single standard that future accounting test work can reuse, improving consistency and reducing duplicated test setup code.
Original PR description
This commit adds bunch of helper methods on AccountTestInvoicingCommon to make it easier to do generic accounting test actions, such as: - creating invoice - creating sale order - reversing invoice - skipping test if module isn't installed - creating down payment invoice ... and many more. We're aware that there are thousands of different helpers for creating invoice out there in different localizations. This commit serves as the first necessary step to create one standard that can be extended across all other test helpers. This is a simplified version of the merged commit in master. We are not refactoring/rewriting any other test to use these new helpers. Our goal is just to make it available for everyone to start using this helper on their accounting-related tests. task-4891206 Forward-Port-Of: odoo/odoo#234036 Forward-Port-Of: odoo/odoo#233724
This update refreshes the QR-code links sent to Avalara when issuing Brazil NFC-e invoices. It helps prevent invoice errors caused by outdated or invalid links, ensuring tax calculations and invoice submission continue to work correctly.
Original PR description
In This PR:
- Several states have updated their NFC-e QR-code URLs, which caused errors when issuing invoices due to invalid or outdated links. This commit updates the 'nfceQrCode' parameter in Avalara requests ('calculate-tax' and 'submit-invoice-goods') to ensure the correct QR-code links are used.
task- 5115845
Forward-Port-Of: odoo/enterprise#95726Messages that include a rating are now treated as non-empty in portal views. This prevents rated feedback from being overlooked and improves the accuracy of customer interactions shown to users.
Original PR description
*: portal, portal_rating, rating, website_slides task-5016995 Forward-Port-Of: odoo/odoo#234059 Forward-Port-Of: odoo/odoo#223515
This update keeps Raspberry Pi and IoT device setup working with newer Python and related system libraries. It also fixes where Wi‑Fi settings are saved, helping ensure network configuration is applied correctly on recent device images.
Original PR description
To ensure compatibility with python 3.13+, we updated the method to generate the rpi's password to avoid using the removed `crypt` lib.
In addition, we ensure that Wi-Fi configuration is saved to the right path, nmcli saving path changed in latest versions. (see: https://github.com/raspberrypi/trixie-feedback/issues/3).
Finally, we ensure compatibility with old `cryptography` versions, by using `not_valid_after_utc` or `not_valid_after` depending on on image version.
Forward-Port-Of: odoo/odoo#234014
Forward-Port-Of: odoo/odoo#233423This update prepares the POS and blackbox integration for a more reliable communication flow by introducing a new action to the connected device. It is the first step toward a queue-based mechanism that will help transactions between the POS and blackbox run more smoothly in the next update.
Original PR description
This commit is the first of two which will introduce a queue mechanism in the communication between the POS and the blackbox. This commit adds an action to the iot and invites users to update their iot to be prepared for the next commit which will effectively add the queue mechanism and use the new action. Second part: https://github.com/odoo/enterprise/pull/90747 Forward-Port-Of: odoo/enterprise#96904 Forward-Port-Of: odoo/enterprise#96639
The Iyzico payment provider now supports webhooks, allowing Odoo to receive payment updates automatically from Iyzico. This improves payment status tracking and makes the integration more reliable for customers and the business.
Original PR description
This commit adds webhook support for the Iyzico payment provider. task-5067754
This update improves how user mentions are detected and validated while composing messages. It also moves part of the message preparation work into a dedicated component, paving the way for a more accurate “what you see is what you get” experience in the composer.
Original PR description
This commit introduces a new MentionPlugin to handle user mentions in the mail composer. The MentionPlugin is responsible for detecting and validating mentions. It listens to selection changes and processes mention elements accordingly. This commit also moves part of the prepareMessageBody logic to the MentionPlugin, so that we can finally get rid of the prepareMessageBody in the future and get what you see is what you get in the composer. task-5137057 backport - https://github.com/odoo/odoo/pull/232538 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update adds the "Wage on signature" field to the contract version list and the "Company Car" field to the employee list. It makes these values visible at a glance, helping users review important HR information more quickly without opening each record.
Original PR description
*: hr_contract_salary,l10n_be_hr_payroll_fleet Added the "Wage on signature" field to versions list view, and "Company Car" to employee list view. task-5231169
Attachment content is now prepared in a way that helps AI find and understand information more accurately. PDFs are indexed more directly, and tabular files are reformatted into a clearer text structure so retrieval results are more relevant.
Original PR description
### Summary
This improvement refines how attachments are indexed to enhance retrieval quality and RAG comprehension.
### Key Changes
- **PDF Indexation:**
- Moved the PDF attachment indexation logic from the previous implementation to the main `_index` method in the `attachment_indexation` module [COM PR].
- PDFs are now indexed directly and their content is stored into `index_content` to be used directly.
- **Tabular File Indexation:**
- In alignment with the community PR that indexes tabular files as CSV text, this update introduces a new helper method:
- `_process_csv_text`: Converts CSV content into a **header–dictionary-style text**, improving semantic understanding for RAG.
---
**Task:** 5045336This update adds extra IGIC tax data for the Canary Islands and splits purchase taxes into goods and services. It helps Odoo apply the correct tax mappings based on the type of purchase, improving compliance and reducing manual adjustments.
Original PR description
We have splitted purchase taxes in goods and services because there are different mappings according to the scope. It has a similar functionality with spanish mainland taxes @jco-odoo There are doubts with the fiscal position `fp_nacional_canary_ns` as it is applied automatically to spanish non canarian partners but it should be similar to non-EU partners IMO. However, I think that the opinion fo some canary people would be nice to clarify it @Christian-RB --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230964 Forward-Port-Of: odoo/odoo#228667
Receipts are now included by default in the invoice and bill views, alongside regular customer invoices and vendor bills. This makes it easier for users to see all related accounting documents without adjusting filters manually.
Original PR description
This commit Shows by default receipts along side invoices/bills from customer invoices or vendor bills pages. task-5187350 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change greatly speeds up the contract template update process when preparing a new job offer. It reduces unnecessary data processing and database work, which cuts waiting time from minutes to a fraction of a second in large databases.
Original PR description
Description ----------- - Fix performance regressions due to breaking the prefetcher via `[0]` indexing of `hr.version` and batch `write`. - Evaluate only the current employees contracts in `_get_contract_versions` for an *onchange* context, else the `hr. version` for all employees are fetched and evaluated, leading to significant overhead downstream. - Add missing index for `_remove_work_entries` Benchmark --------- On a database in 19.0, with ~10k employees, ~30k versions and ~5M work-entries, the onchange triggered when changing the contract template on a pending offer for a new lambda employee took: | | Before | After | |-------------|--------|--------| | Query Count | 107k | 349 | | Time | 2.9min | ~300ms | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234202
The deferred date fields now use a range-style date picker, making it simpler to enter matching start and end dates. If the end date is left blank, it will automatically match the start date, which avoids errors and supports accrual entries without unnecessary warnings.
Original PR description
* use the widget `daterange` on `deferred_start_date` and `deferred_end_date` * auto fill `deferred_end_date` when it is empty to `deferred_start_date` to avoid double encoding of the same value, and avoid raising an error * remove the warning `has_abnormal_deferred_dates` when the date is the same, this can be used to do an accrual entry. task-5207293
Resolved issues and error corrections
This change makes replenishment tests reliable when demo data is used in different time zones. It prevents the system from creating an extra purchase order line by ensuring date checks are compared consistently, so existing orders are reused as expected.
Original PR description
The `test_replenish` test was failing with demo data because replenishment created an extra Purchase Order line. The `_run_buy` search domain included `date_planned_mps` with an equality check on a datetime stored in `UTC`. With demo data loaded in a non-UTC timezone (e.g. Europe/Brussels), the forecast date was converted to `2025-07-31 22:00:00 UTC`, which did not match the existing PO at `2025-08-01 00:00:00 UTC`. As a result, no PO was found and a duplicate was created. Changes: Set the test user timezone to `UTC` so that `date_planned_mps` comparisons are stable when using demo data. This ensures replenishment reuses the existing PO instead of creating a duplicate. [runbot-230425](https://runbot.odoo.com/odoo/error/230425)
This fix corrects how available stock is calculated when a customer orders both individual units and a package of the same product. Previously, the system could count too much quantity as reserved, causing an item to appear out of stock even when enough was available for pickup.
Original PR description
Steps to reproduce: 1. Add a packaging to the storable product (ex. pack of 6) 2. Uncheck continue selling 3. Update qty of the product in the wh to 20 4. Add 4 units to the cart 5. Add 1 pack 6. Choose pickup in store and go to the checkout The product is not in stock even though there is enough quantity.
This change prevents an error that could occur when users add a project update in projects using budget features. It ensures the update form opens correctly instead of failing during display, improving reliability for project teams.
Original PR description
Currently an issue is generated when the project user tries to add a project update. Steps to produce an error: - Install the 'project_account_budget' module with demo data. - Log in with the demo…
Currently an issue is generated when the project user tries to add a project update.
Steps to produce an error:
- Install the 'project_account_budget' module with demo data.
- Log in with the demo user
- Go to Project and open the dashboard of the Home Construction project
- Click new »> error occurs
Error
```
QWebError
Error while rendering the template:
KeyError: 'revenues'
Template: project.project_update_default_description
```
This issue occurs due to:
- The reference commit [1] enhances the project update form description by enabling the display of profitability even without the sale timesheet.
- With commit [1], code was added to set the `profitability_values` to an `empty dictionary ({})` and `show_profitability` to `False` (see [2]) , since the demo user does not belong to the `project.group_project_manager` group (see [3]).
- In the `project_account_budget` module, the value of `show_profitability` is updated and set to True because the total_budget_amount is present in the project (see [4]).
- In the template `project_update_default_description` rendering, the `profitability` is accessed when `show_profitability` is `True`. However, since `profitability` is an empty dictionary, attempting to access the key will result in an error (see [4]).
This commit fixes the above issue by preventing the recalculation of `show_profitability`, as it is already set based on whether `profitability` data is available or not.
[1]: https://github.com/odoo/odoo/commit/e81af984aabe61defa0932b7890ab373fe3c8e2a
[2]: https://github.com/odoo/odoo/blob/385d8473952eeaa9dcc7740bacfc2c9cbdc2d1e2/addons/project/models/project_update.py#L114-L126
[3]: https://github.com/odoo/odoo/blob/385d8473952eeaa9dcc7740bacfc2c9cbdc2d1e2/addons/project/models/project_project.py#L1111-L1112
[4]: https://github.com/odoo/odoo/blob/385d8473952eeaa9dcc7740bacfc2c9cbdc2d1e2/addons/project/views/project_update_templates.xml#L26-L31
Sentry-6915109069,6981931420This update fixes how Odoo handles missing skill-matching data for job applicants. When no matching score is available, the system now falls back to 0 instead of 100, keeping results consistent with earlier versions and avoiding misleadingly high match scores.
Original PR description
- The [PR] added a fallback value for matching score as `100`, whereas in the versions `saas-18.4` and before... we had the fallback value as `0` [source]. - Therefore, to maintain consistency this commit changes the fallback value for `matching_score` to 0. - Also added a testcase for the same. [PR]: https://github.com/odoo/odoo/pull/230323 [source]: https://github.com/odoo/odoo/blob/d13ea53ef64d0281387ad0daf66c90163dded63b/addons/hr_recruitment_skills/models/hr_applicant.py#L47-L51 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change prevents stopped call ringtones from being restarted with the Play/Pause key after a call has ended. It improves call handling behavior and avoids confusing audio playback for users.
Original PR description
Before this commit, users can resume "stopped" ringtones by pressing the Media Play/Pause key of their keyboard/headphones, even after the call has ended. After this commit, stopping the ringtone clears the audio source, effectively preventing it from being resumed. Task-5222704 opw-5186087 Forward-Port-Of: odoo/enterprise#98660
PDF and spreadsheet attachments are now indexed in a way that keeps text and table structure more readable. This improves the quality of search and AI features that rely on attachment content, such as semantic retrieval and RAG.
Original PR description
### Problem 1. **PDF documents** often produced fragmented or misaligned text, especially in multi-column or tightly formatted layouts. 2. **Tabular files** (`.xlsx`, `.ods`) lost their row–column relationships during extraction, making the indexed text less meaningful for semantic processing. ### Changes #### PDF Attachments - Introduced configurable **`LAParams`** parameters in `pdfminer` to fine-tune text extraction for complex or multi-column layouts. #### Tabular Attachments - Updated **XLSX** and **ODS** indexers to output data in **CSV-like format**, preserving **row–column context** for better AI readability. - Uses **`openpyxl`** (now part of Odoo requirements) to efficiently extract and format spreadsheet data in xlsx files. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr task-id-5045336
This fix ensures the views needed to settle invoices are loaded correctly for users who are allowed to perform the action. As a result, employees without administrator access can now settle invoices as expected, preventing a workflow blockage at the point of payment closing.
Original PR description
Before this commit, a user without the "Role / Administrator" group could not settle invoices because the required views were not loaded. After this commit, the necessary views are properly loaded, allowing all authorized users to settle invoices as expected. opw-5138892
This update keeps the scrap order’s BoM information in sync when the product is changed. It prevents cases where the displayed scrap quantity becomes zero while the actual stock movement still uses the correct amount, avoiding inconsistent results during validation.
Original PR description
Problem: When a user changes the product on a scrap order, the bom_id field does not get updated. If they update the product from a product that has BoM to a product that doesn’t have one, then the…
Problem: When a user changes the product on a scrap order, the bom_id field does not get updated. If they update the product from a product that has BoM to a product that doesn’t have one, then the bom_id field is hidden and remains set. This will cause the scrap quantity to be set to 0 when they validate the scrap. However, the product move actually happens for the correct quantity causing an inconsistency. Purpose: This will either set the bom_id field to False if the new product doesn’t have a valid BoM, or it will update it to the first available BoM. Steps to Reproduce on Runbot: 1. Create a scrap order for a product that has a kit type BoM and set the kit field. 2. Change the product to a product without a kit type BoM. 3. Validate the scrap order. 4. Observe the quantity field is set to 0, but there are product moves for the correct quantity. opw-5122880 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234050 Forward-Port-Of: odoo/odoo#231937
This update corrects the badge display in list views so colored badges now appear as expected. It improves visual consistency and helps users recognize statuses more easily at a glance.
Original PR description
Purpose ======= Fix the rotting variant of the badge selection field in list views which should properly support the color field option. Specification ============= The 'ListBadgeSelectionRotting' widget was inheriting from the 'BadgeSelectionField' which doesn't support any color in badges. It should inherit from the list variant of the badge selection field called 'ListBadgeSelectionField' which supports the color field option. Task-5186979 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a broken warehouse test so it no longer appears to pass when it should fail. It helps ensure future changes in stock handling are validated properly and reduces the risk of hidden issues reaching users.
Original PR description
Due to an issue in the runbot, the test associated with the PR: odoo#229958 passed despite underlying conflicts and the PR was merged. This PR addresses and resolves those issues to ensure the test functions correctly. Impacted versions: - 18.0 - saas-18.2 - saas-18.3 - saas-18.4 19.0 and master are addressed in odoo#230685 to replace `procurement.group` with `stock.rule` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230687
This change corrects a spelling mistake in the Attendance module, replacing “Beetween” with “Between.” It improves the clarity and professionalism of the interface for users reviewing overtime rules.
Original PR description
This pull request fixes a typo in the hr_attendance module where the word `Beetween` was displayed instead of `Between`. Before Fix: <img width="1920" height="927" alt="before_fix" src="https://github.com/user-attachments/assets/ffe5e7c2-1d87-47fd-ac82-2b7d80f36448" /> After Fix: <img width="1920" height="927" alt="after_fix" src="https://github.com/user-attachments/assets/961f1f9f-9318-4ab0-8c61-56b8e87b9924" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a warning in the Hong Kong payroll localization so the related process can run cleanly again. It does not change business rules; it simply ensures the system uses the proper access check and avoids the build error.
Original PR description
Use `check_access` instead build-error-233453
The company switcher now correctly displays nested companies a user can access, even when an intermediate company in the hierarchy is not available. This prevents missing entries in the company list and makes it easier for users to switch to the right company context.
Original PR description
### Issue: Given a specific configuration, the `SwitchCompanyMenu` will not display all the companies a user can access. Suppose we have a company hierarchy with the following: `Company 1 > Company 2…
### Issue: Given a specific configuration, the `SwitchCompanyMenu` will not display all the companies a user can access. Suppose we have a company hierarchy with the following: `Company 1 > Company 2 > Company 3` (where 2 is a branch of 1, and 3 is a branch of 2). If a user has access to C1 and C3, but not C2, the menu selector will only display C1, rather than a hierarchy of all 3 companies with C2 disabled. This menu has been improved between versions, but the logic behind how we determine which companies to display remains consistent. We loop over each root company from `companyService.allowedCompaniesWithAncestors`, add it, and then add its children. Depending on whether the child company is accessible, it will be disabled (but still displayed) in the hierarchy list. `companyService` pulls its company information from the `session['user_companies']` dict that is created from `session_info`. For each of the `allowed_companies`, we build the `child_ids` from the intersection of each `user.company_id.child_ids` and `user.company_ids`. So we only add the child if it itself is an allowed company, which C2 would not be. C1 is now considered a root company with no children in our loop, so C2 is skipped. C2 isn't a root company either, so it will never be seen, and therefore neither will C3. ### Solution: A similar case was addressed in #138942, where given the same company hierarchy as above, the user instead has access to C2 and C3, but not C1. This PR adjusted how we build the `child_ids` for `disallowed_ancestor_companies` (C1 in this case), properly setting the children for us to loop through. We can use this same logic for the `child_ids` of `allowed_companies`, ensuring we can properly loop through the disallowed children of allowed companies. Additionally, we need to adapt the `CompanySelector` component, which previously grabbed all children even if they were disallowed. opw-4880477 Forward-Port-Of: odoo/odoo#229829 Forward-Port-Of: odoo/odoo#217001
Fixed an issue where checkout could hang indefinitely when external tax calculation failed for Brazilian sales. Instead of freezing, the system now captures the error and continues to show a user-friendly message at the next checkout step, helping customers understand and correct the problem.
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 Forward-Port-Of: odoo/enterprise#96213 Forward-Port-Of: odoo/enterprise#95045
This change corrects permission handling in attendance settings and overtime calculations. It ensures managers can view the ruleset as intended and that overtime lines correctly identify whether a user is the manager, preventing access issues and incorrect behavior for attendance officers.
Original PR description
Problem ---------- Ruleset can't be read if the user is not an attendance manager. The ruleset_id on employee have the group `group_hr_manager`but it doesn't imply attendance manager. Wrong computation of `is_manager` on overtime line if the user has only attendance officer rights and the employee with overtime has this user as attendance manager. Solution ---------- Make the ruleset readonly for hr manager. Fix the is_manager compute task-5180810
The product catalog now shows the right price when discounts are enabled, even if the product was already added to the order. This fixes a mismatch that could make catalog prices appear inconsistent with the order line and improves accuracy for sales users.
Original PR description
Catalog prices do not consider discounts when displayed separately from the unit price on the order line (if any for a given product). It was fixed for the /update_order_line_info route with 5d1837e47c20f04458472658c4f8ea71284fb6ca, but the issue still remained when fetching the original catalog data on opening, through the /order_lines_info route. This only happened when the product was already added to the order, because in this case we avoid recomputing the pricelist price and use the existing sale order line price. This commit makes sure that the sale order line discount field is correctly considered in that case, and also adds tests to cover the catalog more extensively. Fixes #232219 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233098
When an employee does not have a bank account linked, the payslip now displays a clear payment line instead of leaving it blank or showing a placeholder. This makes payslips easier to read and avoids confusion for payroll users and employees.
Original PR description
### Before: - While printing payslip previously if an employee do not have any bank linked we were not printing anything,. ### After: - If no bank account present we will use: Amount to be paid to [employee_name]: [amount] task- 5101235
This fix prevents a permission error when a non-admin user clicks a configurable product in Point of Sale, especially in branch-company setups. The product configurator now opens normally, so staff can continue serving customers without interruption.
Original PR description
**Issue:** In POS, clicking on a tax-free, inventory-tracked, configurable product as a non-admin user can throw an Access Rights error when trying to access it on a branch company's POS config. **Steps to reproduce:** - Configure a branching company on a parent company - Create a new POS restaurant on the child company - Create a configurable product that has no taxes associated with it and add it to a POS category so that it can be chosen from the POS screen - On a non-admin POS user, try to click that product 🐛 **Before this commit:** The user will get an Access Rights error. **After this commit:** The configurator dialog will load successfully. opw-5145176 Forward-Port-Of: odoo/odoo#231343
Self-order preparation printers were missing a needed IoT Box identifier, which could prevent printing through supported connection methods. This update loads the full device information so printing works reliably in self-order, matching the regular point of sale behavior.
Original PR description
Loading IoT preparation printers in self order was not providing the ID of the IoT Box record, required to print using both webrtc/longpolling/websocket. This commit fixes this issue by loading the whole device record, same as we do to load preparation printers in the regular pos.
This fix prevents an error that could appear when manufacturing products tracked by lot and producing more than the requested quantity. It ensures the lot information is kept correctly on the extra output lines, so the production can be completed without a missing lot warning.
Original PR description
For 'By Lots' manufactured products, producing more than requested gives the error "You need to supply a Lot/Serial Number for product...". This occurs from within _post_inventory operations: - update the finished move line with only the producing quantity - create a new finished move line with the exceeding quantity & lot - raise the warning under action_done because one move line has no lot By inverting the updates ( setting the lot before setting the quantity ) we ensure the lot is correctly propagated. task: 5232544 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
This fix prevents an error when checking multiple payslips if some of them have no problems to report. As a result, payroll processing is more reliable and won’t stop unexpectedly in these cases.
Original PR description
When there are multiple payslip on which we call get_error_message, some may have no issues. In this case, it raises a traceback as issues is False. Introduced in https://github.com/odoo/enterprise/pull/94748
This update prevents chat bubbles from shifting down briefly when they are tapped on mobile devices. It keeps the chat widget in the correct position so the interface feels steadier and more polished.
Original PR description
**Description of the issue/feature this PR addresses:** when clicking on chat bubble in mobile, the chat bubbles were moving down temporarily **Current behavior before PR:** when clicking on chat…
**Description of the issue/feature this PR addresses:** when clicking on chat bubble in mobile, the chat bubbles were moving down temporarily **Current behavior before PR:** when clicking on chat bubble in mobile, the chat bubbles were moving down temporarily. this happens because in some contexts, the chat hub bubbles are lift up, like in discuss app and at bottom of website page. This was done with a `transform: translateY()` but when the button was being clicked the chat bubble temporarily resets its unlifted position, as if no `transform: translateY()` was in effect. **Desired behavior after PR is merged:** This fixes the issue by using `bottom` CSS style rule. Chat hub bubbles part has a bottom value, the lift up is now designed to combine with the static bottom value, thus bubbles part stay at the desired position even when being clicked. Backport of #225757 task-[4914438](https://www.odoo.com/odoo/project/1519/tasks/4914438) Before  After  --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234269
14 changes
New functionality added to Odoo
This update lets users find journal items by entering a balance amount in search. It makes it easier to locate specific accounting entries faster, especially when reviewing or reconciling records.
Original PR description
Description of the issue/feature this PR addresses: adding a search field by balance of journal item Current behavior before PR: can't search by balance Desired behavior after PR is merged: typing a number can result in a search by balance --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Enhancements to existing features
Users can now quickly search journal items by entering an amount, making it easier to find the right accounting lines without manual filtering. This improves day-to-day efficiency for accounting teams working with large numbers of entries.
Original PR description
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
Resolved issues and error corrections
This update prevents products added through a sales combo from being incorrectly merged into a separate product selection. As a result, the system now creates the correct sales lines and keeps combo extra prices from affecting separately added items.
Original PR description
Steps: - create a product with attributes of create_variant=never - set variant selection to order grid entry - add this product as a combo choice and set extra_price>1 - In sale order form first add the new combo product with the previously created product - add the new product with same selection of attribute values as combo Issue: - The separately added product should create a new line, but since it was added as a part of the combo, the product's price is summed with extra price and added to the combo itself Cause: - the grid field that is responsible for adding product using product matrix does not filter combo lines Fix: - added filter for combo lines when matrix opens and saves opw-5164789 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix removes Chinese Yuan (CNY) from the currencies PayPal can use in Odoo when the PayPal account is not eligible for it. As a result, customers will no longer reach a payment flow that fails or behaves unexpectedly for CNY invoices, making checkout clearer and more reliable.
Original PR description
## Versions 18.0+ ## Issue No payment is possible with PayPal for invoices expressed in Chinese currency. ## Steps to reproduce **`account` app required** - Enable "CNY" currency via `Invoicing /…
## Versions
18.0+
## Issue
No payment is possible with PayPal for invoices expressed in Chinese currency.
## Steps to reproduce
**`account` app required**
- Enable "CNY" currency via `Invoicing / Configuration / Accounting / Currencies`;
- Install, setup and publish PayPal payment provider;
- Move to the Invoice app:
- Create a new invoice in "CNY" currency for any customer with at least 1 product;
- Confirm and click on the preview button:
- Click on the "Pay now" button then "Pay" button of the wizard.
## Cause
"CNY" currency is only supported for Chinese accounts and for transactions occurring in China. PayPal says:
> Please note that Chinese Renminbi (CNY) is supported as a payment currency (buyer currency) or settlement currency (holding currency) only for in-country PayPal accounts. If the settlement account is based outside of China, PayPal will convert the funds into the account’s primary currency using the applicable currency conversion rate, which includes a spread or fee.
opw-5071893This change prevents expense report PDFs from showing the title twice when using the DIN5008 German document format. It does this by providing the correct report title for DIN5008 headers, resulting in cleaner and more professional printed expense reports.
Original PR description
Issue: Expense title is duplicated when printing an expense report for localizations using the DIN5008 standard. Steps to reproduce: - Install German localization - Create a new expense report - Print the expense report PDF -> Title is duplicated Cause: DIN5008 reports tries to load a value `din5008_document_title` in their header and fallbacks to report's name With this commit, we add a bridge module to extend the expense sheet report and set the `din5008_document_title` to `Expenses Report`. opw-4314414
This update corrects the test data used for passkey authentication demos by setting the admin user’s time zone. It helps prevent test failures in automated checks and keeps the demo authentication flow reliable.
Original PR description
We need to define timezone of the admin user for no demo tests, similar to how it is done in [saas-18.3](https://github.com/odoo/odoo/blob/9900375bc0bac2754150fd8cd6a1e45ecad8da83/addons/auth_passkey/tests/test_passkey_demo.py#L456): [Runbot error - 229872](https://runbot.odoo.com/odoo/error/229872) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When a mail template is duplicated, its attachments are now copied too instead of being shared between templates. This prevents edits to one template from unintentionally affecting others and helps avoid access issues in future setups with custom rules.
Original PR description
Copying tmeplates should copy their attachments. Otherwise they are
shared, which means
* wrong res_id: ACL check on attachments relies on a specific
template, as res_model / res_id is used in access check;
* propagated changes: changing one attachment changes it on all
duplicated templates;
If custom rules on templates are implemented, this means notably
ACL issues when accessing attachments. It is not the case in standard
Odoo 17 as everyone can read templates but this notably changes in
future versions of Odoo.
While being there, also fix 'default' usage in copy override. User
given values should not be erased by default computation of name.
Task-5128863
Forward-Port-Of: odoo/odoo#232877This change removes a recently added bot-detection filter from website blog and slides. The previous check could be bypassed by crawlers, so it was allowing unwanted indexing of many tag combinations and could overload tag pages; the team is reverting it while a more reliable solution is developed.
Original PR description
This reverts [1] because the `is_a_bot` check is not reliable. Many crawlers spoof user agents or ignore robots rules, so they still index every tag combination and overload tag clouds. We revert while we look for a better protection. [1]: https://github.com/odoo/odoo/commit/4b1c3bfa83af2b1851db62df5aca4d5777a3d88c
A problem that could break quotation previews after customizing a sales report in Studio has been fixed. The preview now works correctly even when a field is added to the report layout, avoiding an error for users viewing quotations in the portal.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Edit the `sale.report_saleorder` report using `web_studio`. 2. Add the `amount_untaxed` field next to the "Untaxed Amount" subtitle. 3. Create or navigate to…
Versions -------- - 17.0+ Steps ----- 1. Edit the `sale.report_saleorder` report using `web_studio`. 2. Add the `amount_untaxed` field next to the "Untaxed Amount" subtitle. 3. Create or navigate to a quotation and click on the "Preview" action. Issue ----- A traceback occurs during the rendering of the `sale.sale_order_portal_template` template. ``` Error while render the template KeyError: 'doc' Template: sale.document_tax_totals Path: /t/t/tr/td[1]/span Node: <span t-field="doc.amount_untaxed"/> The error occurred while rendering the template sale.document_tax_totals and evaluating the following expression: <span t-field="doc.amount_untaxed"/> ``` Cause ----- In the `sale.report_saleorder_document` template, `doc` is used as the variable name for the current sale order. Consequently, the studio edit uses this variable name to modify the `sale.document_tax_totals` template called within `sale.report_saleorder_document`. However, the `sale.sale_order_portal_template` template, used for the portal preview, also calls `sale.document_tax_totals` but uses `sale_order` as the variable name for the current order. Solution -------- Add an alias `doc` for `sale_order` during the rendering of `sale.document_tax_totals` when called in the portal report preview. opw-5136553
This change fixes a mislabeled menu entry in the Recruitment app so the displayed name matches the intended wording. It improves clarity for users navigating the app, with no expected impact on business processes.
Original PR description
used wrong name in this forward-port: 4e847de16a71cb03cb21e05c6d535f6abfae0287 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
This fix ensures employees’ extra hours from attendance are correctly shown in the Time Off dashboard. It matters because managers and employees now see the full available balance, including hours earned through attendance, without missing data.
Original PR description
### Steps to reproduce: - Install Attendance and Time off apps - Create some attendance with extra hours for the employee - Go to the employee's time off dashboard - Notice Extra Hours allocation is not shown ### Cause: When we are getting the allocation data we check for the leave types that require allocation https://github.com/odoo/odoo/blob/5f6d2afa8c09fe72c01d056ebef01214567a4a99/addons/hr_holidays/models/hr_leave_type.py#L473 And then when checking the types that doesn't require allocation we are looping on the res that we got from the super which already excluded those types https://github.com/odoo/odoo/blob/5f6d2afa8c09fe72c01d056ebef01214567a4a99/addons/hr_holidays_attendance/models/hr_leave_type.py#L41-L43 ### Fix: We loop over the self leave types to make sure we are getting all of the employee's leave data whether the type requires allocation or not. opw-5042325
This fix ensures tax closing entries are linked to the right tax report, so generating a closing from a generic report or a national variant no longer creates confusing duplicate draft moves. It also makes sure that when several national variants exist, they all point back to the generic tax report for consistent behavior.
Original PR description
To reproduce the issue, on a Belgian company: 1) From the Generic Tax Report, or any of its two grouped variants (Account>Tax or Tax>Account), click on the closing entry button. It generates a draft…
To reproduce the issue, on a Belgian company: 1) From the Generic Tax Report, or any of its two grouped variants (Account>Tax or Tax>Account), click on the closing entry button. It generates a draft move. Log a note on that move. 2) Open the national tax report of Belgium, for the same period as in 1). Click on the closing entry button again. ==> The draft move generated in 2) is NOT the same as the one generated in 1) (you can check that from the note logged in 1)). This is because tax_closing_report_id is too naively set on the account.move, to always match the report on which the button was clicked. This commit fixes that, ensuring we set the right report in the closing field. Something will be done in the migration script to 19.0 to set the report properly before creating the returns. The problem also occurs when multiple national variants are available : in this case each of those reports creates a distinct closing entry, with the exact same informations, giving the illusion we're doing per-report closings. In such cases, we associate the closing move to the Generic tax Report. opw-4858689
This fix corrects the minimum rental period calculation so it no longer assumes every month has 30 days. Customers can now select valid rental dates in shorter months like February without the system rejecting them incorrectly.
Original PR description
Issue: Currently minimum rental duration uses a hardcoded 30 days. This cause issue for non-30 days month e.g. Feb. which is 28 days. To reproduce: 1- Install `website_sale_renting` 2- From Setting, set `Minimum Rental Duration` to 1 month. 3- Create a rental product and from website, choose the date: - 01/02/2026 - 28/02/2026 4- This fails. The earliest end date it accepts is 03/03/2026. Cause: This is due to hardcoded 30 days: https://github.com/odoo/enterprise/blob/7ffb9f3cb0d818cf3616d6972df424bf0ca251a4/website_sale_renting/static/src/js/renting_mixin.js#L7-L12 https://github.com/odoo/enterprise/blob/7ffb9f3cb0d818cf3616d6972df424bf0ca251a4/website_sale_renting/static/src/js/renting_mixin.js#L47-L53 We can use luxon plus method instead. ```diff + const minEndDate = startDate.plus(Object.fromEntries([[unit, duration]])); ``` In all usages of `msecPerUnit` we can do the same. Also we can keep remove `msecPerUnit` from master. opw-5094534
This fix applies an earlier performance improvement to the spreadsheet version history view, so it no longer makes an unnecessary currency-related server request. It helps the version history action load more efficiently and reduces avoidable delays for users working with spreadsheets.
Original PR description
The perfomance commit added in https://github.com/odoo/odoo/pull/151725 did not account for the version history action that does not inherit from `AbstractSpreadsheetAction`. this missing value trickled down to a bug only detectable in the VersionHistory action and which is addressed in https://github.com/odoo/odoo/pull/232985 This commit adds the same performance to VersionHistory action. Task-5187293 Forward-Port-Of: odoo/enterprise#98038
14 changes
Enhancements to existing features
This update makes an error message more explicit when the system rejects files from an uninstalled module. It should help support teams and users understand the cause faster and troubleshoot without digging into the code.
Original PR description
While working on a support ticket, I was faced with this exception handling: https://github.com/odoo/odoo/blob/49061347c181b1a451435bc363bb9508db8b6fab/odoo/addons/base/models/ir_asset.py#L344-L346 It might be nitpicky, but given the if condition, the exception error text could be more explicit about the fact that it's raised because the files in question being from an uninstalled addon/module. This might fast track troubleshooting without having to dive into the source code to understand why the error is being raised. There is always the possibility that I might be missing some context or other scenarios where this error could be raised. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
When a deferred start date is entered without an end date, the system now automatically uses the same date for both values. This prevents invalid accounting periods and makes the setup flow smoother for users in stable versions.
Original PR description
Previously, specifying a Deferred Start Date without an End Date would result in an invalid period. This commit updates the logic to default the End Date to the value of the Start Date if the End Date is not provided. This streamlines the flow in stable versions until a more comprehensive solution is implemented in master. Task-5207293
This fix ensures sales orders are marked as invoiced when no further stock operations are expected, even if the full ordered quantity was not delivered. It helps keep order and invoicing status accurate, reducing confusion for sales and accounting teams.
Original PR description
If no other operations are expected on the picking, even if the full quantity wasn't delivered, the order should be marked as invoiced. task-4607401 Fixes #144485 Partial revert of #115871 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an automated test so it can run correctly even when demo data is not installed. It ensures the required accounting setup is available, preventing the test from failing when creating a purchase invoice.
Original PR description
The test `test_dropship_return_backorders_bill_on_order` failed when running without demo data because no chart of accounts was installed, so no Purchase journal existed. As a result, `purchase_order.action_create_invoice()` raised: UserError: No journal could be found in company ... for any of those types: purchase This change inherits from `AccountTestInvoicingCommon` to have the necessary charts. [runbot-231285](https://runbot.odoo.com/odoo/error/231285) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents DHL shipping requests from failing when prices or weights are calculated with very small decimal differences. It improves reliability for delivery validation so shipments can be processed without avoidable errors.
Original PR description
Multiple rounding issues could cause DHL validation errors. Example with product price: - Create a storable product - Create a quotation with quantity 7, price 11.43 - Validate the SO - Go to delivery, use DHL carrier, validate - DHL traceback: 11.429999999999998 not multiple of 0.001 Example with product weight: - Create 3 products, each 0.1 kg - Create a SO with these products - Validate the SO - Go to delivery, use DHL carrier, validate - DHL traceback: 0.30000000000000004 not multiple of 0.001 See official DHL API documentation: https://developer.dhl.com/api-reference/dhl-express-mydhl-api and check the POST /shipments data schema opw-5000193
This change fixes an issue where customer details could be updated in two separate steps, causing inconsistent Peppol verification data and validation errors. It helps ensure partner information is saved consistently, reducing failed verifications for affected users.
Original PR description
In some cases, when doing two consequent writes instead of one batch, the ORM will trigger the dependencies needlessly, and it can end up to discrepancies like: EAS=0208, endpoint=BE... which lead to a validation error. opw-5228670 opw-5225590 opw-5228716 opw-5229057 opw-5232276
This fix improves the export dialog’s search so users can find fields by their visible names, even when those names include parent paths like “Order Lines/Product.” It prevents missed results caused by a mismatch in the search logic, while still keeping technical field IDs usable in debug mode.
Original PR description
The export dialog reverses field.string to prioritize field names over parent paths
in fuzzy search scoring. However, the search pattern was not reversed, causing
mismatches when searching with display names like "Order Lines/Product".
Before: pattern "Order Lines/Product" searched in reversed string "Product/Order Lines"
→ character order mismatch → no results
After: both pattern and string are reversed → proper matching
This fix ensures searching by display names (e.g., "Order Lines/Product") works
as expected, while technical IDs (e.g., "order_line/product_id") continue to work
in debug mode.
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix prevents products that have been archived from being included in point of sale combos. It helps avoid accidentally selling items that the business has marked as inactive.
Original PR description
Before this commit, when a product used in a combo was archived, it was still possible to sell it through the combo in the PoS. After this commit, archived products are excluded from combos, preventing them from being sold inadvertently. opw-5180301 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents the delivery date on customer invoices from being unintentionally reset when the invoice is confirmed. It matters because it preserves the correct delivery information for billing and accounting, avoiding confusion and manual corrections.
Original PR description
Versions
--------
- 17.0+
Steps
-----
1. Enable anglo-saxon accounting;
2. have a product category with automated AVCO;
3. assign category to a deliverable product;
4. set product to invoice on delivery;
5. add product to a sales order;
6. confirm order & delivery;
7. create invoice;
8. change the delivery on the invoice;
7. confirm the invoice.
Issue
-----
The delivery date gets reset.
Cause
-----
Commit 818cf04f05767 added `delivery_date` as a permanently protected field when modifying moves or move lines, protecting the records on `write`. With anglo-saxon accounting however, new move lines are created when confirming an invoice, which in turn recalculate the delivery date, as `_get_protected_vals` isn't used for their move on `create`.
Solution
--------
Add `self.env['account.move'].protecting(_get_protected_vals({}, moves))` when creating new lines for a move, to avoid recomputing fields that should always be protected.
opw-4965036Fixed an issue where available stock was not refreshed in Barcode operations after changing the product or source location. This ensures users see the correct quantities when creating or editing internal transfers, reducing confusion and mistakes during warehouse work.
Original PR description
Issue: In this bug, stock quants are not being updated when product_id or location_id is updated. To reproduce: 1- Create a db with demo database and barcode installed 2- Enable storage locations 3- Open barcode -> operations -> Internal transfers -> New 4- Add a product -> e.g. Drawer which there are quants in demo 5- As you see quants are not shown Cause and Fix: This is a partial backport of: #55917 `_compute_product_stock_quant_ids` should depend on `product_id` and `parent_location_id` to be recomputed when product or source location is updated. opw-5065624
Point of Sale now correctly recognizes product packaging when scanned with a GS1 barcode and adds the related quantity automatically. This fixes a checkout issue that could previously require manual quantity adjustment, making barcode scanning faster and more reliable.
Original PR description
Before this commit, scanning a GS1 barcode for a product packaging did not add the quantity. opw-5003035 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update prevents Shiprocket from failing when taxes do not include India GST tags. It also makes the related test more reliable by explicitly using a 15% tax rate, so results are consistent across different company settings.
Original PR description
Some other test adds a fiscal position with tax mapping. This creates 2 problems
1. The new taxes have a tag, which means we evaluate the right hand of
https://github.com/odoo/enterprise/blob/8d3fe30c627eada1186c15480876fb2e8f7ddb59/delivery_shiprocket/models/shiprocket_request.py#L239
However, since l10n_in is not installed,
`tax.env.ref(f"l10n_in.tax_tag_{gst}gst", False)`
does not return anything (False is not a fallback)
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/api.py#L588
So we end up looking for `None` in `tax_tag_ids`, which leads us to compare the `_name` properties, see
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/models.py#L6545-L6558
2. The test added in 4d5df93 was assuming the default company 15% tax, which was not always true
Solution
-----
1. Provide a fallback for the `ref` lookup
2. Force a 15% tax in the test
-----
runbot-232692This change fixes an issue where users without Employees access could not select an employee in certain forms, especially on mobile. The system now correctly shows the available public employee information instead of incorrectly returning no results.
Original PR description
**Steps to reproduce** - With Studio, create a many2one field in relation to the Employee model. - Have a user with no "Employees" rights. - With this user and in mobile view, click on the field to…
**Steps to reproduce** - With Studio, create a many2one field in relation to the Employee model. - Have a user with no "Employees" rights. - With this user and in mobile view, click on the field to select an employee. -> No records found. Note: the many2one_avatar_employee widget used in HR apps avoid this problem. **Cause** Issue since https://github.com/odoo/odoo/commit/e962860c6f0d8ec9e50bb376e1faab5c7bc69374 The `web_search_read` on the private employee model returns no records when an `image_*` or `avatar_*` field is part of the requested fields. This is because we try to fetch these fields https://github.com/odoo/odoo/blob/188a3fe45fb41463ff86d1fa5e930ab43fb70d0e/addons/hr/models/hr_employee.py#L240 but they are not stored on the public employee model, and will not be put in cache. When performing a read after that, these fields are missing from cache. We try to fetch them from the db https://github.com/odoo/odoo/blob/e962860c6f0d8ec9e50bb376e1faab5c7bc69374/odoo/models.py#L3185 but this fetch is again done using the public employee. This results in missing values and is interpreted as an access error, no data is returned in `web_search_read`. **Solution** Read the problematic fields to make them present in cache when the cache of the public employee is copied to the one of the private employee. opw-4297115
Quality checks created per quantity now use the correct company for the related stock operation. This prevents confirmation errors in multi-company setups when users switch between companies.
Original PR description
When creating quality checks per quantity, a multi-company error occurs if the active company differs from the one defined on the control point. Steps to reproduce: - Create a Quality Control Point for Company B and Product Table for the receipt operation with a per-quantity control. - Create a receipt in Company B for this product but leave it in draft. - Switch to Company A and try to confirm → error. Root cause: The company_id was not set when creating the quality check, causing it to default to `env.company` (A) instead of the stock move line’s company (B). opw-86993