Wednesday, September 23, 2026
97 changes · master
New functionality added to Odoo
Businesses can now reconcile payments and invoices across selected intercompany records. This reduces manual accounting work by automatically creating the needed entries in each company to clear invoices and match bank statement lines.
Original PR description
This commit will allow to add the interco reconciliation. To make it work few things where done: - Changing the domain of the reconcile button to be able to see the move lines of the interco companies that are selected - Changing the domain of the suggestion pill for the same purpose - Extending the set_line_bank_statement_line function. When clicking on a line that is from another company, we will create an entry on that company to clear the invoice. Then we will create a new entry on the company of the statement line that will be reconciled with the new entry line. task-6569962 Forward-Port-Of: odoo/enterprise#131502
Enhancements to existing features
The Accounting settings now include a link to documentation for intercompany clearing. This helps businesses understand and configure the process more easily when managing payments between related companies.
Original PR description
Add documentation to : intercompany clearing Documentation pr: https://github.com/odoo/documentation/compare/master...master-doc-intercompany-clearing-toher Task ID: 6478742 Forward-Port-Of: odoo/odoo#284426
Resolved issues and error corrections
Fixed an issue where employees could receive repeated chatter messages when they were automatically enrolled in an eLearning course. This keeps employee records cleaner and avoids confusion from duplicated course enrollment notifications.
Original PR description
Steps to reproduce: - connect with a user with an employee record - recreate a new eLearning course - enable debug mode - add "Role / User" to "Auto Enroll Groups" fields => message is duplicated in the employee's chatter `_action_add_members` in `website_slides` is designed to be idempotent (calling it twice is a no-op if the partner has already joined) but the override in `hr_skills_slides` is not. We have many many duplicated messages on odoo.com (see task) task-6508615 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#290032 Forward-Port-Of: odoo/odoo#284483
Code cleanup and technical improvements
The messaging menu now determines which tabs to show more directly and avoids a brief counter mismatch while messages are loading. This helps prevent selected tabs, such as bookmarks, from disappearing unexpectedly during message updates while keeping the change mostly internal.
Original PR description
Before this PR, the menu reads its tabs from two relations, allTabs and visibleTabs. Each tab fills them from its own side, with messagingMenuAsTab and messagingMenuAsVisibleTabs, two eager computes…
Before this PR, the menu reads its tabs from two relations, allTabs and visibleTabs. Each tab fills them from its own side, with messagingMenuAsTab and messagingMenuAsVisibleTabs, two eager computes returning the singleton menu, the second one only while the tab can be shown app wide. There is only one menu, so allTabs ends up holding every tab record, and visibleTabs the shown ones. The second commit turns allTabs and visibleTabs into computeds over the records of the tab model, so that the four relation fields and the two computes that maintain them go. Note that messagingMenuAsTab also hosted the counters catch-up of a tab made after initializeCountersFetcher ran, which moves to an onChange on the tab, in _catchUpCounter. The first commit comes with it. The counter of a tab is one message short while a message from the tab's own fetch sits in the store without being linked to the tab yet, and a memoized visibleTabs makes activeTab recompute inside that window: a tab hiding itself on a zero counter reads as hidden there, and the tab the user selected is dropped for the first visible one. Three tests fail on the memoization without that commit: "unbookmark all", "sidebar: change active" and "can search messages".
Accounting test setup now refreshes database statistics after loading test charts so the system chooses faster queries. This prevents long delays in localization test builds and makes internal validation more reliable without changing user-facing accounting behavior.
Original PR description
The default order of account.account joins an aggregate over the ancestor paths of every account. A company created in a test only exists in the test transaction, so the planner assumes it has a…
The default order of account.account joins an aggregate over the ancestor paths of every account. A company created in a test only exists in the test transaction, so the planner assumes it has a single account and reruns that aggregate for each of its accounts, including the dead rows left by earlier test classes. On runbot this turned 5s L10n class setups into minutes and got buckets killed. Analyzing the account tables after the chart load gives the planner the real counts, as test_balance_sheet_balanced already does. Order changes alone are not enough, and rewriting the query slows down production searches. The journal default account lookup only needs a code length, so it now uses the id order. | Benchmark | without | with | |--------------------------------------------|----------|----------| | Peru TestSequence, 25k dead rows (local) | 120-132s | 4.3-7.2s | | L10n build, slow account path queries | 94 | 0 | | L10n build, TestPosAR setup | 145s | 15s | | L10n build, TestCIIFR setup | 109s | 8s | Forward-Port-Of: odoo/odoo#289782
Recall emails for stock items now use information from the specific affected stock movement line, rather than only the overall transfer. This lets the email include clearer product and lot or serial details, helping recipients identify the recalled items more accurately.
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 Forward-Port-Of: odoo/odoo#288882
The Vietnam localization now includes dedicated accounts for revenue and costs from selling or liquidating investment property. This helps businesses comply with Circular 99/2025/TT-BTC by reporting these gains and losses on the correct Profit & Loss line.
Original PR description
Circular 99/2025/TT-BTC adds a dedicated Profit & Loss line for gains/losses on the sale and liquidation of investment property, computed from dedicated sub-accounts rather than the main revenue and cost-of-goods-sold accounts. Add the two accounts to the chart of accounts: - 5117 Revenue from sale and liquidation of investment property - 6327 Cost of sale and liquidation of investment property Task-6518304 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#290129 Forward-Port-Of: odoo/odoo#287572
Project tasks that are blocked while waiting for dependencies will no longer be treated as rotting or stale. This helps teams avoid unnecessary alerts for work that is intentionally paused until prerequisite tasks are completed.
Original PR description
Tasks in the 'Waiting' state cannot progress until their dependencies are completed. Since they are expected to remain stalled in the pipeline, there is no need to alert users by flagging them as rotting. This commit excludes tasks in the waiting state from the rotting domain. task-5265403
Back-office users can now find survey certifications using the certification number shown on generated certificates. This makes it easier to locate and verify completed certification records without relying on other participant details.
Original PR description
Purpose ======= Add the possibility to search by certification number in the back-end. Specification ============= A certification number is displayed on the certification when generated, but there's no way to use it to search for that certification in the back-end. Making a new "certification_number" field only available for user inputs that have succeeded a certification survey. Adding it as a column in the user_input list view and adding a search method so that we can search on it without storing it. Using this new field in the certification templates as well. Task-6344097 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Large reports that reuse the same barcodes or QR codes will generate much faster because identical images are reused during the report run instead of being recreated each time. This reduces waiting time for high-volume documents without changing the report output.
Original PR description
### Description of the issue/feature this PR addresses: Reports with hundreds of pages and repeated barcodes or QR codes (same document number, same lot code on every page) re-run reportlab's…
### Description of the issue/feature this PR addresses: Reports with hundreds of pages and repeated barcodes or QR codes (same document number, same lot code on every page) re-run reportlab's createBarcodeDrawing and PNG encoding on every occurrence, even when type, value and options are identical. ### Current behavior before PR: Every call to ir.actions.report.barcode() re-renders the barcode/QR from scratch, regardless of whether an identical (type, value, options) combination was already rendered earlier in the same report. On a 900-page report with 4 barcodes/page, this dominates generation time. Benchmark, 900 pages x 4 barcodes/page, 4 distinct combos, 3600 calls: 19.131s. ### Desired behavior after PR is merged: The pure rendering step (createBarcodeDrawing + mask + PNG encoding) is extracted to a module-level function keyed on (barcode_type, value, options, mask) and wrapped with functools.lru_cache. Repeated barcodes reuse the cached PNG instead of re-rendering. Same benchmark after the fix: 0.020s (946.7x speedup, cache_info hits=3596 misses=4). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289979 Forward-Port-Of: odoo/odoo#289135
Improves the mail module's internal handling of record lists so common lookups and updates avoid unnecessary copying. This should reduce overhead in mail-related screens, especially where many records are involved, while preserving existing behavior.
Original PR description
Before this commit, relation reads such as map, filter and some copied the entire relation into an array of proxies before starting. Even a search matching the first record paid that cost. This…
Before this commit, relation reads such as map, filter and some copied the entire relation into an array of proxies before starting. Even a search matching the first record paid that cost. This commit fixes the issue by implementing these common methods directly on RecordList and centralize the lazy relation computation. On read this accesses the backing array and exposes record proxies as needed, while preserving the callback arguments the inherited array methods accept, including thisArg. The read snapshots the array, so that any mutation during a traversal never skips or repeats a record: the read finishes on the records the relation held when it started. Add regression coverage for traversal during mutations, completed mutation visibility to immediate observers, and callback binding. Chrome 153, median across 18 batches in two runs, in µs per operation (lower is better): | Operation | Records | Before | This commit | | --- | ---: | ---: | ---: | | `some()`, first match | 5 | 0.597 | 0.204 | | `some()`, first match | 500 | 40.02 | 0.203 | | `map()` | 50 | 6.10 | 5.58 | | `map()` | 500 | 63.35 | 62.45 | | `shift()` + `push()` | 500 | 142.38 | 49.65 | | `pop()` + `unshift()` | 500 | 185.11 | 98.95 | | Indexed replacement (`list[i] = record`) | 500 | 1.13 | 47.13 | These are isolated RecordList/Owl microbenchmarks, not end-to-end Discuss UI timings. Forward-Port-Of: odoo/odoo#287994
The IAP settings button can now show a custom label instead of always saying "Manage Service & Buy Credits." This helps businesses make each credit purchase option clearer when a settings section is tied to a specific service.
Original PR description
The button always reads "Manage Service & Buy Credits", which is ambiguous when one setting section offers credits for a specific services. Add an optional label attribute. task-6587953 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#289499
Planning now warns users when they try to send a schedule but none of the selected employees have a valid work email address. This prevents users from thinking schedules were sent successfully when no employee could actually receive them.
Original PR description
Before: when all employees in the send wizard lacked a work email, clicking 'Save & Send Schedule' sent the schedule to no one without informing the user. After: a warning notification is shown explaining that the planning cannot be sent until at least one employee has a valid work email address. task-5092438
Point of sale users can now add money to a customer's account even when that customer still has unpaid invoices. This makes it easier to accept deposits without forcing staff to settle existing dues first.
Original PR description
"Deposit money" was only offered in the partner list when the customer had no due, so a customer with open invoices could not put money on their account without settling those invoices. Always offer it when a customer account payment method exists. opw-6514079 Forward-Port-Of: odoo/enterprise#132065 Forward-Port-Of: odoo/enterprise#131268
Deleting a starting activity in a marketing automation flow no longer removes all connected child activities by default. The system now keeps valid follow-up steps and only removes trigger steps that cannot stand alone, reducing the risk of accidental campaign data loss.
Original PR description
When a user deletes a root marketing activity, the system currently performs a cascading delete, removing all of its child marketing activities as well. This behavior can be disruptive and may result in unintended data loss. This PR refines the deletion logic to remove only trigger nodes (e.g., "wait for value" or "mail interaction") that are not allowed at the root of the flow. Other nodes that are valid at the root level will be preserved. Task-6559148 Forward-Port-Of: odoo/enterprise#131453
The Marketing Automation editor has been visually refreshed with more consistent spacing, icons, step labels, and layout details. This makes campaign setup and review easier to use, while also improving the mobile experience for creating steps and removing unused trace view elements.
Original PR description
Improve the editor UI with consistent spacing, icons, step names, and other visual elements across the application. This gives the interface a more modern and cohesive look and improves the overall user experience. It also removes unused templates from the trace view and improve the responsiveness of the creation helper on mobile devices. Task-6559148 Co-authored-by: Chrysanthe <chgo@odoo.com> Forward-Port-Of: odoo/enterprise#131772
The employee form no longer shows the dependent children attachment field because that information is now managed directly on the salary attachment form. This reduces duplicate entry points and helps users find the document in the more relevant payroll workflow.
Original PR description
Remove `l10n_be_dependent_children_attachment` from employee form view as it is now displayed directly on the salary attachment form. Task:6584296
Payslip adjustment lists now include the estimated end date as an optional hidden column. This gives payroll teams quick access to timing information when needed without changing the default list view.
Original PR description
Added a column in payslip adjustment list for the estimated end date. Task:6565901
Automatic reconciliation now matches payment references to invoice names even when uppercase and lowercase letters differ. This reduces missed matches and manual reconciliation work for accounting teams.
Original PR description
Currently, when a payment reference isn't in the same letter case as the invoice name, it wouldn't automatically reconcile. task-6562440 Forward-Port-Of: odoo/enterprise#131418
The AI website assistant can now allow generated JavaScript for only the current chat session instead of enabling it for the whole website. Generated scripts also wait until the page is ready before running, reducing broken interactions and making AI-created website behavior more reliable.
Original PR description
[IMP] ai_website: propose to allow javascript session-wise Commit [1] added an option to add javascript and to allow it for the whole website. This commit adds an option to allow inserting javascript…
[IMP] ai_website: propose to allow javascript session-wise Commit [1] added an option to add javascript and to allow it for the whole website. This commit adds an option to allow inserting javascript in the current chat only. [1]: https://github.com/odoo-dev/enterprise/commit/ad87d6aac19ad4a2b0fe572fff8931c9c122723d task-6481594 --- [REF] ai_website: rename aiScriptsRuntime to aiScriptsManager aiScriptsRuntime wasn't the best name for it, so we renamed it to the aiScriptsManager. task-6481594 --- [FIX] ai_website: run ai scripts only when the dom is loaded Scripts that are generated by AI run as soon as they are parsed, which might lead to issues if it uses not yet parsed content. Steps to see the issue: - Drop a `splash_intro` snippet and some snippet after it - Ask AI to "scroll the page down to the next section when 'Impact' is hovered" => It might check for the presence of the next section immediately when it runs, exiting the script early. task-6481594 Forward-Port-Of: odoo/enterprise#129834
Customer statement and open items reports now produce clearer, better-formatted PDFs with customer addresses included. PDF exports are organized per customer in one combined file, making reports easier to review and share.
Original PR description
This commit adds the following improvements to the customer statement and open items reports: 1) Adds more space for the company bank account number in the header and avoid line breaks in it 2) When printed in PDF, it prints one PDF per customer concatenated together in a single PDF 3) It includes the customer address in the generated report 4) They have better styling task-6476236
Custom AI agents can now guide users through making the agent available by default on relevant business forms, such as leads or tasks. This makes tailored AI assistance easier to deploy without requiring a separate technical setup or custom server action.
Original PR description
Users create custom AI agents and want them to appear automatically as the default agent when they open the relevant form view (leads, tasks, etc.). Extend the "Self Update" skill instructions so that after the agent writes its own model-specific system_prompt, it walks the user through binding itself to that model's form via the existing generic tools — no dedicated server action needed: 1. Resolve the target ir.model via ai_tool_search. 2. Check for an existing (agent, chatter_ai_button, model) rule and propose to update it rather than duplicate. 3. Ask (in plain text) for 2-4 typical actions. 4. Create/update the ai.composer with interface_key='chatter_ai_button' and ai_agent_id pointing back at the current agent. 5. Create the matching ai.prompt.button rows linked via composer_id. task-6578312 Forward-Port-Of: odoo/enterprise#131952
The Belgian payroll rules now include the updated CP200 homeworking representation fee amount of 164.21 effective September 1, 2026. This helps ensure payroll calculations use the correct allowance value for eligible employees from that date.
Original PR description
Add a value of 164.21 for the rule parameter "CP200: Representation Fee - Homeworking - Amount" with `date_from` set to September 1, 2026. Task:6580623 Forward-Port-Of: odoo/enterprise#132568 Forward-Port-Of: odoo/enterprise#131932
Appointment setup in the calendar is now easier to manage, with slot creation moved back into the main sidebar flow and clearer actions for editing, archiving, deleting, and adding video links. The sidebar now focuses on active appointment types, reducing clutter while keeping older or unused appointments accessible through their full forms.
Original PR description
### Move slot creation back to the top of the sidebar Have it all in one place and allow the same behavior as the old "picking slots" where an appointment is immediately created for users to set…
### Move slot creation back to the top of the sidebar Have it all in one place and allow the same behavior as the old "picking slots" where an appointment is immediately created for users to set slots and share immediately. As this removes the ability to search for a specific existing appointment, we also remove the ability to select specific appointments to show in the list in favor of just filtering unused appointment types (with slots ending over 2 weeks ago) to prevent clutter. We also add an archive button on the quick edit form to enable removing unused appointments. ### Add appointment selection Instead of clicking on an appointment type instantly enabling slot edition mode it will highlight the meetings that are linked to that appointment type in the calendar and set it as default for new bookings made while it is selected. They can then enter slot edition by clicking on the "options" button and clicking picking slots, as was possible before. ### Combine creation and deletion mode This mode was previously added to allow some actions when clicking slots such as creating an event spanning the entire slot. In the end we prefer deleting slots being very accessible over that feature. ### Remove punctual options These options are too advanced for a simple quick appointment creation. We still support displaying them specially but users will have to go to the full form to actually set them up. ### View tweaks Use pencil instead of cog, add a "add video link" button, etc... Renaming of some actions to be more clear (save -> done, configure -> edit, ...) Remove default name when creating a new appointment to force users to pick a good one. ### Minor fixes Slot cloning actions are properly hidden when there are no slots to clone. Users who don't have the access rights to create apt types don't see related options. task-6544898 Forward-Port-Of: odoo/enterprise#131749
Short display labels for margin fields are now managed by the Sales Margin module, where those fields are defined. This keeps module responsibilities clearer and helps avoid label setup being tied to the broader Sales module unnecessarily.
Original PR description
enterprise PR: https://github.com/odoo/enterprise/pull/132119 Move the short label registration for the margin and margin_percent fields from sale to sale_margin, so each field's label lives in the module that defines the field. opw-6580783 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289205
Subcontracting manufacturing orders now show key actions and status details directly on the form, reducing the need to navigate through inventory menus. The overview also shows component availability at the subcontractor location, helping users better understand shortages and replenishment needs for subcontracted work.
Original PR description
*: mrp_subcontracting_purchase Currently, when a subcontracting MO is opened from the picking view, only limited information is displayed. Users need to navigate to the corresponding MO via…
*: mrp_subcontracting_purchase Currently, when a subcontracting MO is opened from the picking view, only limited information is displayed. Users need to navigate to the corresponding MO via Manufacturing Operations in Inventory to access additional details. In addition, the MO overview displays component information based on the warehouse instead of the subcontracting location, making it difficult to review the actual component availability for the subcontracting process. This commit improves the subcontracting MO by: - Adding Overview and Transfers smart buttons, along with the start date and component status, directly on the subcontracting MO form. - Adding a `Free to Use / On Hand (Subcontractor Location)` column to display the quantities available at the subcontractor location for each component in the MO overview. - Hide free to use/on hand and Reserved for finished product. - Computing the `receipt status and reserved quantities` using the subcontractor location instead of the warehouse. - Allow replenishment of components at the warehouse from subcontracting MO overview. - Show the Source PO smart button only in the resupply picking view. - Renamed the `Subcontracting Productions` smart button to `Subcontracted Productions`. TaskId-6234816 Forward-Port-Of: odoo/odoo#267733
Invoice amount due now updates immediately while editing, reducing confusion from totals temporarily appearing out of sync. Applying outstanding credit also saves the invoice first, preventing newly added invoice lines from being lost.
Original PR description
Before this commit, the account.move amount due field would only update on record saving (as it depended on line_ids). This caused a temporary out of sync situation between the total and the amount due on the move form view. This commit ensures that the amount due is computed even before saving the record so that out-of-sync situation is avoided. It also solves the following bug: Repro steps: 1) Create a new invoice 2) Add a customer and save the record 3) Add some invoice lines 4) without saving, add a payment from the outstanding credit Issue: The added (unsaved) invoice lines are removed Solution: This commit forces a record save before assigning outstanding credit task-6534794
Website editors can now insert videos hosted on their own server or a CDN through the media dialog, instead of being limited to supported third-party platforms. This gives businesses more flexibility and control over video content while keeping the feature enabled only where intended, such as the website builder.
Original PR description
Description of the feature this PR addresses: The video tab of the media dialog only accepted urls from the eight supported third party platforms, so a self-hosted video, or one served from a CDN, could not be inserted at all. Add a `VideoFile` provider, tried once no platform matches the url. A video file url has no recognizable shape, so it is probed rather than matched, it is loaded in a detached `<video>`. The feature is behind the `allowVideoFile` config flag, off by default and currently enabled by the website builder. Removes YoutubePlugin which is dead code. task-6466707 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282438
Work order planning now includes draft work orders by default in both Kanban and Gantt views. This gives planners a more complete view of upcoming manufacturing work, helping them schedule earlier and avoid missing items that are not yet confirmed.
Original PR description
- Add the Draft filter to the default filters in Work Orders Planning for both Kanban and Gantt views, ensuring draft work orders are included in the planning view. Forward-Port-Of: odoo/enterprise#131906
Rental sale orders now keep the Delivered column less cluttered by hiding returned quantities when nothing has been returned. When items have been returned, the returned amount is clearly marked with an "R:" label so users can quickly distinguish it from delivered quantities.
Original PR description
Steps to reproduce: - Install sale_renting module. - Create a rental order with a rentable product. - Confirm the order. On a confirmed rental sale order, the qty_returned field is now hidden when it equals zero, keeping the Delivered column uncluttered for lines with no returns yet. When non-zero, it is displayed with a short "R:" prefix using the `labeled_float_field` widget, consistent with other stacked fields in the same column. **Before:** <img width="1228" height="142" alt="image" src="https://github.com/user-attachments/assets/c00aea57-0927-4da5-bac4-3616d6bf3396" /> **After:** <img width="1230" height="150" alt="image" src="https://github.com/user-attachments/assets/8247988f-8d00-4a85-892c-d019d66f5d59" /> Enterprise PR: https://github.com/odoo/odoo/pull/289205 **opw-6580783** Forward-Port-Of: odoo/enterprise#132119
Inventory screens were simplified by removing redundant detailed stock options and making key physical inventory and wave preparation actions easier to find. Wave transfer wording and navigation are clearer, helping users create and manage waves with fewer interruptions.
Tax return checks now focus on issues that actually need attention, reducing unnecessary warnings once company data is complete. The tax reconciliation and draft review checks also provide more accurate results by using the return period, posted entries, and relevant sales and purchase journal filters.
Original PR description
Before this commit:- - Company Data check was always created, just like other checks. - Company Data check's message was using static 'VAT' word. - Drafts & Reviews check excluded moves with type…
Before this commit:-
- Company Data check was always created, just like other
checks.
- Company Data check's message was using static 'VAT' word.
- Drafts & Reviews check excluded moves with type `entry` for common vat report.
- Tax Reconciliation check action
- Opens pivot view of move lines with row group by tax_tag_ids > account_id.
- Domain used only outgoing moves.
- There was no date filter.
After this commit:-
- Company Data check will be created only when failing, if it is passing then
don't create. Because unlike other checks, once company data is set, this check
will always pass, and creating it every time is useless.
- Company Data check's message uses dynamic vat label.
- Drafts & Reviews check now includes `entry` type moves for the common VAT
report, but only when they carry taxes.
- Tax Reconciliation check action
- Opens pivot view of move lines with row group by tax_ids > account_id.
- Remove domain and apply Sales and Purchase journals in default filters so
user can remove it and see it all if needed.
- Apply current return's date period in default filters.
- Apply only Posted moves in default filters.
- Improved names and messages of some checks.
[task-6486107](https://www.odoo.com/odoo/project/967/tasks/6486107)
Forward-Port-Of: odoo/enterprise#130750Customers who start adding a configured product to their cart will no longer lose that action if they close the configurator without explicitly confirming. When the configuration is valid, the main product and selected optional products are still added, reducing missed sales and checkout friction.
Original PR description
Previously, closing the product configurator dialog without confirming resulted in no products being added to the cart, even if the user had initiated an add-to-cart action. This change ensures that both the main product and optional products are added to the cart when the dialog is closed, provided the configuration is valid. task-6055551
Fixed an issue where changing a gradient angle in the website editor color picker could be lost after saving. Users can now set and save custom gradient directions reliably, improving visual editing consistency.
Original PR description
Problem: When changing the gradient angle input in the color picker and saving the record, the updated angle is not saved and reverts to the previous value. Cause: `setOnCloseCallback` runs before `onAngleChange` because the angle input fires the `change` event on blur/close. As a result, `onColorGradientChange` is called with the previous angle value, and `onColorGradientPreview` runs afterwards with the new value, causing the applied preview to be reverted later. Solution: Call `onAngleChange` on the `input` event instead of `change` so that state and preview update immediately each time the user types. Steps to reproduce: - Add a gradient to a building block. - Define a value of 180 degrees. - Save - If you open the color picker the value is still 135. task-6522533 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286990 Forward-Port-Of: odoo/odoo#285967
This fix makes upload areas easier to read by moving the upload icon so it no longer overlaps the drop zone content. It also corrects stacked icon alignment, giving users a cleaner and more consistent visual experience with the updated design.
Original PR description
### Adjust `oi-stack-*` icons Since the introduction of the new Material Icons library, we also introduced the `oi-stack-*` classes to allow stacking multiple icons. Prior to this PR, the vertical…
### Adjust `oi-stack-*` icons Since the introduction of the new Material Icons library, we also introduced the `oi-stack-*` classes to allow stacking multiple icons. Prior to this PR, the vertical alignment was incorrect when stacking a 1x icon with a 2x icon. This commit adjusts the vertical alignment to ensure that stacked icons are properly aligned. ### Adapt drop zone layout Prior to this PR, there was a layout issue where the upload icon was positioned on top of the drop zone, making the content difficult to read. This PR adjusts the icon position and fine-tunes the layout to better match the new Frost design. task-6591717 --- Example using ```xml <div class="oi-stack oi-4x"> <i class="oi oi-stack-2x" data-icon="circle"></i> <i class="oi oi-stack-1x" data-icon="star"></i> </div> ``` | Before | After | |--------|--------| | <img width="149" height="141" alt="Screenshot 2026-09-23 at 09 00 00" src="https://github.com/user-attachments/assets/9d343dc5-6f83-4f1e-8548-47cfec00272a" /> | <img width="146" height="142" alt="Screenshot 2026-09-23 at 09 00 25" src="https://github.com/user-attachments/assets/c67fdc1d-d29f-494d-9646-04014bd68d8f" /> | Adapt drop zone layout | Before | After | |--------|--------| | <img width="1668" height="698" alt="Screenshot 2026-09-23 at 08 51 30" src="https://github.com/user-attachments/assets/d92d5aee-9046-4a35-892e-ba11994d8e4b" /> | <img width="1671" height="698" alt="Screenshot 2026-09-23 at 08 51 22" src="https://github.com/user-attachments/assets/532a0625-5f04-4a52-a113-442ad3c58357" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289893
The messaging menu now gives clearer visual feedback when users hover over the three-dot options button. This reduces accidental clicks and makes opening item options more reliable without changing the overall messaging workflow.
Original PR description
Before this commit, the bg hover effect of messaging menu item was present even when mouse-hovering the "..." button of a non-active messaging menu item. This had the drawback of misclicks on "..." happening because the bg hover effect is unchanged and gives the impression that we would click on messaging menu item selection even when mouse-hovering the "..." button. This commit fixes the issue by following a similar logic as with channel member list panel: the bg hover effect is shown when mouse-hovering the item except the "..." button, so that click on "..." is easier and more reliable. Note that since bg hover effect is visually similar as active messaging menu item, this is kept when the messaging menu item is active. Before https://github.com/user-attachments/assets/4488438c-883f-4dd9-9038-5c14c107556d After https://github.com/user-attachments/assets/00341a1d-cf7d-42f1-b175-08f3d3cf758c Forward-Port-Of: odoo/odoo#289927
Reference fields now make the record selection easier to notice when a model has been chosen. This helps users avoid saving incomplete links that disappear after refreshing the page.
Original PR description
Steps to reproduce: 1. Install Sign. 2. Open the form view of a document. 3. Select a model in the "Link to" (Reference) field, but leave the record empty. 4. Save and refresh the page. Issue: -…
Steps to reproduce:
1. Install Sign.
2. Open the form view of a document.
3. Select a model in the "Link to" (Reference) field, but leave the record empty.
4. Save and refresh the page.
Issue:
- After refreshing, the selected model is cleared because the reference value is invalid.
Cause:
- A reference field is only valid when it contains both a model and a record ID. However, the record selector has no placeholder, making it easy to overlook and save an incomplete value.
Solution:
- Add a default placeholder to the record selector of reference fields to make it more visible.
<table>
<tr>
<th>Before</th>
</tr>
<tr>
<td>
<img src="https://github.com/user-attachments/assets/3ba34b77-f901-4d3e-9768-5acaf2e673b8" alt="Before" width="100%">
</td>
</tr>
<tr>
<th>After</th>
</tr>
<tr>
<td>
<img src="https://github.com/user-attachments/assets/1fe54b89-221f-4d28-bd2b-0a3c706d5746" alt="After" width="100%">
</td>
</tr>
</table>
opw-6426339
Forward-Port-Of: odoo/odoo#280266This update prevents a crash when opening certain image attachments linked to products or other attachments. It improves reliability for users managing product images and attachments, and adds test coverage to prevent the issue from returning.
Original PR description
### Steps to Reproduce: 1. Go to Sales > Products and select a product 2. Upload an image for the product 3. Go to Settings > Technical > Attachments 4. Click on one of the image attachments 5.…
### Steps to Reproduce: 1. Go to Sales > Products and select a product 2. Upload an image for the product 3. Go to Settings > Technical > Attachments 4. Click on one of the image attachments 5. Observe the Client Error: "Uncaught Promise > Invalid props for component 'Many2One': 'domain' is not a function" ### Issue: In `attachment_patch.js`, the domain for the `Many2OneReferenceField` is overridden when an attachment is linked to another attachment. The patch calculates the domain and incorrectly assigns a static Array (using `.toList()`) to `props.domain`. In Odoo 19, the `Many2One` component enforces strict prop validation (caught when Owl's debug mode is enabled during testing), causing a crash because it expects the domain prop to be a function. ### Solution: We can just wrap the resulting domain Array in an arrow function so that it evaluates dynamically when the `Many2One` component mounts. Also added a unit test to explicitly cover this patched scenario. The test manually applies a local patch to `Many2OneReferenceField.prototype` to accurately replicate the environment and verify the fix. opw-6563954 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289772 Forward-Port-Of: odoo/odoo#287951
This update fixes an automated test for the Point of Sale self-order feature after a recent platform change. It helps ensure future changes to this area are checked correctly and reduces the risk of unnoticed test failures.
Original PR description
Since [1], this.props no longer automatically exists on components. As a consequence, a pos_self_order test didn't pass anymore. For an unknown reason, this addon is excluded from regular builds, so its tests aren't run, hence the fact that [1] could be merged with this failing test unnoticed. Hopefully, nightly builds spotted it. [1] https://github.com/odoo/odoo/pull/289550 Runbot-947518 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#290143
The Mail interface now uses even spacing in action panel headers, keeping header content centered and aligned with the panel body. Meeting views also apply the same padding consistently across all action panels, creating a cleaner and more consistent user experience.
Original PR description
The action panel header had uneven start/end padding, so its content sat off-center and did not line up with the panel body. In the meeting view, only the chat panel header got the meeting padding. This commit uses symmetric padding for the header and applies the meeting padding to every action panel of the meeting view. <img width="1704" height="720" alt="meeting-action-panel-header-before-after" src="https://github.com/user-attachments/assets/e483954c-137d-42b1-9fb8-d2eed3e04f80" /> Forward-Port-Of: odoo/odoo#290103
This fixes an issue in the HTML editor where formatting or other attributes could be lost when pasted content was converted from one block type to another. It helps preserve the intended appearance and behavior of edited content.
Original PR description
The PR [1] forgot to copy the attributes from the DIV into the new P. It is not possible to use `setTagName` here because the function is in DomPlugin which depends on BaseContainerPlugin. See [2] for more information. [1]: https://github.com/odoo/odoo/pull/289891 [2]: https://github.com/odoo/odoo/pull/289891#discussion_r4075860275 Forward-Port-Of: odoo/odoo#290085
The mail call settings panel has been refreshed to better match the newer Frost visual design. Setting groups and device selectors now look more polished and consistent, while the download logs action is presented as a simpler link.
Original PR description
The call settings panel still used plain outlined boxes. This commit fills the setting groups and device selectors as raised surfaces, drops the nested borders and the stray push-to-talk separator, and turns the full-width download logs button into a link. <img width="1360" height="510" alt="20 0-discuss-ui-fixes-aku-3" src="https://github.com/user-attachments/assets/4fe070d1-ac36-4e10-b74e-900ab3e9a704" /> Forward-Port-Of: odoo/odoo#290100
The website project form processing has been cleaned up and reorganized to support more reliable handling and future updates. This is a minor internal fix that should help maintain the feature without changing the user experience.
Original PR description
Clean up and move some of the form processing logic for future updates opw-6560036 Forward-Port-Of: odoo/odoo#287697
This update fixes an internal test for messaging channel invitations so it no longer conflicts with sample demo users that share the same name. It helps keep automated quality checks reliable without changing behavior for end users.
Original PR description
Before this commit, the channel invite search test fails on a database with demo data: AssertionError: Lists differ: [18, 405] != [405] This happens because the test searches "Joel" while the demo data holds its own portal user "Joel Willis". The second search asks for portal users, so the demo one comes back as well. This commit fixes the issue by searching a name that only the test user carries. https://runbot.odoo.com/odoo/error/947235 Forward-Port-Of: odoo/odoo#289982
Duplicated taxes now keep the correct domestic tax status instead of being silently marked as non-domestic. This helps prevent configuration errors in accounting when users copy existing tax records.
Original PR description
_compute_is_domestic checks whether the company's domestic_fiscal_position_id is part of the tax's fiscal_position_ids. Because this field is both stored and precompute=True, duplicating a tax recomputes it on a virtual new() record before insert. On that virtual record, fiscal_position_ids is resolved through NewId pseudo-ids while company_id (a plain Many2one) keeps its real id, so the containment check always failed, silently turning is_domestic into False on any duplicate. Use fiscal_position_ids._origin to compare against the real underlying records instead. opw-6575113 Forward-Port-Of: odoo/odoo#289896 Forward-Port-Of: odoo/odoo#289246
Project task counters now ignore subtasks that belong to task templates, matching what users see as real tasks in the interface. This prevents inflated task totals and gives project teams more accurate open, closed, and overall task counts.
Original PR description
Before this commit, the task_count and closed_task_count takes into account the subtask inside task template, however, those subtasks are not considered as a basic task in the UI, there are also considered as a template.
This commit adds `('has_template_ancestor', '=', False)` condition to make sure those subtasks are no longer taken into account. The condition inside the compute of `open_task_count` has also been reviewed to have the same conditions in the 3 fields.
task-6483156
Forward-Port-Of: odoo/odoo#286910This update fixes an internal website test that was still using an outdated footer language selector reference. It helps keep automated checks reliable after recent website changes, reducing the risk of false failures during development.
Original PR description
Steps to reproduce: - Run `test_website_standalone`. => `test_01_cow_views_inherit_on_module_update` fails. Before this commit, the test changed the old footer selector. Since [1], the language selector uses a new hook. The test thus created an invalid view. After this commit, the test changes the new hook to match the temporary parent. [1]: https://github.com/odoo/odoo/commit/39d871397f6969a1c87226bed0d016edf4995e5c runbot-947383 Forward-Port-Of: odoo/odoo#289828
This update prevents crashes in several Odoo screens by making component configuration requirements explicit after an internal framework cleanup. Users benefit from more reliable dialogs, messaging, mailing, website, spreadsheet, and point-of-sale flows without any expected workflow changes.
Original PR description
Forward-Port-Of: odoo/odoo#289550
The Odoo Gmail plugin was updated to use the correct system setting lookup for newer Odoo versions. This prevents an error that could block users from authenticating with Odoo through Gmail.
Original PR description
In version 19.1+, the ir.config_parameter model no longer has the function get_param. Instead you use get_int, get_str, etc. This was causing a traceback in auth_access_token when a user tries to authenticate with Odoo via the Odoo gmail plugin. Forward-Port-Of: odoo/odoo#289957
Clicking inside a styled link in the HTML editor now places the cursor in the correct position. This makes editing linked text more reliable and avoids confusing cursor behavior for users preparing content.
Original PR description
Since #284197 a pointerDown event inside a formated link was not setting the selection in the correct position. We fixed the issue by getting the clicked element closest link to ensure we are effectively outside a link. task-6592373 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289945
This fixes a display issue in the HTML editor where turning large header text into a list could make bullets appear too far to the left. Lists now adjust their spacing automatically, improving document formatting and reducing visual glitches for users editing rich text.
Original PR description
Problem: Creating a list on a header block with large font size content causes the list marker/bullet to overflow to the left. Cause: `ListPlugin.blockToList()` wrapped block elements into a list without invoking `this.adjustListPadding(list)`, leaving the list padding unadjusted for larger font sizes. Solution: Call `this.adjustListPadding(list)` in `blockToList` so that proper inline padding is set based on the list item content font size. Steps to reproduce: - Create a header block (e.g. Header 4). - Change the font size of the header content to be bigger. - Apply a list on the content. => Observe that the list marker overflows to the left. opw-6542903 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286975
Selecting a city in an employee’s private address now fills in the related address details directly on the form, without waiting for the record to be saved. This keeps the employee address entry experience consistent and reduces confusion for HR users.
Original PR description
Issue: When you select a city in the employee's private address field, the other address fields should be populated accordingly. Even though once you save, the changes are recorded, they don't appear in real-time in the form. This is because the onchange related to the address city field was only in `hr.version`, but not `hr.employee`, so the automatic population upon the change of the city wasn't visible in the employee form view. Fix: Add _onchange_private_city_id() in hr.employee under hr_address_extended module which calls the same-name onchange in the linked version. task-6584206 Forward-Port-Of: odoo/odoo#289837
Live Chat rules now reject invalid URL matching patterns when they are saved. This prevents website visitors from triggering errors when Live Chat loads and helps administrators catch configuration mistakes earlier.
Original PR description
Currently, an error occurs when a user opens the website and Live Chat is initialized with an invalid URL regex. Steps to Reproduce: - Install `website_livechat` without demo data. - Open `Live Chat`…
Currently, an error occurs when a user opens the website and Live Chat is initialized with an invalid URL regex. Steps to Reproduce: - Install `website_livechat` without demo data. - Open `Live Chat` and, in the `YourWebsite.com` channel, click the `three-dot` menu and select `Configure Channel`. - Go to the `Rules` tab. - Add a rule, select `Welcome Bot` in `Chatbot`, and set an invalid regex such as `*` in `URL Regex` and save. - Click `Join Channel`. - Open the `website`. `re.PatternError: nothing to repeat at position 0 when serializing dict item 'result' ` - when `URL Regex is '['` `re.error: unterminated character set at position 0 when serializing dict item 'result'` When a user opens the website, Live Chat is initialized by checking operator availability and finding the matching country/URL rule [1]. The rule matching checks whether `regex_url` matches the current page URL. It uses `re.search()` [2], which compiles the regex pattern before searching. If `regex_url` contains an invalid pattern such as `*`, `re.search()` raises `nothing to repeat at position 0` because `*` must follow a preceding regex element. Similarly, `[` starts a character set (`[...]`) but has no closing `]`, causing `unterminated character set at position 0`. This commit adds a constraint to validate `regex_url` and reject invalid regex patterns when creating or updating Live Chat rules. [1]- https://github.com/odoo/odoo/blob/f962f1eccecfdbc95375f795174c8f687459b521/addons/im_livechat/controllers/main.py#L87 [2]- https://github.com/odoo/odoo/blob/f962f1eccecfdbc95375f795174c8f687459b521/addons/im_livechat/models/im_livechat_channel.py#L387 sentry-7679767396 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283545
The HTML editor now ignores blank metadata when showing link previews. This ensures users see a useful fallback, such as the URL, instead of an empty clickable preview area.
Original PR description
Problem: When a link's metadata contains whitespace-only strings for `og_title`, `og_description`, or `og_image` (e.g. `og_title: " "`), the link popover displays an empty clickable preview area.…
Problem: When a link's metadata contains whitespace-only strings for `og_title`, `og_description`, or `og_image` (e.g. `og_title: " "`), the link popover displays an empty clickable preview area. Cause: `LinkPopover` assigned raw metadata values directly. Non-empty whitespace strings evaluate to truthy values in JavaScript (`" "` is truthy), preventing fallback to the default URL or empty string. Solution: Trim the metadata values (`og_title`, `og_description`, `og_image`) when populating state so that whitespace-only values evaluate to empty strings and trigger appropriate fallbacks. Steps to reproduce: - Open HTML editor. - Add a link with URL `https://netorg4182089.sharepoint.com/:v:/s/projects/IQD72ajP3WOBT4jcAu_1qLfIAamL9lvrq4ls1Bs9XCyXJvw?e=vQ9wH3`. - Open the link popover. => Observe that the popover title falls back to the URL instead of showing an empty clickable space. opw-6564118 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288188
The calendar view now updates properly when users resize their browser or switch to a smaller screen. This prevents the desktop sidebar from staying open on mobile, making the calendar easier to use on phones and narrow windows.
Original PR description
See commits Forward-Port-Of: odoo/odoo#289677 Forward-Port-Of: odoo/odoo#288329
This fixes a crash that could occur when opening an email message containing an embedded code block in the chatter. Odoo now avoids applying code syntax highlighting inside incoming email bodies, keeping those messages readable and preventing the chatter from failing to load.
Original PR description
**Steps to reproduce:** - Receive a mail with an embedded code block - Open a chatter containing this message - Error: "Cannot mount a component on a detached dom node" **Issue:** Mail message are…
**Steps to reproduce:**
- Receive a mail with an embedded code block
- Open a chatter containing this message
- Error: "Cannot mount a component on a detached dom node"
**Issue:**
Mail message are rendered with a shadow dom body and isolated from surrounding styling.
```xml
<div class="o-mail-Message-shadowBody overflow-x-auto" t-if="this.message.message_type and this.message.message_type.includes('email')" t-custom-ref="shadowBody"/>
```
Then in `useLayoutEffect` parent element is created for the shadow root and the message body is created:
```js
const bodyEl = createElementWithContent(
"span",
this.message.showTranslation
? this.message.richTranslationValue
: this.props.messageSearch?.highlight(this.message.richBody) ??
this.message.richBody
);
const roots = this.prepareMessageBody(bodyEl) ?? [];
this.shadowRoot.appendChild(bodyEl);
```
But after [1] we have `return this.renderEmbeddedCodeBlocks(bodyEl);` which calls:
```js
const { root, mountPromise } = mountComponent(...);
```
And root creation fails as the element is not on the shadow root yet (due to `validateTarget` and `isAttachedToDocument`).
```js
const root = app.createRoot(Component, { props, env });
```
But even if we have the element directly added on the `shadowRoot` the highlighting styling won't be applied properly without all the needed assets.
**Fix:**
Prevent `ReadonlySyntaxHighlightingComponent` for incoming email body.
Doesn't seem worth to try to load the needed css/style elements in the shadow root.
[1] https://github.com/odoo/odoo/commit/8fa3cc31e8b81645d40b5d09c925b57d2c0558ab
opw-6463735
Forward-Port-Of: odoo/odoo#288136
Forward-Port-Of: odoo/odoo#287977Pasted content from one Odoo editor to another now adapts better when the destination editor uses different paragraph formatting rules. This prevents layout and editing issues in areas such as email marketing and website content when content is copied from places like project tasks.
Original PR description
When pasting from an editor whose config allows DIV as paragraphs, like project task, into an editor whose config does not allow it, like mass_mailing or website, those DIVs where inserted as is and did not behave correctly since the editor in which they were pasted did not expect them to exist. This commit checks the incoming DIVs in the pasted content and converts them to P if they would otherwise be candidate for base containers. In theory, Ps should also be converted to DIV if the config allows DIV and not P, but there is no such use case in practice. Forward-Port-Of: odoo/odoo#289891
When Knowledge is turned off for a Helpdesk Team, the related article is now unlinked automatically. This prevents articles from remaining blocked as “in use” and makes any archive or unpublish warning clearer by naming the affected teams.
Original PR description
Before this commit, unchecking the "Knowledge" option on a Helpdesk Team did not remove the link to the associated article. As a result, users could not delete or archive the article later because it was still considered "in use" by the team. This commit ensures: - The linked article is automatically removed from the Helpdesk Team when the "Knowledge" option is disabled. - The validation error message displayed when archiving or unpublishing a linked article is improved to explicitly list the specific Helpdesk Team(s) involved. task-5075527
The AI website builder now avoids starting the same recovery process more than once when the connection service comes online. This prevents random duplicate recovery attempts, making result handling more reliable for users generating website content.
Original PR description
When the bus connects, it would trigger the recoverScraperResults but we may already have have recovery scheduled. This happens randomly, depending on when the bus connects. This commit adds a check on the bus connect call to first check that a recovery is not already happening before calling the recovery. Forward-Port-Of: odoo/enterprise#131732
Financial reports no longer run an extra currency translation calculation when all consolidated companies use the same currency. This avoids needless processing while keeping multi-currency consolidation behavior unchanged.
Original PR description
The condition used to be options['currency_table']['type'] != 'cta'. In monocurrency, the 'currency_table' option key contained 'monocurrency', so the CTA computation always returned an empty result. However, now that the option key has been removed and we use self.currency_translation, some additional check needs to be added in order to avoid uselessly computing CTA when not consolidating companies in different currencies. Forward-Port-Of: odoo/enterprise#132220
The AI website builder now prioritizes Unsplash images when credentials are available, using default images as a fallback. This avoids unnecessary AI image generation unless the user specifically asks for it, reducing delays and costs.
Original PR description
Currently we have an issue where the AI will ignore unsplash credentials because it thinks that it will be able to make better images using the generation. However, this is slow and costly. This commit fixes the prompt to tell the AI precisely what to do i.e. always use unsplash if possible otherwise fall back to default images. If the user specifically asks for ai generated images, then we will prioritise that. task-6591258 Forward-Port-Of: odoo/enterprise#132517
This fixes an issue where users could not validate subcontracted purchase receipts after partially processing them in the Barcode app. The change keeps the related manufacturing order aligned when barcode operations split quantities, preventing validation errors and reducing disruption in receiving workflows.
Original PR description
eproduction steps: - MRP subcontracting + purchase - Subcontracted product with BOM - Create PO with a qty > 1 for this product - Go into barcode - Scan > 0 and < all of the expected quantity - Back…
eproduction steps: - MRP subcontracting + purchase - Subcontracted product with BOM - Create PO with a qty > 1 for this product - Go into barcode - Scan > 0 and < all of the expected quantity - Back out of barcode - Click validate -> Error **OR** Go back into barcode, attempt to validate -> Error Added the StockMove and StockPicking classes to stock_barcode_mrp_subcontracting to extend functions `_subcontracted_produce`, `_clean_merged`, and `split_uncompleted_moves` to use a new context flag, `keep_subcontract_production`. When this flag is set, the move Barcode creates from the split keeps the MO of the move it was split from rather than splitting the MO in two, gives that link up before it is merged away so its cancellation does not cancel the MO, and the MO quantity is resynced with the merged move afterwards. Error thrown here: https://github.com/odoo/odoo/blob/f84eeb3ed1421e0cc07c906ff6444734dc01d35f/addons/mrp_subcontracting/models/stock_move.py#L248 opw-6428928 Forward-Port-Of: odoo/enterprise#131459
The Documents app now keeps the spreadsheet template search bar visible even when no templates match a search. It also prevents a crash when users choose to add a custom filter, making template selection smoother and more dependable.
Original PR description
- templates searchbar disappear when the search has no match - Clicking "Add a custom filter' in the searchbar crashes Task-6526322 Forward-Port-Of: odoo/enterprise#132689 Forward-Port-Of: odoo/enterprise#130096
This fix restores the missing space between the top banner and barcode Kanban cards. It improves readability and keeps the Barcode app layout consistent for warehouse users.
Original PR description
https://github.com/odoo/enterprise/commit/11cd136b2d222fd53dfeb07a611e14d14918009f introduced a margin to prevent Kanban cards from being too close to the top banner. Commit…
https://github.com/odoo/enterprise/commit/11cd136b2d222fd53dfeb07a611e14d14918009f introduced a margin to prevent Kanban cards from being too close to the top banner. Commit https://github.com/odoo/enterprise/commit/c33e82717c4862a32f1feadd9d333f7237c59103 unintentionally removed this margin. This commit restores the missing margin in BarcodeView. | Before | After | |--------|--------| | <img width="1277" height="465" alt="Screenshot 2026-09-22 at 16 25 13" src="https://github.com/user-attachments/assets/9917112b-d503-432f-95f0-aec14033c10d" /> | <img width="1279" height="460" alt="Screenshot 2026-09-22 at 16 24 42" src="https://github.com/user-attachments/assets/80de37dd-500f-45f1-9720-118a6d991836" /> | | <img width="1281" height="610" alt="Screenshot 2026-09-22 at 16 25 15" src="https://github.com/user-attachments/assets/e0c67c37-367b-4bcb-a451-6edbb91e4fd2" /> | <img width="1279" height="559" alt="Screenshot 2026-09-22 at 16 24 51" src="https://github.com/user-attachments/assets/dc550a73-0c33-404c-9d18-8d06d3d2d8f8" /> | Forward-Port-Of: odoo/enterprise#132612
The Belgian payroll employee form no longer shows the same worker status information twice. This reduces confusion for HR users and makes employee records easier to review without changing payroll functionality.
Original PR description
Remove duplicate fields in `hr.employee` form view in belgian payroll module which are `l10n_be_worker_status` and `available_l10n_be_worker_status`. task-6565809 Forward-Port-Of: odoo/enterprise#132586
Updates Vietnam Profit and Loss reporting to follow Circular 99/2025/TT-BTC, including the new investment property gain/loss line and revised line numbering. This helps businesses produce compliant financial statements for fiscal year 2026 while avoiding double-counting in key revenue and cost figures.
Original PR description
Circular 99/2025/TT-BTC (effective FY2026) replaces Circular 200/2014/TT-BTC. The Profit & Loss statement (Mẫu B02-DN) gains a new mandatory line, "Lãi/lỗ của hoạt động bán, thanh lý bất động sản đầu…
Circular 99/2025/TT-BTC (effective FY2026) replaces Circular 200/2014/TT-BTC. The Profit & Loss statement (Mẫu B02-DN) gains a new mandatory line, "Lãi/lỗ của hoạt động bán, thanh lý bất động sản đầu tư" (mã số 21), computed from the new 5117/6327 sub-accounts (see the paired l10n_vn commit). Financial income, financial expenses and the interest memo line shift to mã số 22/23/24 accordingly, the "Net profit from operating activities" formula is updated to include the new line, and all following line numbers/labels are renumbered to match the printed form. The interest memo line itself is renamed from "Chi phí lãi vay" to "Chi phí đi vay" (Borrowing costs), per the gazette text. Also, per revised guidance: - Revenue and cost of goods sold now exclude the new investment property sub-accounts (5117/6327), so those amounts aren't double-counted between the main lines and the new gain/loss line. - Other income is now computed from the "income_other" account type instead of a hardcoded account code, matching how the chart of accounts already classifies it. Both the Balance Sheet and Profit and Loss VN reports also declare an extra "Code" string column (for the printed-form mã số) alongside "Balance". Core's growth-comparison heuristic only turns on the auto growth-% column when there are exactly 2 total columns; with Code+Balance that becomes 4 once a comparison period is added, so the % never renders even though the underlying side-by-side comparison values are fine. account.report exposes filter_growth_comparison as a toggle independent from filter_period_comparison for exactly this case (see Trial Balance and the Deferred reports), so both reports set it to False: period comparison stays available, only the auto growth-% column is suppressed. Task-6518304 Forward-Port-Of: odoo/enterprise#132715 Forward-Port-Of: odoo/enterprise#131085
Non-dashboard spreadsheets, such as documents, now use the intended page background instead of inheriting the navigation bar color. This fixes a visual inconsistency and makes spreadsheet documents easier and more pleasant to view.
Original PR description
The documents (and other non-dashboard spreadsheets) should not have the navbar color as their background color. Forward-Port-Of: odoo/enterprise#132613
This update fixes how Belgian payroll calculates basic salary when an employee has multiple contract versions in the same month. Payroll now applies the 50% rule consistently, reducing the risk of incorrect salary amounts in affected payslips.
Original PR description
there is a problem that we If we have two versions in the same month, we always follow the second option of the 50% rule. This is because the theoretical hours are calculated for the whole month, but the paid amount is calculated separately for each version. We fixed this by checking If unpaid hours > paid hours, salary is calculated by multiplying the hourly rate by the total hours. Otherwise, salary is calculated as the base wage minus (unpaid hours × hourly rate). And return back the test to what exist before the task with id : 6260378 task Id: 6515980 Forward-Port-Of: odoo/enterprise#129985
This pull request mainly tidies and fixes how document records are updated, making future changes safer and easier to maintain. It also includes several payroll, reporting, translation, leave planning, and interface polish fixes that improve reliability and consistency for users.
Original PR description
* 238 lines is just too long. * Prepare adding more writing logic for 6310302. * Remove obsolete archiving methods. Task-6443853
This fix makes field service planning tests use a consistent employee time zone. It prevents demo data settings from changing expected working hours, reducing false test failures and improving release confidence.
Original PR description
Employees created in TestPlanningFieldServiceCommon had no explicit tz, so they inherited the acting user's timezone. With --with-demo that user's tz is Europe/Brussels, shifting the resource calendar's work hours by 1h in January and making test_planning_slot_allocated_hours_on_multiple_resources compute 7 allocated hours instead of the expected 8. runbot-946587 Forward-Port-Of: odoo/enterprise#131570
Settings no longer crashes when a company cannot access certain WhatsApp planning templates. The update only assigns templates to companies that are allowed to use them and treats inaccessible templates as not configured, keeping multi-company settings usable.
Original PR description
Purpose: Settings crashed with an `AccessError` for a company that can't read the planning templates. Specifications: At install, the planning templates get the first WhatsApp account found, which is often allowed for one company only. The post init hook and the field defaults set these templates on every company, so the other companies couldn't read them and Settings raised. The hook now only sets a template on the companies its account allows, and the defaults only set a template without account, since a new company isn't on any account yet. The account of a template can still change later, so Settings shows a template the user can't read as not configured, and the wizard clears it. Forward-Port-Of: odoo/enterprise#131831
Resetting an expense report to draft now also clears Studio approval records for posting journal entries. This prevents old approvals from being reused, ensuring the report must be approved again before it can be posted.
Original PR description
Currently, when resetting to draft an expense sheet, approval steps added with studio are not reset, silently granting the change Steps to reproduce: - In Studio, add an approval rule on the "Post Journal Entries" button on expense sheet - Create an expense report, submit it and approve it - Click "Post Journal Entries" and approve approve it - Open the journal entry and reset it to draft - Back to the expense sheet, reset it to draft too Issue: The "Post Journal Entries" button is still approved, showing the previous approver with the same approval date. Analysis: Approval entries are dropped on state change by a base automation that Studio builds when the rule is created. However it is only done for sale order, account move and purchase order. opw-6530689 Forward-Port-Of: odoo/enterprise#130692
The manufacturing work order preparation action no longer updates the quantity being produced automatically. This prevents unintended quantity changes when preparing manufacturing orders, helping teams keep production quantities accurate.
Original PR description
The prepare MO action sets the producing_qty what shouldn't be the case. Task-id: 6292360
This update corrects missing setup details in several Odoo components that could cause screens or actions to crash after a platform compatibility change. It helps keep affected areas such as Sign, Barcode, VoIP, spreadsheets, accounting reports, AI discussions, and Peru POS invoicing working reliably.
Original PR description
Forward-Port-Of: odoo/enterprise#132379
This fixes how PLM handles files uploaded during a product revision. Newly uploaded files are no longer incorrectly linked back and forth with copied files, so users can still see the expected “New” indicator and attachment history stays clearer.
Original PR description
When a revision is applied in PLM and new files were uploaded, `action_apply` will make a copy of the attachments for the `product.template` then set the origin_attachment_id of the attachments on `mrp.eco` & `product.template` to be the attachment of the other model. This creates a circular relation where an attachment is the origin of another and also originates the same other attachment. While there's no breaking issue, this still doesn't make sense. And this also hides the "New" banner that appears on the uploaded files of a revision when we want to see it (see odoo/enterprise#83278). So when uploading a file for a new revision, there should be no origin_attachment_id since it will be the first appearance of the file. Also removing `test_eco_attachments` because `test_eco_apply_document_without_origin` does the same job. Forward-Port-Of: odoo/enterprise#132583
Users can now provide the intended language for voice transcription in the AI feature. This helps prevent speech from being transcribed in the wrong language, reducing confusing or incorrect results.
Original PR description
Prior to this commit, it was not possible to specify a transcription language. This could lead to glitches when the model would transcribe the user's voice in an improper language. Forward-Port-Of: odoo/enterprise#132534
Manufacturing work order barcode sheets were updated with smaller barcodes and wider spacing to reduce scanning mistakes on the shop floor. The barcode generation setup was also streamlined so future updates can be maintained more consistently.
Original PR description
Shrink barcodes and increase their spacings to avoid mistakes when scanning. Externalize make_sheet function to avoid code duplication. Allow to insert a blank row for more spacing through `blank_middle_column` parameter. Forward-Port-Of: odoo/enterprise#132432
This fix prevents Kenyan eTIMS invoice numbering from moving backwards after certain failed submissions. It reduces the risk of two invoices sharing the same eTIMS number, helping avoid filing mismatches and incorrect receipt details.
Original PR description
Give an eTIMS invoice number back to the sequence only when the failing call is the one that took it, and only when it is still the last one handed out. When sending a customer invoice fails with anything other than a timeout, the number is given back so that it is not consumed for nothing. current issue: - send an invoice, let it time out, so it keeps number N - send other invoices, so the sequence moves past N - send the first one again and let it fail with a non-timeout error - the sequence drops by one and the next invoice sent reuses a number Both documents then sit under the same number. On its next attempt the one that was never accepted finds the other one's filing through selectInvoiceDetails and copies its receipt details. opw-6502563 Forward-Port-Of: odoo/enterprise#131790 Forward-Port-Of: odoo/enterprise#129994
Ecuadorian point-of-sale orders now keep the user's choice when they uncheck "Invoice" during payment. This prevents unwanted invoices from being created and sent to the tax authority after order validation, especially when orders are reloaded through kitchen printer flows or feedback screen navigation.
Original PR description
Steps to reproduce: - Ecuadorian company, PoS with a preparation printer (or use the "Back" button on the feedback screen) - Open a session, add a product, go to the payment screen - Select a…
Steps to reproduce: - Ecuadorian company, PoS with a preparation printer (or use the "Back" button on the feedback screen) - Open a session, add a product, go to the payment screen - Select a customer, uncheck "Invoice", pay in cash and validate Issue: An invoice is created and sent to the SRI although "Invoice" was unchecked. Cause: l10n_ec_edi_pos patches PosOrder.setup() to force to_invoice = true. setup() runs not only on creation but every time the record is reloaded from the server, so the sync done at validation flips the flag back to true in the browser. Since the paid order can now be re-synced after validation (kitchen printer, "Back" on the feedback screen), the server processes it in process_saved_payments, writes to_invoice = True and generates the invoice. Fix: Only apply the Ecuadorian default when the loaded values carry no to_invoice, i.e. for a newly created order. Reloaded records keep the value the user chose. opw-6572987 Forward-Port-Of: odoo/enterprise#131612
The AI website builder now saves custom styling to the correct website and better checks style code before saving. This prevents broken pages and errors when users ask the AI to apply visual changes such as button colors or background images.
Original PR description
[FIX] ai_website: save custom css scoped Before this commit, if you had multiple websites, AI wouldn't save custom css in the correct website's bundles, which caused the following broken flow: - open…
[FIX] ai_website: save custom css scoped
Before this commit, if you had multiple websites, AI wouldn't save
custom css in the correct website's bundles, which caused the following
broken flow:
- open css editor, make any changes, and save it
- open the AI website builder agent and ask it to make all buttons red,
writing a custom css for that
=> you get a traceback, and after reloading your website is broken.
Note that this isn't an issue in 20.0 as this behavior has been changed.
Related to task-6578231
---
[FIX] ai_website: validate custom SCSS with bundle url rewriting
When AI used url($var) in scss, it would break the style compilation and
display an error. This happened because compiling replaced relative urls
with the absolute path. It wasn't caught before saving the custom css,
because we preprocessed css content inline, which doesn't rewrite
relative url()s.
To directly check it, you can just ask it to save this custom css:
`'$img: "a.png"; #test { background: url($img); }'`
=> Style compilation will fail.
Also, this commit updates some already present nested `with` statements
in tests to remove Ruff warnings.
task-6578231
Forward-Port-Of: odoo/enterprise#132463
Forward-Port-Of: odoo/enterprise#131954This fix ensures remaining monthly pay balances are applied to the correct worked day line in Belgian payroll. It improves payroll amount distribution accuracy, especially when multiple worked day entries are present.
Original PR description
For monthly pay, the amount regularization (remaining balance) was incorrectly applied to the worked day line with the maximum hours. It must be applied to the first worked day line instead to ensure proper amount distribution. This commit: - Modifies `_l10n_be_get_paid_work_days` to sort `paid_worked_days` by `code` first, and `number_of_hours` (descending) second. This ensures the correct code is targeted while safely handling multiple lines with the same code. - Updates test assertions to match the newly expected distribution. Task: 6512884 Forward-Port-Of: odoo/enterprise#131884
This fix prevents shared appointment resources from being overbooked when bookings are created from the backend Gantt view. It avoids invalid capacity calculations that could block customers from completing website appointments, improving booking reliability.
Original PR description
**Steps to reproduce:** - Install Appointment app - Create an appointment type based on resources, auto-assigned, with two shareable resources linked together - Set the first resource's capacity to 3…
**Steps to reproduce:**
- Install Appointment app
- Create an appointment type based on resources, auto-assigned, with two shareable resources linked together
- Set the first resource's capacity to 3 and the second resource's capacity to 4
- From the backend Gantt view, create a booking for 2 people on the first resource
- Create a second booking for 2 people on the same resource, at the same date and time
- First resource is now overbooked with reserved capacity of 4 out of 3
- Try to create an appointment from the website
- Error: "The capacity reserved should be positive."
**Issue:**
When bookings are created from the backend gantt view, the selected resource can be overbooked even if another linked resource still has available capacity.
Then when trying to book an appointment the new booking lines will trigger this constraint:
```py
_check_capacity_reserved = models.Constraint(
'CHECK(capacity_reserved >= 0)',
"The capacity reserved should be positive.",
)
```
This is caused by the negative values in:
```py
booking_line_values = []
if appointment_type.schedule_based_on == 'resources':
capacity_to_assign = asked_capacity
for resource in resources:
resource_remaining_capacity = resources_remaining_capacity.get(resource)
new_capacity_reserved = min(resource_remaining_capacity, capacity_to_assign, resource.capacity)
capacity_to_assign -= new_capacity_reserved
booking_line_values.append({
'appointment_resource_id': resource.id,
'capacity_reserved': new_capacity_reserved,
'capacity_used': new_capacity_reserved if resource.shareable and appointment_type.resource_manage_capacity else resource.capacity,
})
```
**Fix:**
Avoid negative remaining value in resource booking when computing available slots.
Note: Tried to take the capacity already used by overlapping bookings into account when assigning resource booking lines from the backend gantt view. And also force linked_resources booking when trying to book more
than the total capacity to properly dispatch as many slots as possible. But it was breaking `appointment_google_reserve` tests.
opw-6503147
Forward-Port-Of: odoo/enterprise#132484
Forward-Port-Of: odoo/enterprise#130520Vendor bill lines now only allow users to choose purchase order lines from confirmed purchase orders. This prevents draft or unconfirmed RFQs from being accidentally linked to bills, improving purchasing and billing accuracy.
Original PR description
Issue Before This Commit: ========================= Currently, the Purchase Order Line field on the vendor bill line allows users to select purchase order lines regardless of the purchase order…
Issue Before This Commit: ========================= Currently, the Purchase Order Line field on the vendor bill line allows users to select purchase order lines regardless of the purchase order state. As a result, lines from purchase orders that are not confirmed can also be selected and linked to vendor bill lines. Steps to Reproduce: =================== - Install Purchase and create an RFQ. - Create a vendor bill for the same vendor. - Add a bill line and enable the Purchase Order column. - Open the dropdown of the Purchase Order Line field. - Observe that lines from unconfirmed purchase orders are available for selection. Cause of the Issue: ==================== This [PR](https://github.com/odoo/odoo/pull/266003) made Purchase Order lines selectable directly on bill lines, but the selection domain did not restrict the lines to confirmed purchase orders. Therefore, lines from unconfirmed purchase orders remained available for selection. After This Commit: ================== Only Purchase Order lines from confirmed purchase orders are selectable on vendor bill lines. Forward-Port-Of: odoo/odoo#288858
This fixes a crash that could occur when creating multiple records from popovers that include translatable fields, such as in calendar views. Translation controls are now hidden where they do not apply, making the popover more reliable for users.
Original PR description
When a translatable field is displayed in the multi create popover (e.g. in a calendar view with a `multi_create_view`), the rendering of the popover crashes when the props are validated (in debug…
When a translatable field is displayed in the multi create popover (e.g. in a calendar view with a `multi_create_view`), the rendering of the popover crashes when the props are validated (in debug mode) with "Invalid component props (TranslationButton)", `resId` being reported as a missing key of the `record` prop. The `TranslationButton` indeed requires a `resId` on the record it receives, which must be `false` when the record doesn't exist yet. The record of the popover is produced by the `Record` component (`@web/model/record`), which forwards its `resId` prop as is to the config of the standalone model. As no `resId` is given for that new record, the datapoint ends up with an `undefined` `resId`, which is considered as a missing prop by the props validation. Normalize the `resId` in the model, such that a mono record config always has a `resId`, which is `false` when the record is new, as the `FormController` and the datapoints created by the lists already do. `_getNextConfig` is the single entry point of every load, so every root datapoint is covered, whatever the caller. The next props are normalized as well in the `Record` component, otherwise each re-render of the parent would trigger a useless reload (`undefined !== false`). 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#289585
Users who join a Discuss channel themselves will no longer receive a misleading push notification saying they were invited. This prevents confusion and keeps invitation alerts reserved for cases where someone is actually added by another user.
Original PR description
Steps to reproduce: -------------------------------------- 1. Install the mail module 2. Allow push notification permissions from the site settings 3. Open Discuss > Go to Channels 4. Click Join on a…
Steps to reproduce: -------------------------------------- 1. Install the mail module 2. Allow push notification permissions from the site settings 3. Open Discuss > Go to Channels 4. Click Join on a channel where the current user is not a member Observation: -------------------------------------- The current user receives a push notification saying: 'User has invited you to this channel.' This is incorrect; the user joined voluntarily. Nobody invited them Issue: -------------------------------------- The commit https://github.com/odoo/odoo/pull/255052/changes/cddd9491c28e9c949efb24d2330c58e35144af12 Adds a push notification when a user is invited to a channel `_add_members` creates the new member and sends a push notification to all newly added members' partner IDs without checking whether a member joined by themselves or was invited by someone else. https://github.com/odoo/odoo/blob/e9cfa0fd65d234bcff8130a2c790cd80ee443595/addons/mail/models/discuss/discuss_channel.py#L830-L853 Interestingly, the bus notification code just a few lines above already makes this distinction using `member.is_self` but the web push block doesn't apply the same filter. https://github.com/odoo/odoo/blob/e9cfa0fd65d234bcff8130a2c790cd80ee443595/addons/mail/models/discuss/discuss_channel.py#L810-L811 Solution: -------------------------------------- Filter out self-joined members from the web push notification recipients. The push notification should only target members who were invited. OPW-6527691 Forward-Port-Of: odoo/odoo#289796 Forward-Port-Of: odoo/odoo#286421
The stock app now correctly loads the information needed for the rescheduling warning popover. This prevents a page crash when users click the warning icon on delivery orders with delayed related receipts, keeping warehouse scheduling workflows usable.
Original PR description
Issue Before this Commit: ===================== Clicking on the rescheduling popover widget on the picking form leads to a page crash. Steps to Reproduce: ===================== 1. Install the `stock`…
Issue Before this Commit: ===================== Clicking on the rescheduling popover widget on the picking form leads to a page crash. Steps to Reproduce: ===================== 1. Install the `stock` module. 2. Create a storable product, then create a delivery order for it 3. Create a receipt for the same product, and `set its Scheduled Date to a date later than the delivery order's Scheduled Date`. 4. Open the Allocation Report from the receipt and assign the received quantity to the delivery order. 5. Open the delivery order and click the Danger icon next to the Scheduled Date. Observe that the page crashes with the following error: `Uncaught Promise > Invalid loop expression: "undefined" is not iterable` Cause of the Issue: ===================== The `late_elements` is not defined in `useProps` of `StockRescheculingPopoverComponent`, even though it was used by the `stock.PopoverStockRescheduling` template. As a result, the template tried to iterate over `undefined`, leading to a page crash. After this Commit: ===================== This commit defines the `late_elements` and `delay_alert_date` in useProps so that the values are correctly available in the component and the rescheduling popover renders without crashing. Forward-Port-Of: odoo/odoo#288895
Fixes an error that could stop payment validation in Point of Sale when settling a sale order for a made-to-order manufactured product. This ensures staff can complete those POS transactions reliably without interruption.
Original PR description
Step to reproduce: ------------------ - Install `pos_sale_stock` and `mrp` module. - Go to the setting enable "Replenish on Order (MTO)" - Create a storable product with the MTO route - Create a Bill…
Step to reproduce:
------------------
- Install `pos_sale_stock` and `mrp` module.
- Go to the setting enable "Replenish on Order (MTO)"
- Create a storable product with the MTO route
- Create a Bill of Materials for the product with a storable component
- Now Create Sale order for the Product and confirm it.
- Open POS Store and settel Created sale order.
- Process toward payment and try to validate it.
Issue:
------
`AssertionError: Invalid falsy real id`
Cause:
------
When an MTO product with a manufacturing Bill of Materials is added to a Sale Order and the SO is confirmed, Odoo creates two distinct sets of stock.move records that share the same stock.reference group:
1. **Delivery moves** (picking_id → stock.picking) Created by the outgoing stock rule triggered by the MTO route. These moves are assigned to a delivery picking and have a valid picking_id.
2. **Manufacturing component moves** (picking_id = False) Created by the Manufacture route's procurement rule, which spawns an mrp.production. The raw-material moves inside an MO belong to the production order, not to any stock.picking. Their picking_id field is intentionally False by design.
Both sets of moves are linked to the same stock.reference record through the stock_reference_move_rel many2many table. This means that traversing:
so_line.move_ids → delivery move(s)
.reference_ids → shared stock.reference
.move_ids → ALL moves in the group (delivery + MRP)
every move in the reference group, including MRP component moves whose picking_id is False.
- Then In PosOrder.sync_from_ui(), the code collected the IDs of all related pickings into a set for later cancellation:
https://github.com/odoo/odoo/blob/a0cdf9c33ed464b4ec8bd520e4d0523afb8dbd28/addons/pos_sale/models/pos_order.py#L111
https://github.com/odoo/odoo/blob/a0cdf9c33ed464b4ec8bd520e4d0523afb8dbd28/addons/pos_sale/models/pos_order.py#L130-L133
waiting_picking_ids.add(move.picking_id.id) # ← adds False for MRP moves
Because MRP moves pass the state filter ('confirmed') but have picking_id = False, `move.picking_id.id` evaluates to False (the empty recordset's falsy id), which was silently added to the waiting_picking_ids set.
Issue occur from this [commit](https://github.com/odoo/odoo/commit/515eb5ba0892a759dde32a9b2923d8ecc1e4bf74?debug=1), the ORM assertion in browse() rejects falsy IDs:
https://github.com/odoo/odoo/blob/a0cdf9c33ed464b4ec8bd520e4d0523afb8dbd28/addons/pos_sale/models/pos_order.py#L139
https://github.com/odoo/odoo/blob/9e02922f821a3b4e891e90bf9bd18448a08e66fa/odoo/orm/models.py#L5297
Fix:
---
Add guards in `sync_from_ui()`
*Inner filtered() guard* — add `m.picking_id` as the first condition so
that MRP component moves (picking_id = False) are never iterated, preventing
`False` from ever entering the set
---
opw-6486681
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#289890
Forward-Port-Of: odoo/odoo#284103The Manufacturing app now uses the same status tag colors across related manufacturing screens. This makes production order statuses easier to recognize and reduces visual inconsistency for users.
Original PR description
Update state tag color to match other mrp models. Task-6574839 Forward-Port-Of: odoo/odoo#289860
This fix prevents an error that could occur when sales order prices are forcibly recalculated. It helps ensure sales teams can update order pricing without interruptions caused by a missing internal price check.
Original PR description
When force price recomputation is done, the manual price check was skipped due to short-circuit evaluation, leaving `manual_price` undefined and causing an `UnboundLocalError`. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289901
This fixes a small display issue in Odoo Studio where an icon style was missing in the selection field dialog. Users should now see the intended icon presentation, improving clarity when editing app menus or fields.
Original PR description
task-6592802 Forward-Port-Of: odoo/enterprise#132610
A date handling issue in the rental planning test was corrected so it uses the proper working timezone. This prevents false test failures during early morning hours and helps keep release validation stable.
Original PR description
**Issue:** `test_payment_renting_product_available` test is failing when executed between 0:00 AM and 2:00 AM in Brussels timezone (UTC+2): ``` AssertionError: datetime.datetime(2026, 6, 22, 16, 0) != FakeDatetime(2026, 6, 21, 16, 0) : The planning slot should begin at the same time as the picking time. ``` In the database the datetime is stored in UTC, which is the previous day for the example above. In `test_payment_renting_product_available` test, the datetime is passed to `datetime.combine()` function that naively uses the date part, which leads to a one-day delta. The datetime should be converted to the working timezone before being passed to `datetime.combine()`. runbot-940435 Forward-Port-Of: odoo/enterprise#131944
This fixes a test setup issue where some assets were only prepared when first needed, causing slow first runs and occasional failures. The change warms up those assets earlier so onboarding tour tests run more consistently.
Original PR description
mass_mailing.assets_inside_builder_iframe and web_studio.studio_assets are only loaded dynamically, so _pregenerate_assets_bundles misses them and the first tour to need them pays a costly cold compile.
This fixes an issue in the website editor where drop areas around the Animated Cover block could overlap, making it harder to add new content nearby. Editors can now place snippets above or below Animated Cover sections more reliably.
Original PR description
Steps to reproduce: - Go to a website page in edit mode. - Drag and drop an "Animated Cover" snippet onto the page. - Try to drag and drop another snippet below it. => The two dropzones overlap. Before this commit, the last dropzone inside the `Animated Cover` snippet overlapped the dropzone used to add a new section below it. After this commit, the first and last dropzones inside the `Animated Cover` snippet are shifted away from adjacent dropzones. task-6588702 Forward-Port-Of: odoo/odoo#289629
Customers who sign in during an active live chat will no longer lose the chat window or chat button. This keeps the conversation available after login, reducing interruptions and failed handoffs during customer support interactions.
Original PR description
Before this commit, a visitor signing in during a live chat session sometimes landed on a page with neither the chat window nor the live chat button, which fails website_livechat.chatbot_continue_after_login_tour on its "Your email is validated, thank you!" step. This happens because the login moves the live chat sessions of the guest to the partner of the user, and unlinking a member tells the bus channel of that member to close the chat window of the channel. The browser that just signed in still listens on the bus channel of its guest, so that order closes the conversation the visitor is taking over. An order arriving before the page restores its chat windows changes nothing, which is why the tour fails only under load. This commit fixes the issue by unlinking the guest members with close_chat_window=False, so that nothing tells the visitor to close the session they keep. https://runbot.odoo.com/odoo/error/947173 Forward-Port-Of: odoo/odoo#289993
Fixes an error that occurred when a user removed all notification options for a follower in the Mail chatter. This lets teams update follower subscriptions without interruption or needing technical support.
Original PR description
Before this commit, when unselecting all message subtypes for another follower would cause a traceback. Steps to reproduce: 1. Add Marc Demo as follower 2 Edit their subscription unselecting all sutypes 3. Click "Apply" -> traceback This happens since [1] moved the `removeRecipient()` call outside of the "some subtypes selected" branch. This causes `thread` inside `removeRecipient` to be undefined when all subtypes are unselected, since in that case we call `follower.remove()`. This commit fixes the issue by checking for the follower existance before updating the recipiency. [1] https://github.com/odoo/odoo/pull/276170 task-6545366 Forward-Port-Of: odoo/odoo#289959
This update replaces an outdated internal testing helper with its current supported equivalent in the website and HTML builder test suites. It helps keep developer tests reliable and aligned with the latest platform standards without changing customer-facing website builder behavior.
Original PR description
Since commit [1] deprecated `patchWithCleanup`, we need to use `patch` instead of it. [1]: https://github.com/odoo/odoo/commit/05ff795907445f0310d0e47fff19d084f034af77
This update replaces an outdated internal testing helper in the AI website module with its supported alternative. It helps keep the module maintainable and aligned with current platform standards without changing customer-facing behavior.
Original PR description
Since commit [1] deprecated `patchWithCleanup`, we need to use `patch` instead of it. [1]: 05ff795907445f0310d0e47fff19d084f034af77