Wednesday, August 26, 2026
38 changes · saas-19.3
Enhancements to existing features
The Indian localization stock demo data now creates a warehouse for the Indian demo company. This makes demonstrations and testing involving e-waybills easier because users no longer need to manually set up a warehouse first.
Original PR description
Following the task-4034713, we used to create warehouse for all company but after this task we only create warehouse for the main company while testing for Indian Demo company considering the ewaybills it's annoying to create a new warehouse for Devs and POs and even for Demos After this commit, we will create demo warehouse for the Indian demo company Task [link](https://www.odoo.com/odoo/project.task/4034713) task-4034713 Forward-Port-Of: odoo/odoo#283797
Product pages now include the product internal reference as SKU information in their structured data when it is available. This helps search engines and other services better identify products, improving consistency in product listings and integrations.
Original PR description
Include default_code as the Schema.org sku property in the product structured data when it is set. @Tecnativa TT64220 **Description of the issue/feature this PR addresses:** Product structured data does not expose the product internal reference as a SKU. **Current behavior before PR:** The sku property is absent even when default_code is set. **Desired behavior after PR is merged:** The product structured data includes default_code as the Schema.org sku property when available. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284342 Forward-Port-Of: odoo/odoo#282911
Resolved issues and error corrections
The overtime rules screen now shows the related employee versions button only to HR managers. This prevents HR officers from seeing an access error caused by data behind the button that requires manager-level permissions, improving reliability during normal use and upgrades.
Original PR description
The button requires the group `hr.group_hr_user`, but the button uses `versions_count`, that in its computation uses fields like `contract_date_start` that require the group `hr.group_hr_manager`. To avoid the mismatch, the button is restricted to only managers. This error was found in upgrades failing. To reproduce: - Install `hr_attendance`. - Assign any employee the Default Ruleset to make the button not invisible. - Change the HR security of your user to Officer. - Go to Attendance->Configuration->Overtime Rulesets and try to see the record. - A message will display the following error: ``` You do not have enough rights to access the field "contract_date_start" on Employee Record (hr.version). Please contact your system administrator. Operation: read User: 2 Groups: allowed for groups 'Employees / Administrator' ``` Forward-Port-Of: odoo/odoo#284194
Fixed an issue where section or note lines from quotation templates could be linked to active planning sessions as if they were real service lines. This prevents errors in field service planning workflows when quotations include organizational text lines.
Original PR description
This commit patches a niche bug involving creating a quotation via a quotation template containing a line section, then connecting it to an active planning session. The current architecture did not filter out `line_section` or `line_note` typed lines. This updated search domain resolves this issue. opw-6351484 Forward-Port-Of: odoo/enterprise#125056
This fix makes an internal accounting reports test run consistently by ensuring journal filter groups are checked in a stable order. It reduces random test failures, helping updates move through quality checks more reliably without changing customer-facing behavior.
Original PR description
The journal groups created in the test share the default sequence (10), so _get_journal_groups' order='sequence' has no tiebreaker and it may be returned in any order, making the assertions randomly fail. Assign an incrementing sequence per created group so the order is deterministic. runbot-941251 Forward-Port-Of: odoo/enterprise#125145
Gantt charts using a weekly view now place tasks in the correct week based on the user's locale, including regions where weeks start on Sunday. This prevents extra empty columns and keeps schedules aligned without changing existing day, month, or year views.
Original PR description
In Gantt views, for a given focus date, the appropriate time interval is displayed by finding its start and end date, based on the scale. For example, if I focus on 18 may 2026 with a month scale,…
In Gantt views, for a given focus date, the appropriate time interval is displayed by finding its start and end date, based on the scale. For example, if I focus on 18 may 2026 with a month scale, then the whole month of may is displayed. The behaviour was as expected in standard code, because all localisations agree on the beginning of the available scales (day, month, year). In custom code, however, some customer requires to see the gantt charts with a weekly scale. The differences in start of the week based on the localisations and the inconsistencies of use of localStartOf breaks the view. For example, if the localization has the start of the week on a sunday, and a task on the first column starts on a sunday as well, it will get assigned to column before (because it considers sunday as the last day of the previous week). The column before the first column does not exist, so one empty column is created to put the task in it. This commit fixes these inconsistencies so that GanttRenderer behaves as expected with weekly scales, without changing the standard behaviour. Tests are written to check both that the task is assigned to the proper localized week (starting on Sunday) and column (1, not 0). Forward-Port-Of: odoo/enterprise#118625
The update prevents an error that could occur when sales reporting or tracking data references models that are temporarily out of sync. This helps keep related business workflows stable instead of failing due to missing internal registry entries.
Original PR description
Following 6dedae804748, in case `ir.model` models are out-of-sync with the available models in the registry, trying to compute the target selection model will result in a crash (`KeyError`). This commit ensure the target model is available in the registry to avoid that crash. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284161
Sale order PDF reports now keep section and combo rows aligned when users remove columns such as Taxes or Discount through Studio. This prevents confusing blank spaces in customer-facing documents and improves the reliability of customized sales reports.
Original PR description
**Steps to reproduce:** 1. Open a Sale Order report in Studio 2. Delete the Taxes column 3. Save 4. Create a sale order with at least one section line and products that have taxes 5. Print the sale…
**Steps to reproduce:** 1. Open a Sale Order report in Studio 2. Delete the Taxes column 3. Save 4. Create a sale order with at least one section line and products that have taxes 5. Print the sale order PDF **Issue:** - A blank column is rendered in the PDF report on section (and combo) rows whenever a column such as Taxes or Discount is removed via Studio. **Why this happens:** - The section row's `colspan` and the combo row's `colspan` were computed using `3 + (1 if display_discount else 0) + (1 if display_taxes else 0)`. - `display_taxes` and `display_discount` are derived from order data (i.e. whether any line has taxes/discounts), not from which columns are actually rendered in the table. - When Studio removes a column it deletes the `<th>` and matching `<td>` elements via XPath, but these Python variables remain `True`. As a result, section/combo rows still accounted for the removed column in their `colspan`, producing one extra cell and a visible blank column. **Fix:** - Introduce a `colspan_count` variable which is incremented inside each `<th>` body - Use that counter for `td_section_name` and `td_combo_name` instead of the previous formula. - Because the increment occurs inside the `<th>` element, it is skipped whenever the element is not rendered, whether because `display_taxes`/`display_discount` is `False` or because Studio's XPath removed the element entirely. opw-6433679 Forward-Port-Of: odoo/odoo#283657 Forward-Port-Of: odoo/odoo#280719
This update corrects how Mail identifies extra attachments on messages so the system consistently treats them as attachment records. It helps ensure attachment lists behave reliably, especially when some images are embedded directly in a message body.
Original PR description
Before this commit, `extra_body_attachment_ids` is declared with `fields.Attr("ir.attachment", { compute() })`, while its compute returns the records of `attachment_ids` that the body does not inline. The model name is therefore the default of an attr field, and only a read inside an update cycle answers that string, as the compute runs on the first read outside one. No reader of the field does that today.
This commit declares the field as the `fields.Many("ir.attachment")` its compute returns, so that the declaration matches the value before the first compute as well as after.
Note that the added test asserts that a message inlining one of its two images lists only the other one, which nothing covered so far. It passes without this change.
Forward-Port-Of: odoo/odoo#284445Appointment invitation emails now generate public calendar links without permission errors. This prevents failed email rendering when attendees receive appointment invites, helping ensure customers can access their calendar details smoothly.
Original PR description
Since calendar attendee access tokens are restricted to system users, appointment mail templates must sudo token reads when generating public calendar links. This follows the same pattern as the calendar mail templates and avoids an AccessError when rendering attendee invitation emails. ref: https://github.com/odoo/enterprise/commit/88a3cca752a5f726cd0260b485fc93f65a268cf8 Forward-Port-Of: odoo/enterprise#128959
Fixes an error that could occur when marking several employee appraisals as done at once. Completion notifications and messages are now handled individually for each appraisal, so HR users can process batches without interruption.
Original PR description
Steps to reproduce: - select multiple appraisals and try to mark as done from list view. Issue: - The completion notification uses an appraisal variable assigned by a previous loop, raising an UnboundLocalError. Furthermore, message_notify() requires a singleton. Fix: - notify and post the completion message for each appraisal explicitly. task-6479018 Forward-Port-Of: odoo/enterprise#128207
The fiscal year validation now catches cases where a newly created period fully contains an existing fiscal year. This helps prevent conflicting accounting periods and reduces the risk of reporting or closing errors.
Original PR description
Before this commit: - The current constraint for overlap check allows if we define a new, larger fiscal year that completely swallows an existing smaller one (e.g., creating Aug 2025 - Nov 2026 when Sept 2025 - Oct 2026 already exists). After this commit: - The constrain domain was changed to consider the above missed case. no task Forward-Port-Of: odoo/enterprise#128942
This fix ensures French VAT return submissions do not include an express mention unless a real reason has been entered. It prevents submissions from failing when the reason field contains only spaces, improving reliability when sending tax returns to ASPOne.
Original PR description
While sending the tax return to ASPOne, before adding the BC zone we are checking that BA zone won't be empty as if BC is completed there must be the BA zone in the xml file. The problem is that when we have only whitespaces, the condition will be respected but later on due to cleanup_xml_node(), the BA zone will not be rendered in the xml but BC will and it leads to an error This commit checks that express_mention_reason fields is not empty or not only whitespaces task-6476440 Forward-Port-Of: odoo/enterprise#128242
The tour export process no longer adds an outdated URL field to generated JavaScript files. This keeps exported tour files aligned with the current format and avoids unnecessary data in generated assets.
Original PR description
The url was removed from all js file tours[1], but the exporter to JS still add it to the created JS file. This commit removes that part from the exporter. [1]: https://github.com/odoo/odoo/commit/53410a93685880b817d2b6b0ffeb7a28c254ac17
Email notifications for tracked changes now correctly display the arrow and parentheses that show what changed. This makes change summaries in emails easier to read while preserving compatibility with older messages.
Original PR description
Bug === When notifying by email a tracking change, the arrow and parentheses are not rendered in the email body. Technical and Constraints ========================= The class `o_track` is only set in…
Bug === When notifying by email a tracking change, the arrow and parentheses are not rendered in the email body. Technical and Constraints ========================= The class `o_track` is only set in the web client template (`mail.Message`). There's no class in the body of the email that is sent. It can be rendered with "notification templates" that we cannot change either (and they just do `t-out="message.body"`, so the body field of the mail message has to be properly rendered). We also need existing mail messages to be rendered correctly, and so we need a way to differentiate mail messages created before the fix from those created after it, to know when to disable the arrow and parentheses. Alternatives ============ We have tough about many solutions, this one is the best we found based on the constraints we have 1. Add a class in 19.3, use that class to not remove the arrow on previous mail message. That solution required a migration script that will change all tracking messages. Because the initial migration of the tracking was really slow, we wanted to avoid that. 2. Add a class, and keep it forever. But that solution makes the body of the mail messages bigger, which defeat one of the purpose of the initial refactoring 3. Change the outgoing email without changing the body of the mail message. That solution was really not reliable (regex change to add the arrow, and we have no clean way to target the tracking rows) 4. During the migration create a system parameter with the date, and compare with the create_date of the mail message to know if we should add the arrows or not (but we will need to keep that system parameter forever, and the code to support both to) Task-6424104
This fix separates checks for product loading limits from checks for product ordering in Point of Sale and stock-related Point of Sale tests. It helps ensure automated tests remain reliable when stock features are installed alongside Point of Sale, reducing false failures without changing user-facing behavior.
Original PR description
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching…
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching code: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L190 This allowed us to completely override (not extend) the ordering of the loaded products in our new pos_stock module: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/pos_stock/models/product_template.py#L42-L65 Notice the difference in point_of_sale: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L403-L416 This was causing problems with our existing test for this feature in point_of_sale because we were explicitly examining the ordering of the products; obviously this ordering would be different when pos_stock is installed alongside point_of_sale. Thus, we must decouple our original test for this feature so that ordering can be examined independently in each module's tests. ## Now: We have one test in point_of_sale that just makes sure our limited products loading feature actually caps the number of products loaded. This test will work correctly whether or not pos_stock is installed. In addition, we have one more test in point_of_sale and pos_stock that explicitly examines the ordering of the products in these limiting conditions when both modules are installed. The point_of_sale test will be skipped when pos_stock is installed because the latter module defines conflicting ordering. runbot-243064
The editor now checks that selected cells belong to the table whose menu is being used before allowing merge or unmerge actions. This prevents users from accidentally changing a different table when editing documents with multiple tables.
Original PR description
Steps to reproduce: - Insert two tables in the editor. - Merge cells in the first table. - Select the merged cell in the first table. - Open the table menu for the second table. - Observe that the…
Steps to reproduce: - Insert two tables in the editor. - Merge cells in the first table. - Select the merged cell in the first table. - Open the table menu for the second table. - Observe that the "Unmerge Cells" option is available even though the second table has no merged cells. - Click "Unmerge Cells". - The merged cell in the first table is unexpectedly unmerged. Description of the issue: - The "Unmerge Cells" option is shown for the second table when a merged cell from the first table is selected. - Clicking the option unmerges the selected cell from the first table. Cause: - In `getSelectedCellsMergeInfo`, `canUnmerge` was determined using `td.rowSpan > 1 || td.colSpan > 1` without checking whether the cell belonged to the target table. Solution: - Verify that the selected cells (`td`, `firstCell`, and `lastCell`) belong to the `targetTable` before allowing merge or unmerge operations. - Prevent merge and unmerge operations from being applied to cells in a different table. task-6475293
This update corrects an internal automated test related to mail tracking template changes. It helps keep quality checks reliable so future updates can be validated with fewer false failures.
Original PR description
Task-6424104
Users can now delete multiple email templates at once without the system crashing. This fixes a problem in Field Service Planning where one protected customer rating template check incorrectly blocked batch deletion.
Original PR description
Steps to reproduce: - 1. Install `planning_field_service`. 2. Open Settings > Technical > Email Templates. 3. Select two templates and delete them. Issue: - The deletion crashes with `ValueError: Expected singleton: mail.template(290, 212)`, and several templates can no longer be deleted at once. Cause: - `_unlink_customer_ratings_mail_template` guards the template configured for intervention customer ratings, but it reads `self.id`. An `@api.ondelete` hook is called once with the whole recordset being unlinked, so it raises as soon as more than one template is deleted. Fix: - Look up the configured template id in `self.ids` instead. task-6488394
This fix prevents an occasional automated test failure in the German POS certification module by waiting for the table order to finish syncing before checking its badge. It improves test stability and reduces false alarms in validation runs, with no expected impact on end users.
Original PR description
Sometimes, `test_fiskaly_basic_order` test fails with the following error: ``` AssertionError: FAILED: [55/68] Tour FiskalyTour -> Step body:has(.pos-leftheader .badge:contains(5)). Element (body:has(.pos-leftheader .badge:contains(5))) has not been found. ``` `FloorScreen.clickTable()` clicks on the table and waits for a badge to appear. The badge is rendered once the table order is synced to the server. If the order is still syncing when the click on the table lands, the badge will not be present and triggers the failure. runbot-940256
The salary offer signing page now hides an unnecessary large placeholder when no benefits are available. It also removes duplicate “Review & Sign” and “Feedback” buttons, making the offer review experience clearer for candidates and employees.
Original PR description
This commit fixes the issue of showing a big placeholder in the signing offer page when there was no benefits available, and also fix the duplicated buttons of "Review & Sign" and "Feedback" on the same page. taskid-6486370
Sales quotation and pro forma email templates now use separate full sentences for quotations and orders. This lets translators adapt grammar correctly in languages where the words require different articles or adjective forms, improving customer-facing email quality.
Original PR description
The quotation and pro forma email templates inserted either "quotation" or "order" into shared translatable text. In French, for example, "devis" is masculine while "commande" is feminine, so the surrounding articles and adjectives cannot agree with both terms. Define a complete sentence for each document state so translators can translate the surrounding grammar independently. opw-6445304 Forward-Port-Of: odoo/odoo#283901 Forward-Port-Of: odoo/odoo#283229
UPS shipping rate checks now follow UPS documentation by allowing phone numbers from 1 to 15 digits instead of requiring at least 10. This prevents valid customers in countries with shorter phone numbers, such as Luxembourg, from being blocked when getting UPS shipping rates.
Original PR description
**Steps to reproduce:** - Create a contact with a phone number that has 9 characters - Setup an UPS carrier, a configuration that works is UPS Saver as Service Type and UPS Package/customer supplied…
**Steps to reproduce:** - Create a contact with a phone number that has 9 characters - Setup an UPS carrier, a configuration that works is UPS Saver as Service Type and UPS Package/customer supplied as a package type - Create a quotation, put the created contact as a client - Try adding a shipping and getting the rates - An User Error appears, the phone number is too short **Why the fix:** Before this commit, any phone number that was less than 10 characters would raise an User Error, but some countries, such as Luxembourg, use phone numbers that are nine characters long or even less. If we check the official UPS documentation (https://developer.ups.com/tag/Shipping?loc=en_EN#operation/Shipment), we can see in the Ship_to/Phone section, that the phone number should be a number between 1 and 15, not saying it should be 10 characters or more. <img width="495" height="473" alt="image" src="https://github.com/user-attachments/assets/fed82987-ffb8-4b84-b282-6c3d3b4f304e" /> After this commit, we adapt the way we prevent the user from inputing phone numbers to fit the official UPS documentation. opw-6307577 Forward-Port-Of: odoo/enterprise#128632 Forward-Port-Of: odoo/enterprise#122831
The German tax report export now preserves cents for Kz83 values instead of rounding them down to whole euros. This helps ensure tax XML submissions show accurate monetary amounts, such as 26.40 remaining 26.40.
Original PR description
Description of the issue this commit addresses: The German tax report XML casts Kz83 to an integer before formatting it. This truncates decimal values, causing amounts such as 26.40 to become 26.00. --- Desired behavior after this commit is merged: This commit preserves the Kz83 decimal value and formats it with two decimal places in the German tax report XML. --- task-6414439 Forward-Port-Of: odoo/enterprise#125607
Users can now open links in spreadsheet cell comments with a regular click, instead of needing Ctrl+click or Cmd+click. This restores expected link behavior and makes shared references in comments easier to access.
Original PR description
Current behavior before PR: - Clicking a link in a cell comment did not work. A left click was blocked, while Ctrl+click (or Cmd+click) opened the link in a new tab. - This was caused by `t-on-click.prevent` on the comment thread and popover. It was originally added because the scroller service used the URL hash to scroll to anchors, which was removed in https://github.com/odoo/odoo/commit/711e9c9f24818714129f55283e2df64503d93605 Desired behavior after PR is merged: - `t-on-click.prevent` is removed and links in cell comments can be opened normally with both left click and Ctrl+click (Cmd+click on macOS). Task: [6448651](https://www.odoo.com/odoo/project/2328/tasks/6448651) Forward-Port-Of: odoo/enterprise#129002 Forward-Port-Of: odoo/enterprise#127473
The lunch order test now waits for the correct test product to appear after changing locations before selecting it. This prevents the test from accidentally ordering outdated demo products, reducing intermittent failures and improving release reliability.
Original PR description
The lunch order tour selects `Farm 1` before ordering a product. However, it only waits for the location input to be updated before clicking the first kanban record. With demo data installed, a product from the previous location can still be displayed while the product model is being reloaded. The tour can therefore order a demo product instead of the product created by the test. This notably fails during weekends when the corresponding demo vendor is unavailable. To fix we need to wait for the product created by the test before clicking it. Besides selecting the intended product, this also ensures that the product reload following the location change has completed. [error-181572 ](https://runbot.odoo.com/odoo/error/181572) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281753
This fix ensures that signup and invitation links are created with the required account setup information. It helps prevent failed token generation when users are invited or granted portal/project access.
Original PR description
A `signup_type` is required to generate a token. Task-6452339 Forward-Port-Of: odoo/odoo#283417 Forward-Port-Of: odoo/odoo#280891
This change makes an automated website editor test more stable by waiting for the interface to finish updating before checking the popup visibility state. It helps reduce false CI failures, improving developer confidence without changing customer-facing behavior.
Original PR description
The test `undoing something on a target outside s_popup closes it` had a few fails in CI: the `fa-eye-slash` was not set as expected. This commit adds a `waitSidebarUpdated` call just before to ensure owl has no pending rendering when checking the eye. The fix is similar to aaf0f54d1feda60becb0bfbad578b366715c0172 which is about a similar failure in another test. runbot-938967 Forward-Port-Of: odoo/odoo#284381
The salary configurator now handles cases where no company bike is configured, instead of showing an error when the bike option is selected. This keeps recruitment offer setup working smoothly and defaults the bike cost to zero when no bike is available.
Original PR description
Steps to Reproduce: - install l10n_be_hr_contract_salary module. - make sure that there is no model with vehicle type bike in fleet. - create an offer in recruitment. - open salary configurator. - click on company bike checkbox. Issue: - traceback occurs when enabling the company bike option without a configured bike. Reason: - the company bike depreciated cost value is empty when no bike is available, but the code tries to split it into bike options and vehicle ID resulting in a traceback. Solution: - Use the condition to check if the company bike depreciated cost is available before spliting the value. - Set the depreciated cost to 0 when no bike is selected. task-6468987 Forward-Port-Of: odoo/enterprise#127898
The timesheet timer now excludes archived projects from its project dropdown. This prevents employees from accidentally logging time against projects that are no longer active, while preserving past timesheet history.
Original PR description
Steps to reproduce: ---------------------------------- 1. Install the `timesheet_grid` module. 2. Create a project and add any timesheet to it. 3. Archive the project. 5. From the systray timer,…
Steps to reproduce:
----------------------------------
1. Install the `timesheet_grid` module.
2. Create a project and add any timesheet to it.
3. Archive the project.
5. From the systray timer, click on the Project field.
Observation:
----------------------------------
The archived project is visible in the dropdown.
Issue:
----------------------------------
In Odoo, standard search views and `name_search` calls on `project.project` automatically respect `active_test=True`. When you open the timer, the frontend passes `{'timesheet_timer_search': True}` in the context to `name_search` with an empty query string. `name_search` overrides standard searching to retrieve recently used projects first by querying `account.analytic.line` via `_get_recently_used_records ('project_id', ...)`. `account.analytic.line` stores past timesheet logs. Even after a project is archived, historical timesheet records for that project still exist in `account.analytic.line`. Because `_get_recently_used_records` runs a `_read_group` query on `account.analytic.line` (which has no active field of its own), it fetched the `project_id` from historical timesheet entries without checking if the referenced project was active.
Solution:
----------------------------------
In `name_search`, explicitly append `[('active', '=', True)]` to the `project_domain` used when querying `_get_recently_used_records`. Standard form/list views using `_domain_project_id` already benefit from Odoo's default ORM `active_test=True` mechanism during standard `project.project` searches.
Note:
----------------------------------
Another solution was to add `active = true` in `getTimesheetTimerFieldInfo` https://github.com/odoo/enterprise/blob/22eb84cdc94ba334d42bad32fb491d35c8147c94/timesheet_grid/static/src/services/static_timesheet_timer_service.js#L322-L328
Fixing it in Python ensures that any call passing `timesheet_timer_search` in context (e.g. mobile widgets, custom RPCs, or python wizards) will benefit from the fix, rather than only patching a single OWL JS service.
opw-6445528
Forward-Port-Of: odoo/enterprise#127374The Point of Sale now automatically chooses a product option when it is the only available choice, except for multi-select attributes. This removes an unnecessary prompt and helps cashiers add products more quickly and reliably.
Original PR description
Before this commit: ----------- - When a product attribute had only one available value, it was not automatically selected for display types other than multi. After this commit: ------------ - Automatically select the attribute value when an attribute has a single available value and its display type is not multi, allowing the product to be added without any additional user interaction. Task-6327371 Forward-Port-Of: odoo/odoo#282350 Forward-Port-Of: odoo/odoo#272437
This fix prevents quotation printing from failing for Norwegian customers when no VAT number is entered. Sales users can now print quotations successfully in this case, avoiding disruption during document generation.
Original PR description
**Steps to reproduce:** - Install the `sale_management` module. - Create a new customer and set the country to `Norway`. - Go to Sales and create a new quotation for the newly created customer. - Click the `Print` button. **Error:** `AttributeError: 'bool' object has no attribute 'startswith'` **Root Cause:** At [1], `startswith()` is called on VAT even when the customer's TIN (VAT) is not set, causing an `error`. Fix: This commit prevents the error and allows users to print the report successfully. [1]: https://github.com/odoo/odoo/blob/5c2d5daa13cf582c40bdb44e245e1359d7c410f0/addons/account_edi_ubl_cii/models/account_edi_ubl.py#L924-L928 opw-6469642 Forward-Port-Of: odoo/odoo#282961
Odoo now keeps tax usage indicators in sync when related accounting, expense, point of sale, or purchase records are changed. This prevents outdated tax status information from appearing and helps users see whether taxes are actively used before making changes.
Original PR description
Currently, `is_used` is computed using queries on `account.move.line`, `account.reconcile.model.line`, etc. As a result, it has no depends and is not automatically updated when records in either model are created, modified, or deleted. This commit reverse M2M fields for respective models and use it as dependency to `_compute_is_used`. It also adds a missing dependency of `is_used` to `_compute_repartition_lines_str`. Forward-Port-Of: odoo/odoo#283406
This fixes an internal manufacturing test cleanup so it only removes rules tied to the intended make-to-order route. It prevents accidental deletion attempts on unrelated company rules, avoiding database errors during test runs with demo data.
Original PR description
`test_check_update_qty_mto_chain` was removing `stock.rule` records from other companies using `mto_route.rule_ids.search()`. Calling `search()` on a recordset does not restrict the search to the records already present in that recordset, so the domain was effectively applied to all `stock.rule` records. With demo data, this could attempt to unlink an unrelated stock rule that is still referenced by an existing stock move, causing a `stock_move_rule_id_fkey` foreign key violation. This commit restricts the search explicitly to rules belonging to `mto_route` before unlinking them. [error-940031 ](https://runbot.odoo.com/odoo/error/940031) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users now see a loading spinner while message search results are still being updated. This helps avoid confusion when searches are slow or when early, incomplete results appear before the final results are ready.
Original PR description
Before this commit, when searching messages in a conversation, the search message panel had no UI visual when the search is ongoing. This is a problem because the search can be slow and show intermediate search results from a less specific search. This commit mitigates the issue by replacing the oi-search icon into a spinner when messages search is ongoing. That way, when this is slow or showing intermediate results, there's something on the UI that hints that the search hasn't finished. Before <img width="405" height="95" alt="Screenshot 2026-08-06 at 18 02 24" src="https://github.com/user-attachments/assets/db67b5b8-9563-433a-8367-beb2cac19f26" /> After <img width="404" height="126" alt="Screenshot 2026-08-06 at 18 02 40" src="https://github.com/user-attachments/assets/dc10366a-2102-4fd5-89c9-5b8a9e35b6b5" />
This fixes an issue in HR employee searches for users who do not have access to private employee data. Some advanced searches could return an invalid query, so the update helps keep employee search results reliable for restricted-access users.
Original PR description
The hack to search fields as a user that has no access to private employee data and searching on the `current_version_id` instead of the provided field since we force to wrap searchable fields domains in a Query in odoo/odoo#280373. The hack did not support usage of the 'any!' operator on `current_version_id` leading to a query like: "hr_employee.id in (select id from hr_version ...)". task-6468820 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284271 Forward-Port-Of: odoo/odoo#283811
This fix prevents inactive products from affecting automated website shop filter tests. It improves test reliability without changing what customers see in the online store.
Original PR description
Description of the issue/feature this PR addresses: Addresses an issue causing test failures by ensuring that [inactive products](https://github.com/odoo-dev/odoo/blob/dbc917ddc263a330ff70f5edec716ccafe88d7a6/addons/website_sale/tests/test_product_filters.py#L93-L99) are filtered out rather than leaking from the environment into the test execution. I have verified that this issue does not allow [inactive records to leak to customers](https://www.odoo.com/mail/message/1151343506). runbot-242426 Forward-Port-Of: odoo/odoo#283973
This fix ensures pay gap report tests use the correct contract pay field depending on the payroll setup. It helps prevent false test failures and supports more reliable ESG HR reporting validation.
Original PR description
Without `hr_payroll`, the contract wage is stored in `wage`. With `hr_payroll`, hourly employees use `hourly_wage` instead. This commit uses `_get_contract_wage_field()` so the test sets the correct field in both cases. [error-237750](https://runbot.odoo.com/odoo/error/237750)