Daily updates from Odoo
Wednesday, November 12, 2025
26 changes · saas-18.4
Enhancements to existing features
This change adds a new exact-match selector option for Hoot tests, making test definitions easier to read and write. It also updates existing tests to use this clearer syntax, improving developer productivity without changing business behavior.
Original PR description
This commit adds the ':text()' pseudo-class to the list of supported pseudo-classes in Hoot selectors. Its purpose is the same as ':contains()', with the specificity of being an *exact* match instead of a *partial* one. It effectively replaces ':contains(/^<expression>$/)' by ':text(<expression>)', improving the readability and making the developer experience a bit nicer. Enterprise: https://github.com/odoo/enterprise/pull/98772 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#235107 Forward-Port-Of: odoo/odoo#234331
The test suite now uses a newer text-matching method in places where it behaves more predictably than the previous approach. This helps keep automated checks more stable and easier to maintain, without changing product behavior for users.
Original PR description
This commit replaces all found occurrences where ':contains' (with an exact match regular expression) could be replaced by ':text'. Community: https://github.com/odoo/odoo/pull/234331 Forward-Port-Of: odoo/enterprise#99183 Forward-Port-Of: odoo/enterprise#98772
The POS no longer checks for blackbox driver updates during session opening. If the drivers are outdated, users will still be warned later when they try to use a blackbox feature, which keeps startup smoother without losing the warning.
Original PR description
When introducing the blackbox queue service, we added a check at the opening of the POS to ensure that the blackbox drivers were up to date. This check is done at the start of session opening. It is now not necessary anymore, if the drivers are not up to date, an error will also be shown to the user when they try to use a blackbox functionality. Forward-Port-Of: odoo/enterprise#99014
Resolved issues and error corrections
This fixes an access issue that prevented some Recruitment administrators from sending referral campaigns when they did not have Employee access. The change ensures the right users can complete this common recruitment action smoothly.
Original PR description
STEP TO REPRODUCE:
------------------
1- Give to Marc Demo the right : Recruitment / Administrator (be sure he doesn't have any right on Employees)
2- Log as Marc Demo
3- Go to Recruitment
4- Click on the three dots in kanban card
5- Click on Referral Campaign
6- Click on Send
You will have an access error
This user (with these groups) should be able to send a referral campaign
task-5082344
Forward-Port-Of: odoo/enterprise#98773
Forward-Port-Of: odoo/enterprise#96746The upload button in accounting dashboards could be accidentally dragged out of place. This update locks the button in position so the interface stays stable and easier to use.
Original PR description
Issue: - In the dashboard, the upload button (purchase journal and others) could be dragged. - This caused unintended movement of the upload UI element. Fix: - Added `draggable=false` to the upload button element. - Ensures the button remains fixed and cannot be dragged around. TaskID-5114617 Forward-Port-Of: odoo/odoo#235086 Forward-Port-Of: odoo/odoo#229013
Updated a purchase-related test so it accepts the error type now returned by PostgreSQL 18. This keeps automated test runs stable after a database behavior change, without affecting customer-facing purchase features.
Original PR description
Apparently in pg18 a standard-compliance fix (postgres/postgres@086c84b23d99c2ad268f97508cd840efc1fdfd79) has led to `RESTRICT_VIOLATION` being emitted in cases which formerly emitted…
Apparently in pg18 a standard-compliance
fix (postgres/postgres@086c84b23d99c2ad268f97508cd840efc1fdfd79) has led to `RESTRICT_VIOLATION` being emitted in cases which formerly emitted `FOREIGN_KEY_VIOLATION`. One such case is specifically being tested for by `test_purchase_order_line_without_uom`, leading to this test failing systematically when running pg18:
psycopg2.errors.RestrictViolation: update or delete on table "uom_uom" violates RESTRICT setting of foreign key constraint "purchase_order_line_product_uom_id_fkey" on table "purchase_order_line"
DETAIL: Key (id)=(29) is referenced from table "purchase_order_line".
Update the test to use the more generic `IntegrityError` as it's probably more than sufficient for our purposes. Technically we could pass a tuple of `(ForeignKeyViolation, RestrictViolation)` but it doesn't really seem necessary. And it would require fixing the `_raisesContext` override as currently it is very much *not* compatible with that.
Forward-Port-Of: odoo/odoo#235119A test in the HR module was trying to access employee fields that are not always available on an employee record, which caused a build failure. The test now checks whether each field can actually be accessed before using it, preventing this crash and keeping automated builds stable.
Original PR description
This test had a bug: `self.env['hr.employee']._fields.keys()` may contain fields that do not exist in an `hr.employee` record. Now, employee fields that cannot be accessed are filtered out using `hasattr()`. To avoid further crashes. Runbot build error: https://runbot.odoo.com/odoo/runbot.build.error/233942 Bug has been introduced by task-5103739 task-5254322 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change fixes flaky website builder tests related to editing images. It ensures the required image assets load before the tests continue, so results are consistent and failures no longer happen randomly.
Original PR description
The goal of this commit is to fix the indeterminate tests related to image editing in the website builder. Problem: ===== Some tests related to image editing on the website fail in an indeterminate…
The goal of this commit is to fix the indeterminate tests related to image editing in the website builder. Problem: ===== Some tests related to image editing on the website fail in an indeterminate manner. This test failure is related to the sidebar's async. When selecting an image, the Image options need to fetch certain data (the original image, etc.). The “html_editor.assets_image_cropper” bundle is also loaded. This loading time can exceed 200 ms, causing the test to fail unpredictably. Solution: ====== 1.Preload the “html_editor.assets_image_cropper” bundle and store it in the cache. 2. Use `waitSidebarUpdated` when selecting an image. `waitSidebarUpdated`` will wait until all the data is loaded and the sidebar is updated. This solution is not optimal, but it will make all the tests deterministic. The best solution: ========= We should mock or preload all the data needed for the tests. This change requires adapting the current production code to make it easily patchable to mock, for example, “.text()” on a response to an image fetch. Error: https://runbot.odoo.com/odoo/error/232956 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When a pivot table with date-based columns is inserted into a spreadsheet, it now keeps the same sort order as in the web view. This fixes cases where the spreadsheet version could appear unsorted because date values were not being translated into the expected display format.
Original PR description
If on the web pivot view we create a pivot with a date/dateTime field in the columns, and sort on one of these columns, the resulting pivot when inserted in a spreadsheet isn't sorted. This was because we didn't normalize the date values in the pivot `sortedColumn`, and we had UTC timestamps `2023-01-01 00:00:00` instead of normalized values `01/2023`. Task: [3575465](https://www.odoo.com/web#id=3575465&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form) Forward-Port-Of: odoo/enterprise#96508
This update prevents spreadsheet crashes when freezing or sharing sheets that use boolean global filters. It makes exporting to Excel more reliable by correctly handling empty filter values.
Original PR description
The method `getFilterDisplayValue` would not handled `undefined` values for boolean global filters, causing crashes when exporting to Excel. Task: [5188932](https://www.odoo.com/web#id=5188932&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form) 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#232784
This change fixes Swiss ISO20022 payment files so they no longer mix incompatible XML formats and get rejected by some banks. The previous behavior is now only enabled when explicitly requested, which helps companies keep file generation compatible with their bank’s requirements.
Original PR description
[REV] account_iso20022: Wrong XML generated for Switzerland This reverts commit https://github.com/odoo/enterprise/commit/a0e981171808d4e475249431424955ab2223f5da. This commit was introduced after…
[REV] account_iso20022: Wrong XML generated for Switzerland This reverts commit https://github.com/odoo/enterprise/commit/a0e981171808d4e475249431424955ab2223f5da. This commit was introduced after this fix https://github.com/odoo/enterprise/commit/c160b2ead711797ca7362649971038cc245c5611. Though that original fix was correct, it had some unwanted side-effects: due to the payment method being forced on some payments in order to use SEPA, the sepa_pain_version field was used to generate the corresponding XML nodes, most of the time keeping its default value of pain.001.001.09. For Swiss banks supporting pain.001.001.09 (which becomes mandatory in November 2026), it was not a problem, and everything worked fine. This was the case of the customer for whom the fix was made (ticket 4535542). For the ones still not supporting it, and expecting pain.001.001.03, the bank refused the file, since the it contained unsupported nodes, like BICFI, or a subnode to ReqdExctnDt. The commit we revert here tried to patch the symptoms without really understanding the cause of the issue, by not forcing the payment method everywhere. It breaks again the case of the original ticket (because ScvLvl is not passed to "SEPA" on EUR payments), and essentially makes no sense. We revert it in favor of a better fix. ticket-4535542 ======================= [FIX] account_iso20022: Swiss variant: introduce config parameter to force SEPA nodes in the file https://github.com/odoo/enterprise/commit/c160b2ead711797ca7362649971038cc245c5611 made it so we now force SEPA payments into Swiss ISO20022 files when they're made in EUR to an IBAN account. Though all in all correct, this fix forgot to consider the fact that the SEPA nodes would be generated using the sepa_pain_version field, with defaults to pain.001.001.09 version of the ISO standard. As it is today, the Swiss file is still generated using pain.001.001.03 in Odoo (some task will change that soon, since the support for that old version will be dropped in November 2026). Having such pain.001.001.09 nodes in the file causes it to be rejected by a lot of Swiss banks, because they don't support that version yet, or simply because of the file mixing both versions of the standard. Since no one had asked us to enforce SEPA nodes within the file before recently, we make the choice to keep the fix behavior only when a config parameter is explicitly set to enable it. In all other cases, the former behavior is restored. We also now display the PAIN version field in the journal's form view when this config parameter is set, to give more control on the format of the generated file. ticket-4535542 Forward-Port-Of: odoo/enterprise#99005 Forward-Port-Of: odoo/enterprise#98918
Live chat visitors on mobile devices will no longer have the chat input automatically zoom in when they tap it. This keeps the send button visible and makes it easier to type and send messages without having to zoom back out manually.
Original PR description
Before this commit, when using livechat for visitors on mobile devices, click on input would zoom on input of about 115%. This zoom would hide send button at the very end of composer input, and would…
Before this commit, when using livechat for visitors on mobile devices, click on input would zoom on input of about 115%. This zoom would hide send button at the very end of composer input, and would force users to pinch-to-unzoom, making the UX quite poor. This problem happens because mobile devices have an auto-zoom feature that is triggered when font-size is below 16px. The discuss UI is designed with 14px font size (web client font size), and since 14px < 16px, it zooms on input focus to about 115%. This commit fixes the issue by using a font-size of 16px specifically for livechat visitor on mobile devices, so that this doesn't auto-zoom. Note that this problem doesn't happen on the web client even though this uses a font-size of 14px because it specifically disable the autozoom feature: https://github.com/odoo/odoo/blob/17.0/addons/web/views/webclient_templates.xml#L250 This solution is not practical for livechat, for which it has to work on any external website. opw-5229076 Before <img width="199" height="431" alt="after" src="https://github.com/user-attachments/assets/cc2f8e04-bde7-4eeb-84d5-b2efa2763490" /> After <img width="199" height="431" alt="before" src="https://github.com/user-attachments/assets/6c6679fc-9c16-40e7-ab6f-21540d20d59d" /> Forward-Port-Of: odoo/odoo#235182 Forward-Port-Of: odoo/odoo#234967
The website builder’s selection dropdown now correctly displays all available options when users change an existing choice. This fixes a bug where only four options were shown, helping users make updates without confusion or extra steps.
Original PR description
With the initial [website builder refactor], only 4 options appeared in the `many2x` dropdown when user try to re-select. This commit fixes the issue so the dropdown now fetches all required options through passing domain in rpc call instead of filtering after rpc call this makes sure we only fetch required data by avoiding already selected ids. Steps to Reproduce: 1. Open the website builder. 2. Drop any snippet onto the page. 3. Set the visibility option to conditionally. 4. In the UTM medium dropdown, select any social media option. 5. Try changing the selection again. 6. Only 4 options are shown. Expected: Dropdown should always display 5 options. [website builder refactor]: https://github.com/odoo/odoo/commit/9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2
This change makes input fields inside image captions use a transparent background instead of a dark gray one. It improves the visual consistency of captions and makes the editor look cleaner for users.
Original PR description
### Purpose of this PR: - Set the default background of inputs inside `<figcaption>` to transparent. This prevents them from appearing dark gray (rgb(59,59,59)) in caption. task-5122745 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents a table placed inside another table from growing beyond the space available in its parent cell when resized. As a result, nested tables stay usable and editable instead of becoming partially hidden or inaccessible.
Original PR description
**Current behavior before PR:** - When a table was created inside another table, resizing the inner table could cause it to overflow its parent cell, making it uneditable. **Desired behavior after PR is merged:** - The inner table no longer overflows its parent cell when resized, ensuring it remains editable. task-5216916 Forward-Port-Of: odoo/odoo#233554
This change fixes an issue in the mobile editor where using a formatting button like bold could incorrectly switch the toolbar to the image tools. The toolbar now stays in the correct mode and clearly highlights the selected formatting option, making editing on mobile more reliable.
Original PR description
**Current behavior before PR:** In mobile view, when applying the bold format using the toolbar button, the normal toolbar is incorrectly replaced by image toolbar. This occurs because `getFilteredTargetedNodes` returns an empty array, and as a result, the `isApplied` method evaluates to true since Array.every on an empty array returns true. **Desired behavior after PR:** This PR ensures that the toolbar remains in its normal state when a format is applied via the toolbar button. The corresponding format button (e.g., bold) is correctly highlighted. task-5123317 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234467 Forward-Port-Of: odoo/odoo#229454
This fix brings back the save button and the related trusted-order behavior in Point of Sale. It restores the intended workflow so trusted terminals can continue handling orders correctly, preventing missing functionality for affected users.
Original PR description
The button save and all the logic about trusted orders were removed. This commit puts it back. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229335 Forward-Port-Of: odoo/odoo#200567
This update corrects how job listings are counted and shown to visitors based on their location, even when they are not logged in. It also fixes an issue where duplicate location results could lead to incorrect counts being displayed, improving the accuracy of job search and redirection behavior.
Original PR description
This commit fixes 2 bugs: When you are not logged in and geolocalized, we don't redirect the visitor to the right country because the visitor cannot read hr.job, so the count will always be 0. Now we use sudo to have the count whether you are logged in or not. Another bug is in compute_filter_selection_counters: in case you provide a key_getter that is not the same as the grouping_field, when we count, we only keep the last count in case of duplicates. Eg, if you group by address_id and count the address_id.country_id, you will get the count of hr.job open in the last office you iterate over. Forward-Port-Of: odoo/odoo#234713
This update prevents an unexpected scrollbar from appearing in the website editor when hidden text is used inside certain content blocks. It improves the editing experience in Chrome, Edge, and Safari by keeping the page layout stable and avoiding a distracting visual issue.
Original PR description
This is a known issue [1] in bootstrap, which displays an unexpected scrollbar when we have a visually-hidden text in the table. The issue occurs in Chrome, Edge and Safari, but does not in Firefox. **Steps to see the issue:** - Open website and start editing - Drop a table of content - Drop inside of the ToC a donation snippet - Click on the donation amounts form => A scrollbar appears. The visually-hidden spans are present since [2], but the problem couldn't be seen until commit [3] removed the `overflow: hidden` style. [1]: https://github.com/twbs/bootstrap/issues/41554 [2]: https://github.com/odoo/odoo/commit/faafb913a0af5c4bfa7d207e09bbea0d97125aed [3]: https://github.com/odoo/odoo/commit/10156c10b09dc502a40253d64e2505e817a520bf task-5169275
This change prevents an access error that could appear when a purchase order uses an unrestricted analytic account shared across companies. It ensures users only see budget lines they are allowed to access, avoiding interruptions when entering purchase orders.
Original PR description
Steps to reproduce: - Create an analytic account [ACCOUNT] not restricted to any company - Create an analytical distribution model applying [ACCOUNT] to [PRODUCT] not restricted to any company - Create a budget in company [COMP A] using analytic account [ACCOUNT] - Create a budget in company [COMP B] using analytic account [ACCOUNT] - In company [COMP B], create a purchase order, add [PRODUCT] to a line Issue: Access Error is raised Analysis: Because we search with sudo company rules are bypassed and the system assign both budget lines to the order line (budget_line_ids). When we access the field, the system try to access the budget line of the other company, causing the error. As solution we revert https://github.com/odoo-dev/enterprise/commit/4941c1928c9a2bcb38af3cadf023f904c9fd9be0 removing the `sudo` on the search and we explicitly check if the user has read access on the budget analytic model opw-5056712 Forward-Port-Of: odoo/enterprise#98573
This change stops event ticket products from being changed into a rental setup, which could break the online registration and payment flow. It helps ensure attendees can always complete booking and payment for event tickets without errors.
Original PR description
Steps ----- 1. Have `sale_renting` but not `sale_stock_renting` installed; 2. create an event with a ticket; 3. make the ticket's product rentable; 4. change ticket's product type to Goods; 5. publish the event to website; 6. register for the event via website; 7. go to payment. Issue ----- > AttributeError: 'bool' object has no attribute 'tzinfo' Cause ----- By making it a rental product, it creates a rental order, but as registering for an event via website doesn't have any way to add rental dates, rental lines cannot be processed & rendered as expected. Solution -------- Prevent users from changing the `service_tracking` away from `'event'` by adding an `api.constrains` to `product.product` on `service_tracking` and `event_ticket_ids`. opw-5207045 Forward-Port-Of: odoo/odoo#234705
This fix restores automatic cost updates on sale order lines after an order has been confirmed, canceled, and then reset to draft. It matters because sales margins and pricing can now reflect the correct purchase cost again, even after order status changes.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have a product with a purchase cost; 2. have sale margins enabled; 3. add a the product to a quotation; 4. change pricelist to one with a different currency; 5. note that the line's cost gets updated; 6. change order state to confirmed, then canceled, then back to draft; 7. change pricelist again. Issue ----- The purchase cost no longer update. Cause ----- The `_compute_purchase_price` override in `sale_stock_margin` doesn't pass the line to `super` if it `has_valued_move_ids`. This hook only checks for the existence of linked `move_ids` on the record with no regard for their state. Solution -------- 1. Move the `has_valued_move_ids` hook from `sale` to `sale_stock`. 2. Only return `True` if any of the moves aren't in draft or canceled. opw-5147321 Forward-Port-Of: odoo/odoo#233746
This change prevents the website editor from crashing when a user presses Delete without an active text selection. It improves stability during common editing actions, especially when working with embedded content like videos and snippets.
Original PR description
If the selection of the document is not set and the user presses the delete key, the delete handler of the list plugin throws an error. Steps to reproduce (in 19.0, where the issue was discovered): - Open website builder - Drop the video inner snippet in the header - Double-click & drag from the video to just outside the video - Click once on the video - Press "delete" - Bug: Traceback task-5186954 Forward-Port-Of: odoo/odoo#232643
The website now publishes product price information in a way that matches the shop’s tax display setting. This prevents search engines and other consumers of the page markup from seeing a different price than visitors see on the website.
Original PR description
## Version
18.2+
SEO Schema refactoring from task-3866937
## Issue
The markup always contains the price without taxes, no matter the website settings for pricing display (with or without taxes).
## Steps to reproduce
- Go to Website settings:
- Choose "Taxes Included" for "Display Product Prices".
- Got to the shop and select any product on which taxes apply (e.g. Customizable Desk):
- Open console and execute `JSON.parse(document.querySelectorAll('[type="application/ld+json"]')[1].innerHTML)[0]['hasVariant'][0]['offers']['price']`;
- The found price and the displayed price (visible on the page) are different
## Fix
Allow tax inclusion based on parameter to mimic template's behavior on variants too depending on the website.
https://github.com/odoo/odoo/blob/52a6d88a188d5456262428847aed229f117da8ed/addons/website_sale/models/product_template.py#L377-L430
opw-4923780
Forward-Port-Of: odoo/odoo#235106
Forward-Port-Of: odoo/odoo#225577This change cleans up a complex styling workaround in the spreadsheet side panels. It keeps the same visual result while making the interface easier to maintain and less prone to styling conflicts in the future.
Original PR description
Because of a really strong rule in o_spreadsheet lib that forced the box-sizing property pretty much everywhere, we came up with a super dense rule to counteract it inside odoo and specifically inside the side panels. This commits aims to simplify it at best with the common denominator of those rules. Task-4878174 Forward-Port-Of: odoo/enterprise#99240 Forward-Port-Of: odoo/enterprise#98876
This update fixes spreadsheet input styling so missing or invalid fields are always clearly marked. It also prevents dark mode styling from altering the spreadsheet layout, keeping the interface consistent and easier to use.
Original PR description
Following the style revamp of the o-spreadsheet lib, we introduced a class o-input (differs from odoo o_input) in order to avoid collision with the odoo classes which tend to be altered in dark mode which spreadsheet does not support. However, we still relied on the default behaviour of odoo classes to mark specific inputs as invalid or missing. This commit ensures that missing/invalid are always marked as such while make preventing the dark mode to break the default layout. Task-4878174 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#235236 Forward-Port-Of: odoo/odoo#234517