Thursday, August 27, 2026
97 changes · master
Enhancements to existing features
Product pages now include the internal product reference as the SKU in structured data when that reference is available. This helps search engines and other services better identify products, improving catalog clarity without changing the shopping experience.
Original PR description
Include default_code as the Schema.org sku property in the product structured data when it is set. @Tecnativa TT64220 **Description of the issue/feature this PR addresses:** Product structured data does not expose the product internal reference as a SKU. **Current behavior before PR:** The sku property is absent even when default_code is set. **Desired behavior after PR is merged:** The product structured data includes default_code as the Schema.org sku property when available. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284739 Forward-Port-Of: odoo/odoo#282911
This update makes an internal mail test helper more robust when tests are run in parallel. It prevents certain unusual test data from crashing the test suite, improving development reliability without changing user-facing behavior.
Original PR description
If the value needs to be serialized for IPC (cough cough pytest-xdist) and a weirdo sets recordsets as message values, the serialization fails and the test suite crashes. Since this is just subtest identification it shouldn't be too much of an issue. Forward-Port-Of: odoo/odoo#284279 Forward-Port-Of: odoo/odoo#284178
Client-facing wording in the Expenses app has been updated to be easier to understand. This helps users interpret expense-related messages more clearly and reduces confusion in day-to-day expense processing.
Original PR description
Changes some client facing texts to make them clearer. task-6060590
Indian state and union territory data has been centralized so it can be used consistently across Odoo. The update also reflects the merged union territory of Dadra and Nagar Haveli and Daman and Diu, improving accuracy for addresses and localization data.
Original PR description
and merge "Diu & Daman" and "Dadra & Nagar Haveli" as one UT. [Task #6126667](https://www.odoo.com/odoo/project/1251/tasks/6126667)
The search bar was updated so parent screens can manage its focus behavior more directly. This supports smoother interactions in document-related workflows and prepares the interface for broader framework updates without changing everyday functionality.
Original PR description
- enterprise: https://github.com/odoo/enterprise/pull/126864 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Updated customer-facing text in expense-related payroll and Stripe demo screens to make instructions and labels easier to understand. This helps users complete expense and top-up workflows with less confusion, without changing underlying functionality.
Original PR description
*: hr_expense_stripe_demo Changes some client facing texts to make them clearer. task-6060590
The payroll configuration timeline now uses the correct visual styling and responsive behavior. This makes the selected payroll configuration clearer and ensures timeline items collapse properly into dropdowns when space is limited.
Original PR description
The payroll configuration bar is a copy of the employee records one and lost the same styling: its selected version was painted in the grey used on hover, and its items never folded into the dropdowns because the statusbar looks them up by ".o_arrow_button_wrap". Reuse the class the employee records bar now hangs its styling on, and give the items the class the statusbar expects. task-6510183
The appointment date picker now shows unavailable dates, such as weekends or fully booked days, in muted text. This makes scheduling clearer and improves readability for customers selecting an available time.
Original PR description
With this commit, we want to make the date picker more accessible and readable. For this we change a little element in its UI. Now, unavailable dates (for example weekends or fully booked dates) are now muted to better distinguish them from available dates. Task-6429894
The Belgian payroll employee field previously labeled “Relation Start” is now shown as “First Employment Date.” This makes the wording clearer for HR users and better reflects the meaning of the date.
Original PR description
Rename the field `l10n_be_dimona_relation_date_start` string attribute from `Relation Start` to `First Employment Date`. task-6510430
This update tidies up icon styling in several Odoo areas so status bubbles and website buttons appear more consistently. It removes outdated icon rules and fixes a small alignment issue in the website scroll button, improving visual polish without changing functionality.
Original PR description
[IMP] event, maintenance, project: clean up the state bubble scss --- Follow-up of 62bab6a4be6e, which sized the state selection bubbles from the shared bubble variables: a few per-module overrides…
[IMP] event, maintenance, project: clean up the state bubble scss --- Follow-up of 62bab6a4be6e, which sized the state selection bubbles from the shared bubble variables: a few per-module overrides were left behind. __Before commit__ The bubbles kept a negative `margin-top` to compensate their old position, and in project the `hourglass_empty` icon had its own `font-size` and `oi-lg` class, plus per-view `!important` overrides on `font-size`, `margin-top` and `padding-left` for the list view. __After commit__ Icons are sized from the bubble variables (`$o-bubble-color-size-xl`, `$o-bubble-color-size`), so all the per-icon nudges and `!important` rules are gone, along with the `oi-lg` class in the template. <img width="717" height="478" alt="image" src="https://github.com/user-attachments/assets/14ee6f32-53a2-40fe-bb72-c276a3f91330" /> task-6377407 [IMP] web, website: drop leftover font-awesome icon selectors --- Social media, share and scroll down button icons, as well as the webclient icon-only buttons, are now always rendered with `oi` classes. The `fa-stack` / `fa-Nx` / `fa-fw` counterparts in the selectors are dead code, so remove them. task-6377407 [FIX] website: vertically center the scroll down button icon --- __Problem__ Since icons are rendered with `oi` instead of `fa`, the arrow of the scroll down button sits slightly off-center in its round button. __Quick fix__ Force `vertical-align: middle` on the `.oi` pseudo-element. <img width="660" height="143" alt="image" src="https://github.com/user-attachments/assets/354ed891-a6e8-4ef1-b10b-a7e6f15925a3" /> task-6377407
This update makes automatic cursor focus more reliable when fields or buttons are displayed through dialogs or shared page areas. Users should see smoother interactions in places like mail GIF selection and quick-entry forms, with tests adjusted to match the intended behavior.
Original PR description
useAutofocus was built on useLayoutEffect, whose dependencies are recomputed from the render/patch cycle of the component calling it, with an untracked read of the ref so that component doesn't…
useAutofocus was built on useLayoutEffect, whose dependencies are recomputed from the render/patch cycle of the component calling it, with an untracked read of the ref so that component doesn't subscribe to it. When the ref is written by a render that component doesn't own, typically content passed to a <Dialog>'s slot, that cycle never runs and the element is never focused. Rewrite the hook on owl's useOnChange: the dependency is a tracked read of the ref, computed in a signal computation of its own, so the element is focused no matter which render writes the ref, and the component is still never subscribed, as its re-render would reset an input bound with t-att-value (e.g. calendar quick-create title). The callback stays untracked: el.focus() synchronously runs the focus handlers, and the signals they read must not become dependencies of the hook, or any later change to them would steal the focus back. navigation_hook.test.js's BasicHookParent fixture combined useAutofocus on an unrelated button with useNavigation's initial-item activation, relying on onMounted registration order to decide which one ended up with real focus. No real component pairs the two hooks that way, so move that call to "navigation with virtual focus", the only test that exercises the interaction, and where virtual focus never touches real focus.
Folded Kanban columns now display their unfold arrows more neatly and consistently, improving visual alignment with the rest of the column. Related tests were updated to focus on the intended scrolling behavior rather than fragile screen-size-specific values.
Original PR description
[IMP] web: align unfold arrows in folded kanban columns --- __Before commit__ <img width="319" height="266" alt="image"…
[IMP] web: align unfold arrows in folded kanban columns --- __Before commit__ <img width="319" height="266" alt="image" src="https://github.com/user-attachments/assets/8947d533-c1cf-43a4-a6dd-0939bc619102" /> The two arrows of the `o_column_unfold` button were spaced with horizontal paddings on the button and a `margin-right` on `arrow_left`, both swapped on hover to keep the folded column at a constant width. With the new icons, that no longer lines the arrowheads up with the rest of the folded column. __After commit__ <img width="216" height="153" alt="image" src="https://github.com/user-attachments/assets/34fb9c16-223e-4a9f-86ef-0bdad05c9363" /> The button has a fixed width and centers its icons, each clipped to the width of its arrowhead; only the `gap` between them grows on hover. The quick create `Add column` button drops its horizontal padding for the same reason. The unfold-scroll test used to pin the exact `scrollLeft` values that `scrollIntoView` produces on the CI viewport, and those depend on the width of a folded column. It now asserts what the feature actually guarantees: whether a scroll happened, and that the group brought into view ends up flush with the right edge of `.o_content`. Its last case also folds the last group, so that it really exercises the "unfolded group has no next group" branch. task-6377407
The accounting dashboard KPI calculations were cleaned up and covered by an automated test. This should help keep dashboard figures reliable while improving performance for important dashboard views.
Original PR description
* add a test for the function `get_account_dashboard_kpis` * use the ORM to compute the consolidated balances * avoid a `OR` in `_get_open_sale_purchase_query` as it would prevent using efficient indexes, while performance is crucial on the dashboard.
The AI fields area has been simplified by removing older custom patches that are no longer needed. This should make future changes easier to maintain while keeping the user experience stable.
Original PR description
The property definition is now more expandable, then not needed patched has been removed.
The graph view toolbar has been simplified by removing repeated text labels for sorting and chart type controls. Users still get guidance through icons, tooltips, and accessibility labels, keeping the interface cleaner without reducing usability.
Original PR description
Before this commit, the graph view toolbar labelled its sort and chart-type button groups with "Order" and "Type". Both groups already carry an aria-label, and every button a tooltip, so the text only restated what the icons convey. After this commit, the groups rely on icons and tooltips alone. task-6497293 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Indian localization stock demo data now includes a warehouse for the Indian demo company. This makes demos and testing smoother by removing the need for users, developers, or partners to manually create a warehouse when working with Indian e-waybill scenarios.
Original PR description
Following the task-4034713, we used to create warehouse for all company but after this task we only create warehouse for the main company while testing for Indian Demo company considering the ewaybills it's annoying to create a new warehouse for Devs and POs and even for Demos After this commit, we will create demo warehouse for the Indian demo company Task [link](https://www.odoo.com/odoo/project.task/4034713) task-4034713 Forward-Port-Of: odoo/odoo#283797
French localization return reports now display the expected status colors for DAS2 and fiscal declarations. This makes it easier for users to quickly understand the state of each return without changing report content or workflow.
Original PR description
During the development of the das2 report and fiscal declaration, we didn't change the _compute_visible_states to accept the return of those reports. By doing so, we now have colors on the returns. task-6297355 Forward-Port-Of: odoo/enterprise#120417
Appointment booking views now group entries by guest automatically, making it easier for staff to review bookings by customer. This helps teams quickly see each guest's reservations without manually changing the view.
Original PR description
Add default Group By Guest Task-id: 6253719 Forward-Port-Of: odoo/enterprise#118681
The channel kanban view has been adjusted to better match the redesigned web interface. Users should see cleaner spacing, better-aligned cards, and more polished channel images when browsing channels.
Original PR description
This PR fixes the layout of the ungrouped kanban view for channels as it was relying on the margin around each `KanbanRecord` for spacing. As we rely on the gap for the spacing, apply the same approach + add some minor fine-tuning like a `border-radius` on the channel image, spacing between category title and cards task-6488068 follow-up of task-6330603 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update strengthens automated checks so outdated frontend code patterns are caught before they can cause hard-to-find user interface issues. It helps prevent silent failures in areas such as messaging and point of sale by flagging incompatible code during quality checks.
Original PR description
Owl 3's useEffect takes a single callback and calls it with no arguments, but Owl 2 code still parses and runs. `useEffect(fn, () => [deps])` silently drops the dependencies, and `useEffect((el) => ...)` gets undefined parameters - nothing fails until a user walks the path. Add two no-restricted-syntax selectors so eslint catches both on the lint build. They are wrong by construction, so no exceptions are needed, and the useLayoutEffect shim keeps its two arguments under a different callee name. The rules go in test_lint/tests/eslintrc and, for point_of_sale, iot and obox, in web/tooling/_eslintrc.json. The chatter composer patch is the last community call site of that shape. Its body already reads both recipient lists, so dropping the dependency argument is enough; it matches master, so the forward-port is a no-op. Enterprise: https://github.com/odoo/enterprise/pull/128751 Forward-Port-Of: odoo/odoo#283883
Resolved issues and error corrections
The grouped list view once again shows the arrow used to expand and collapse grouped rows. This restores a small but important visual cue that helps users navigate grouped lists confidently.
Original PR description
The grouped list caret was broken during the PR #280964 This commit adds the caret back.
Code cleanup and technical improvements
This update modernizes internal interface code by replacing an older development pattern with newer framework capabilities. It should make future maintenance easier across calendar, messaging, stock, and scheduling areas without changing day-to-day user workflows.
Original PR description
- enterprise: https://github.com/odoo/enterprise/pull/126245 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Documentation and clarification updates
ERPVibe Limited has signed Odoo's Corporate Contributor License Agreement. This formalizes the legal terms for their contributions to Odoo, supporting clearer governance and compliance for future work.
Original PR description
ERPVibe Limited signs the Odoo Corporate Contributor License Agreement v1.0. Forward-Port-Of: odoo/odoo#283477
This change fixes an internal automated test for subscriptions that could fail when run shortly after midnight. It improves confidence in the testing process without changing the product experience for users.
Original PR description
Before this commit, the test could fail with the following error:
```
File "/data/build/enterprise/sale_subscription/tests/test_subscription_controller.py", line 194, in test_automatic_invoice_token
subscription = self._portal_payment_controller_flow()
File "/data/build/enterprise/sale_subscription/tests/test_subscription_controller.py", line 233, in _portal_payment_controller_flow
self.assertEqual(subscription.next_invoice_date, datetime.date.today())
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: datetime.date(2026, 8, 19) != datetime.date(2026, 8, 18)
```
These kind of error could happen when the test was running shortly after midnight.
runbot-946013The mail meeting test flow now closes the camera permission prompt before entering a guest name. This prevents intermittent failures caused by the prompt blocking the name field, improving reliability of automated quality checks without changing user-facing behavior.
Original PR description
Before this commit, discuss.meeting_view_public_tour failed on runbot at the step typing the guest name: "It is not allowed to do action on an element that's below a modal." This happens because the welcome page opens the camera permission dialog as soon as navigator.permissions.query answers "prompt", and that answer comes at no fixed moment. The tour types the name first and closes the dialog only on the next step, so a dialog already open covers the input. This commit closes the dialog before typing the name. https://runbot.odoo.com/odoo/error/946301 Forward-Port-Of: odoo/odoo#284491
This update corrects behavior covered by withholding tax flow tests, helping ensure withholding tax processes remain reliable. It reduces the risk of errors in localized accounting workflows that depend on this module.
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
This update fixes issues in the withholding tax localization area and adds test coverage for related accounting flows. It helps improve reliability for businesses that use withholding tax processes in Odoo.
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
Pending invitation buttons in General Settings now display with clear spacing instead of appearing stuck together. This makes the settings page easier to scan and interact with, especially when several invitations are pending.
Original PR description
Before this commit: the pending invitations buttons in General Settings render as one continuous run of pills touching edge to edge. This commits adds a flex-wrap container with a gap. task-6511840 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Email notifications for tracked changes now display the expected arrow and parentheses in the message body. This makes change summaries easier for recipients to read and understand without affecting the underlying notification behavior.
Original PR description
Bug === When notifying by email a tracking change, the arrow and parenthesis are not rendered in the email body. This commit cleans the fix we did in stable, and move the arrow from the python Markup to the template. Task-6424104
This fixes a duplicated manufacturing label-printing action that accidentally limited access to only one screen. Users can now print labels again from list, kanban, and form views, making the workflow consistent and easier to access.
Original PR description
Before adding the `action_print_labels` server action from [PR](https://github.com/odoo/odoo/pull/163289), the server action with same id and purpose had already been merged in [PR](https://github.com/odoo/odoo/pull/166495). As a result, the action was duplicated. The duplicate definition with `binding_view_types=form` was overriding the original `list,kanban,form` binding and restricting the action to the `form` view only. This commit removes the duplicate `action_print_labels` server action so the label printing flow is available from `list,kanban,form`, consistent with the `stock.picking` server action.
Website snippet links that define their own color style now keep that style instead of being overridden by the surrounding section. This improves visual contrast for elements like the Splash Intro scroll button, making them easier for visitors to see.
Original PR description
Steps to reproduce: - Drag and drop a "Splash Intro" snippet onto the page. - Inspect the scroll button. => The icon uses the `o_cc5` link color from the section. => There is not enough contrast between the arrow and the button background, making the arrow hard to see. Before this commit, color combination link rules still targeted links that were color combination roots themselves. Since [1] added `o_cc5` on the `s_splash_intro` section, its `a:not(.btn)` rule overrode the `o_cc1` scroll button color. After this commit, link color rules skip elements with `o_cc`, so a link using its own color combination keeps its own colors. [1]: https://github.com/odoo/odoo/commit/b7a4edb9fa3d task-6303725 Forward-Port-Of: odoo/odoo#273120
The recruitment job offer page now displays the quick assign button at the same size as the nearby avatar image. This small visual fix improves alignment and gives the page a cleaner, more consistent appearance when a company is linked to the job offer.
Original PR description
Before this PR, the o_quick_assign button was not the same size as the o_avatar img which makes it look like it's misaligned when there is a company associated with the job offer. task-6092395 | Before | After | |--------|--------| | <img width="1058" height="705" alt="Screenshot 2026-04-20 at 15 19 03" src="https://github.com/user-attachments/assets/31b38b78-591d-4c55-b3e8-b3888484f9a1" /> | <img width="1058" height="705" alt="Screenshot 2026-04-20 at 15 29 40" src="https://github.com/user-attachments/assets/6f78190a-be92-4eeb-9a9f-55e8f247bf1c" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283038 Forward-Port-Of: odoo/odoo#260133
The dashboard list now uses each user's existing access rights to decide whether they can create new dashboards. This prevents the create option from being shown to users who should not have it, keeping permissions consistent and clearer.
Original PR description
The attribute to create a new dashboard was set to `true` for every user instead of defaulting to their access rights. Task-6345154
Belgian payroll will no longer show a minimum wage warning when an employee's wage already matches the required threshold. This prevents unnecessary alerts and avoids confusion after using the wage adjustment action.
Original PR description
The minimum wage warning for Belgian payroll was incorrectly triggering when an employee's wage was equal to the required minimum scale threshold. This occurred because floating-point precision issues in `_get_l10n_be_min_wage()` resulted in minute floating-point discrepancies (e.g., `4095.1200000000004`), causing the strict inequality check (`current_wage < min_wage`) to evaluate to `True`. As a consequence, clicking "Adjust Wage" applied the exact minimum wage but left the warning displayed. Fix this by rounding both `current_wage` and `min_wage` according to the wage type precision (2 decimals for monthly wages, 4 for hourly wages) before performing the inequality check. Task: 6488645
This update prevents a point-of-sale appointment page from failing to load due to a widget that relied on a removed component. By excluding the incompatible widget from the appointment assets, the module should load more reliably for users.
Original PR description
Purpose --- The new widget "Many2ManyAttendeeMail" depends on a removed asset in this module, messing the load order of the asset bundle. This commit fixes this by also removing the new widget from the assets. Task-6209447
A subscription pricing helper was moved into the core subscription module so it is always available when product configuration needs it. This prevents potential errors in subscription sales flows, including website-related setups, without changing the user experience.
Original PR description
Moved the function `_get_recurring_pricings` from website_sale_subscription to sale_subscription as it is called in _get_additional_configurator_data but may not be necessarily available. This is safe not only because it is in master but because website_sale_subscription depends on sale_subscription, and the function is kept on `product.template` so it should always be available still.
Point of Sale receipts now include general customer notes that are added to an order but not tied to a specific product line. This restores expected receipt behavior and helps staff and customers see important order instructions on printed tickets.
Original PR description
## Steps to reproduce: - Go to the pos, click a product - Click the product again to unselect the line - Go to the 3 dots -> customer note - Enter a customer note, pay for the order - Try and print the receipt -> The customer note is not displayed ## Why the fix: Since the receipt REF, the general customer note was not displayed on the ticket anymore, but in was in earlier versions. When making a customer note without a selected line, we make a general one, which is not attached to a product line, so it was never displayed. We now display the general customer note if it exists, after having displayed all lines, as we did before 19.2. opw-6483621 Forward-Port-Of: odoo/odoo#284456
The salary offer page now avoids showing a large empty placeholder when no benefits are available. It also removes duplicate action buttons, making the review, feedback, and signing experience clearer for candidates or employees.
Original PR description
This commit fixes the issue of showing a big placeholder in the signing offer page when there was no benefits available, and also fix the duplicated buttons of "Review & Sign" and "Feedback" on the same page. taskid-6486370 Forward-Port-Of: odoo/enterprise#129008
The HTML editor now prevents table merge or unmerge actions from affecting cells in a different table. This avoids accidental changes when users work with multiple tables in the same document.
Original PR description
Steps to reproduce: - Insert two tables in the editor. - Merge cells in the first table. - Select the merged cell in the first table. - Open the table menu for the second table. - Observe that the…
Steps to reproduce: - Insert two tables in the editor. - Merge cells in the first table. - Select the merged cell in the first table. - Open the table menu for the second table. - Observe that the "Unmerge Cells" option is available even though the second table has no merged cells. - Click "Unmerge Cells". - The merged cell in the first table is unexpectedly unmerged. Description of the issue: - The "Unmerge Cells" option is shown for the second table when a merged cell from the first table is selected. - Clicking the option unmerges the selected cell from the first table. Cause: - In `getSelectedCellsMergeInfo`, `canUnmerge` was determined using `td.rowSpan > 1 || td.colSpan > 1` without checking whether the cell belonged to the target table. Solution: - Verify that the selected cells (`td`, `firstCell`, and `lastCell`) belong to the `targetTable` before allowing merge or unmerge operations. - Prevent merge and unmerge operations from being applied to cells in a different table. task-6475293 Forward-Port-Of: odoo/odoo#283222
Invoice document recognition now compares bank account numbers in the same cleaned format used by OCR. This helps the system correctly match supplier IBANs even when saved bank details include spaces, dots, or dashes, reducing manual corrections.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#128264 Forward-Port-Of: odoo/enterprise#127775
This fixes how Odoo identifies extra email or message attachments that are not embedded directly in the message body. It helps ensure attachment lists are consistent and accurate for users viewing messages.
Original PR description
Before this commit, `extra_body_attachment_ids` is declared with `fields.Attr("ir.attachment", { compute() })`, while its compute returns the records of `attachment_ids` that the body does not inline. The model name is therefore the default of an attr field, and only a read inside an update cycle answers that string, as the compute runs on the first read outside one. No reader of the field does that today.
This commit declares the field as the `fields.Many("ir.attachment")` its compute returns, so that the declaration matches the value before the first compute as well as after.
Note that the added test asserts that a message inlining one of its two images lists only the other one, which nothing covered so far. It passes without this change.
Forward-Port-Of: odoo/odoo#284628
Forward-Port-Of: odoo/odoo#284445Automated onboarding tours now handle drag-and-drop steps more reliably, preventing tours from getting stuck during guided setup flows. This improves the reliability of Project and Helpdesk onboarding checks without changing everyday user workflows.
Original PR description
Robot mode (onboarding tours replayed with real actions instead of a human) got stuck on drag&drop steps: - tour_step_interactive.js's findTrigger() returned undefined for a "drag" event when no draggable ancestor was found, instead of falling back to the element itself. - tour_interactive.js's drop conditional only matched the exact pointerup/drop coordinates; clamp the point into the drop target's rect first, since it can land just outside due to rounding. - Reset tour.anchorEl when the pointer target disappears so a stale element isn't reused. Also mark project_tour's synchronization-only steps (waiting for a dirty form, a dropdown, ...) as isActive: ["auto"], since robot mode performs the real action and doesn't need them, and add project_tour and helpdesk_tour to the onboarding tours test coverage.
Corrects a setup error in the Turkish Nilvera e-invoicing module so the zero VAT warning works as intended. This prevents invoice processing errors when the system checks whether a sales invoice should display the zero VAT warning.
Original PR description
The `l10n_tr_zero_vat_warning` field is a boolean field but was incorrectly defined as [binary], causing the compute method to fail when assigning a boolean value. ```py File…
The `l10n_tr_zero_vat_warning` field is a boolean field but was incorrectly defined as [binary], causing the compute method to fail when assigning a boolean value.
```py
File "/home/odoo/src/odoo/saas-19.3/addons/l10n_tr_nilvera_einvoice/models/account_move.py", line 156, in _compute_l10n_tr_l10n_tr_zero_vat_warning
invoice.l10n_tr_zero_vat_warning = exempt_zero_tax and invoice.l10n_tr_gib_invoice_type == 'SATIS' and exempt_zero_tax in invoice.line_ids.tax_ids
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py", line 1892, in __set__
self.write(protected_records, value)
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/fields_binary.py", line 151, in write
super().write(records, value)
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py", line 1583, in write
cache_value = self.convert_to_cache(value, records)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/fields_binary.py", line 83, in convert_to_cache
raise TypeError(f'{self}: use BinaryValue instead of {value.__class__.__name__}')
TypeError: account.move.l10n_tr_zero_vat_warning: use BinaryValue instead of bool
```
upg-4608394
[binary]: https://github.com/odoo/odoo/pull/242043/changes#diff-d3cbb345d0a5855b7d7aa91e64a0ff480e3e5acfa3b2c71503a23ca7f3c0c511R132
Forward-Port-Of: odoo/odoo#284165This fix makes an automated website test wait until the relevant page record is fully selected before deleting it. It reduces random test failures, helping keep website-related quality checks stable without changing user-facing behavior.
Original PR description
Fix the random tour failure by making sure the record is selected before trying to delete it. runbot-944542 Forward-Port-Of: odoo/odoo#280644
Very short timesheet assistant events that are ignored will no longer change the user's active project or task. This prevents small, accidental activity records from influencing future timesheet suggestions and keeps time tracking more accurate.
Original PR description
Before this Commit, small events (<60s) would be ignored but could still set or change the project and task of future events. After this Commit, if an event is small enough to be ignored by the assistant, it is also unable to change the current project or task of the user. For this commit to work correctly, it is expected that each event objects from the assistant has a duration value. task-[6486183](https://www.odoo.com/odoo/project/4105/tasks/6486183) Forward-Port-Of: odoo/enterprise#128700
Deleting multiple email templates at once now works correctly in Field Service Planning. This prevents an error that blocked users from cleaning up templates in bulk, while still protecting the customer ratings template from accidental deletion.
Original PR description
Steps to reproduce: - 1. Install `planning_field_service`. 2. Open Settings > Technical > Email Templates. 3. Select two templates and delete them. Issue: - The deletion crashes with `ValueError: Expected singleton: mail.template(290, 212)`, and several templates can no longer be deleted at once. Cause: - `_unlink_customer_ratings_mail_template` guards the template configured for intervention customer ratings, but it reads `self.id`. An `@api.ondelete` hook is called once with the whole recordset being unlinked, so it raises as soon as more than one template is deleted. Fix: - Look up the configured template id in `self.ids` instead. task-6488394 Forward-Port-Of: odoo/enterprise#128905
This fixes an intermittent failure in an automated test for German POS certification by ensuring the test waits for order synchronization before checking the table badge. It helps keep the validation pipeline stable and reduces false failures that can delay releases.
Original PR description
Sometimes, `test_fiskaly_basic_order` test fails with the following error: ``` AssertionError: FAILED: [55/68] Tour FiskalyTour -> Step body:has(.pos-leftheader .badge:contains(5)). Element (body:has(.pos-leftheader .badge:contains(5))) has not been found. ``` `FloorScreen.clickTable()` clicks on the table and waits for a badge to appear. The badge is rendered once the table order is synced to the server. If the order is still syncing when the click on the table lands, the badge will not be present and triggers the failure. runbot-940256 Forward-Port-Of: odoo/enterprise#128998
The message interface styling was simplified by removing an expensive visual rule that offered little visible benefit. This should help keep the mail experience responsive while preserving the overall look for users.
Original PR description
This PR cleans up a complex selector that is quite costly without providing any striking visual value. task-6481656 Forward-Port-Of: odoo/enterprise#128906
The website builder now shows custom gradient buttons without a border when the border is set to zero. This prevents editors from seeing a misleading preview and helps ensure the editing experience matches the final website result.
Original PR description
Steps to reproduce: 1. Create a button 2. Choose "custom" in type 3. Put a gradient for Fill option 4. Remove border (put 0) Problem: Since [this commit][1] support has been added to preview custom…
Steps to reproduce: 1. Create a button 2. Choose "custom" in type 3. Put a gradient for Fill option 4. Remove border (put 0) Problem: Since [this commit][1] support has been added to preview custom buttons with gradient backgrounds in the website builder. However, if a user sets the border to 0px it a false border is shown. This is inconsistent the changes that will be applied to the button on the website. The cause is how the preview border is set. In the same [commit][1], borders are previewed at 2px regardless of their actual size. This works for solid background buttons but causes a gradient pseudo-border to appear with custom gradient buttons. Solution: The solution is to set the preview button's border-width styling to 0px in the case when the border is being changed and its width is set to 0. This styling does not affect the classes applied to the actual button being edited and is removed if the border thickness is changed again. [1]: https://github.com/odoo/odoo/commit/291a77c50f19622f8083a5e3798c17b49f3b1c7e task-6296905 Forward-Port-Of: odoo/odoo#279165
The overtime rules screen now shows the related employee versions button only to HR managers. This prevents HR officers from seeing an access-rights error when opening overtime rule records, improving reliability during normal use and upgrades.
Original PR description
The button requires the group `hr.group_hr_user`, but the button uses `versions_count`, that in its computation uses fields like `contract_date_start` that require the group `hr.group_hr_manager`. To avoid the mismatch, the button is restricted to only managers. This error was found in upgrades failing. To reproduce: - Install `hr_attendance`. - Assign any employee the Default Ruleset to make the button not invisible. - Change the HR security of your user to Officer. - Go to Attendance->Configuration->Overtime Rulesets and try to see the record. - A message will display the following error: ``` You do not have enough rights to access the field "contract_date_start" on Employee Record (hr.version). Please contact your system administrator. Operation: read User: 2 Groups: allowed for groups 'Employees / Administrator' ``` Forward-Port-Of: odoo/odoo#284194
Email notifications for tracked record changes now correctly display the arrows and parentheses that show what changed. This makes update emails clearer for users while preserving how older messages are displayed.
Original PR description
Bug === When notifying by email a tracking change, the arrow and parentheses are not rendered in the email body. Technical and Constraints ========================= The class `o_track` is only set in…
Bug === When notifying by email a tracking change, the arrow and parentheses are not rendered in the email body. Technical and Constraints ========================= The class `o_track` is only set in the web client template (`mail.Message`). There's no class in the body of the email that is sent. It can be rendered with "notification templates" that we cannot change either (and they just do `t-out="message.body"`, so the body field of the mail message has to be properly rendered). We also need existing mail messages to be rendered correctly, and so we need a way to differentiate mail messages created before the fix from those created after it, to know when to disable the arrow and parentheses. Alternatives ============ We have tough about many solutions, this one is the best we found based on the constraints we have 1. Add a class in 19.3, use that class to not remove the arrow on previous mail message. That solution required a migration script that will change all tracking messages. Because the initial migration of the tracking was really slow, we wanted to avoid that. 2. Add a class, and keep it forever. But that solution makes the body of the mail messages bigger, which defeat one of the purpose of the initial refactoring 3. Change the outgoing email without changing the body of the mail message. That solution was really not reliable (regex change to add the arrow, and we have no clean way to target the tracking rows) 4. During the migration create a system parameter with the date, and compare with the create_date of the mail message to know if we should add the arrows or not (but we will need to keep that system parameter forever, and the code to support both to) Task-6424104 Forward-Port-Of: odoo/odoo#282210
This fixes an internal test issue in the website shop area by making sure inactive products are excluded during test runs. It helps keep automated quality checks stable without changing what customers see in the online store.
Original PR description
Description of the issue/feature this PR addresses: Addresses an issue causing test failures by ensuring that [inactive products](https://github.com/odoo-dev/odoo/blob/dbc917ddc263a330ff70f5edec716ccafe88d7a6/addons/website_sale/tests/test_product_filters.py#L93-L99) are filtered out rather than leaking from the environment into the test execution. I have verified that this issue does not allow [inactive records to leak to customers](https://www.odoo.com/mail/message/1151343506). runbot-242426 Forward-Port-Of: odoo/odoo#284326 Forward-Port-Of: odoo/odoo#283973
Fixes a printing issue where customized sale order PDFs could show an unwanted blank column after a column such as Taxes or Discount was removed in Studio. This keeps section and combo rows aligned correctly, improving the appearance of customer-facing sales documents.
Original PR description
**Steps to reproduce:** 1. Open a Sale Order report in Studio 2. Delete the Taxes column 3. Save 4. Create a sale order with at least one section line and products that have taxes 5. Print the sale…
**Steps to reproduce:** 1. Open a Sale Order report in Studio 2. Delete the Taxes column 3. Save 4. Create a sale order with at least one section line and products that have taxes 5. Print the sale order PDF **Issue:** - A blank column is rendered in the PDF report on section (and combo) rows whenever a column such as Taxes or Discount is removed via Studio. **Why this happens:** - The section row's `colspan` and the combo row's `colspan` were computed using `3 + (1 if display_discount else 0) + (1 if display_taxes else 0)`. - `display_taxes` and `display_discount` are derived from order data (i.e. whether any line has taxes/discounts), not from which columns are actually rendered in the table. - When Studio removes a column it deletes the `<th>` and matching `<td>` elements via XPath, but these Python variables remain `True`. As a result, section/combo rows still accounted for the removed column in their `colspan`, producing one extra cell and a visible blank column. **Fix:** - Introduce a `colspan_count` variable which is incremented inside each `<th>` body - Use that counter for `td_section_name` and `td_combo_name` instead of the previous formula. - Because the increment occurs inside the `<th>` element, it is skipped whenever the element is not rendered, whether because `display_taxes`/`display_discount` is `False` or because Studio's XPath removed the element entirely. opw-6433679 Forward-Port-Of: odoo/odoo#283657 Forward-Port-Of: odoo/odoo#280719
The Point of Sale now automatically chooses a product option when it is the only available choice, as long as the option type is not multi-select. This removes an unnecessary step for cashiers and helps products with simple variants be added to an order smoothly.
Original PR description
Before this commit: ----------- - When a product attribute had only one available value, it was not automatically selected for display types other than multi. After this commit: ------------ - Automatically select the attribute value when an attribute has a single available value and its display type is not multi, allowing the product to be added without any additional user interaction. Task-6327371 Forward-Port-Of: odoo/odoo#282350 Forward-Port-Of: odoo/odoo#272437
The mail thread data request now returns only the information that is actually needed for the current user and conversation. This reduces unnecessary data handling and helps keep mail-related views more consistent across access scenarios, including multi-company cases.
Original PR description
This change cleans up the requested data from `/mail/thread/data` route, ensuring it aligns with what is actually needed depending on the user and thread. part of task-6452761 Forward-Port-Of: odoo/odoo#284452 Forward-Port-Of: odoo/odoo#280713
This fixes an intermittent issue in the Lunch app's automated order check by ensuring the test waits for the intended product to appear after changing location. It helps avoid false failures caused by outdated demo products still showing briefly, improving confidence in release testing without changing user-facing behavior.
Original PR description
The lunch order tour selects `Farm 1` before ordering a product. However, it only waits for the location input to be updated before clicking the first kanban record. With demo data installed, a product from the previous location can still be displayed while the product model is being reloaded. The tour can therefore order a demo product instead of the product created by the test. This notably fails during weekends when the corresponding demo vendor is unavailable. To fix we need to wait for the product created by the test before clicking it. Besides selecting the intended product, this also ensures that the product reload following the location change has completed. [error-181572 ](https://runbot.odoo.com/odoo/error/181572) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284626 Forward-Port-Of: odoo/odoo#281753
Chat windows now keep their usual display priority by default while allowing other parts of Odoo to adjust how they appear on top of screens when needed. This prevents layout conflicts on mobile views and makes future customizations safer without disrupting existing behavior.
Original PR description
The z-index of chat windows on mobile views was previously fixed at `1020`, preventing other modules from adjusting their stacking order. This commit introduces a configurable z-index for chat windows, defaulting to `1020` while allowing other modules to override it when needed. task-6412411 Forward-Port-Of: odoo/odoo#283671 Forward-Port-Of: odoo/odoo#283178
Contacts now validate tax numbers using the country set on the partner record instead of guessing from the first two characters of the tax number. This prevents valid Mexican RFCs and similar identifiers from being incorrectly treated as foreign VAT numbers, reducing false validation errors when saving contacts.
Original PR description
**Issue**: If a partner has a tax number that begins with a different country’s code (for instance, a Mexican RFC number that begins with “RO”, matching Romania), when a user tries to add the tax…
**Issue**: If a partner has a tax number that begins with a different country’s code (for instance, a Mexican RFC number that begins with “RO”, matching Romania), when a user tries to add the tax number to the partner, there will be a validation error.
**Steps to reproduce** (on fresh database with Contacts app and l10n_mx module installed):
1. Make a new contact.
2. Give the contact a Mexican address.
3. Give the contact the RFC number (or `vat` field): ROS561231GR8.
4. Try to save this change. Observe the validation error.
**Explanation**:
The `get_all_identifiers` method uses the first two characters of `partner.vat` as a heuristic to detect the issuing country, since many VAT formats start with a country code (e.g. RO1234567897). This prefix was used unconditionally whenever it matched an item from `get_tin_metadata_of_country`. without checking whether the VAT actually belongs to that country. Some countries' identifier formats begin with letters which are not country codes. In Mexico, for instance, RFC numbers start with letters derived from the partner's name, so a partner named “Sofia Rodriguez” would get an RFC starting with “RO”. Therefore, this heuristic can produce false-positive matches against unrelated countries.
**Solution**:
We no longer use a partner's vat number to detect the issuing country. Instead, we use the partner's `country_code` field as the issuing country.
opw-6471006
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283376This update makes an error message clearer when sending a credit note through French e-invoicing in demo mode. Users should better understand what went wrong during EDI document generation, reducing confusion and support effort.
Original PR description
Steps to reproduce: - Install `l10n_fr_pdp` module > Switch to `FR Company` - Activate `French e-invoicing` (Demo mode) - Create a New `Credit Note` with `FR Customer` > Send Issue: The system currently displays a confusing error message during EDI document generation. We are making the error message clearer and more user-friendly. opw-6412521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284189
Sales quotation and pro forma email templates now use separate complete sentences for quotations and orders. This lets translators adapt grammar correctly in languages where the words require different articles or adjective forms, improving customer-facing email quality.
Original PR description
The quotation and pro forma email templates inserted either "quotation" or "order" into shared translatable text. In French, for example, "devis" is masculine while "commande" is feminine, so the surrounding articles and adjectives cannot agree with both terms. Define a complete sentence for each document state so translators can translate the surrounding grammar independently. opw-6445304 Forward-Port-Of: odoo/odoo#284596 Forward-Port-Of: odoo/odoo#283229
A small configuration error meant two important accounting report records were not individually protected from deletion as intended. This fix corrects the list so both reports remain safely protected, reducing the risk of accidental removal.
Original PR description
On `ir.actions.report` we want to block the unlinking of specific reports in odoo. However, when the list was created a comma was missed between `action_account_original_vendor_bill` and `account_invoice_without_payment` which means we were actually protecting against people unlinking `action_account_original_vendor_billaccount_invoice_without_payment`. Adding in that comma will allow these two records to be properly protected. task-none Forward-Port-Of: odoo/odoo#283323
When multiple projects are duplicated at the same time, each copied project now receives only the milestones from its original project. This prevents copied projects from being cluttered with unrelated milestones from other selected projects, keeping project plans accurate.
Original PR description
Before this commit, duplicating several projects at once from the list view gave every copy the milestones of all the duplicated projects, because the copy loop assigned the milestones of the whole recordset instead of the ones of the project being copied. Duplicating a single project behaves correctly, which hid the issue. Steps to reproduce: - create two projects with milestones enabled, add a milestone to the first one and two others to the second one - select both projects in the list view and duplicate them Each copy contains the three milestones instead of only the milestones of its original project. Solution: Copy the milestones of the project being duplicated. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278520
Peruvian accounting reports now use the exchange rate already stored on each accounting entry instead of recalculating it during report generation. This reduces rounding discrepancies and helps businesses get more reliable report figures.
Original PR description
Previously, the `_get_ple_report_data` method computed the currency rate when called. Since the calculation was based on the entry totals, it was prone to rounding errors. This PR makes it use the rate stored in the entry itself. This should lead to more accurate results. opw-6411322 Forward-Port-Of: odoo/enterprise#128027 Forward-Port-Of: odoo/enterprise#126882
This update adjusts an internal automated test related to mobile mail notifications so it continues to match recent template tracking behavior. It helps keep quality checks reliable without changing the product experience for users.
Original PR description
Task-6424104 Forward-Port-Of: odoo/enterprise#127778
The French VAT report submission now treats notes containing only spaces as empty. This prevents incomplete files from being sent to ASPOne and avoids avoidable submission errors for users.
Original PR description
While sending the tax return to ASPOne, before adding the BC zone we are checking that BA zone won't be empty as if BC is completed there must be the BA zone in the xml file. The problem is that when we have only whitespaces, the condition will be respected but later on due to cleanup_xml_node(), the BA zone will not be rendered in the xml but BC will and it leads to an error This commit checks that express_mention_reason fields is not empty or not only whitespaces task-6476440 Forward-Port-Of: odoo/enterprise#128242
AI chat windows now appear in front of other chats and fullscreen editing screens on mobile. This prevents AI assistance and related popups from being hidden, making the feature usable in those views.
Original PR description
AI chats opened on mobile views could appear behind other chats. This was inconsistent with the expected stacking behavior, where newly opened chats should appear on top of existing ones. To reproduce: * Open the chatter of any module. * Open the message composer in fullscreen mode. * Click the AI button. This commit increases the z-index of AI chats on mobile views so they are displayed on top of other chats. task-6412411 Forward-Port-Of: odoo/enterprise#128649 Forward-Port-Of: odoo/enterprise#128346
Appointment invitation emails can now generate public calendar links without running into permission errors. This helps ensure invitees receive working calendar links and reduces failures when sending appointment-related emails.
Original PR description
Since calendar attendee access tokens are restricted to system users, appointment mail templates must sudo token reads when generating public calendar links. This follows the same pattern as the calendar mail templates and avoids an AccessError when rendering attendee invitation emails. ref: https://github.com/odoo/enterprise/commit/88a3cca752a5f726cd0260b485fc93f65a268cf8 Forward-Port-Of: odoo/enterprise#128959
Users can now open links included in spreadsheet cell comments with a normal click, as expected. This removes a frustrating interaction issue and makes shared references in comments easier to access.
Original PR description
Current behavior before PR: - Clicking a link in a cell comment did not work. A left click was blocked, while Ctrl+click (or Cmd+click) opened the link in a new tab. - This was caused by `t-on-click.prevent` on the comment thread and popover. It was originally added because the scroller service used the URL hash to scroll to anchors, which was removed in https://github.com/odoo/odoo/commit/711e9c9f24818714129f55283e2df64503d93605 Desired behavior after PR is merged: - `t-on-click.prevent` is removed and links in cell comments can be opened normally with both left click and Ctrl+click (Cmd+click on macOS). Task: [6448651](https://www.odoo.com/odoo/project/2328/tasks/6448651) Forward-Port-Of: odoo/enterprise#129188 Forward-Port-Of: odoo/enterprise#127473
A bug was fixed so planning sessions linked to quotations only use real sale order lines, not section or note rows from quotation templates. This prevents errors in a specific Field Service planning flow and helps keep quotation-to-planning links accurate.
Original PR description
This commit patches a niche bug involving creating a quotation via a quotation template containing a line section, then connecting it to an active planning session. The current architecture did not filter out `line_section` or `line_note` typed lines. This updated search domain resolves this issue. opw-6351484 Forward-Port-Of: odoo/enterprise#129228 Forward-Port-Of: odoo/enterprise#125056
Opening the sales product configurator in debug mode no longer fails when a product has an empty custom attribute value. This keeps sales order editing reliable for configurable products and avoids interruptions for users or testers working with debug mode enabled.
Original PR description
This commit prevents a traceback when opening the product configurator in debug mode. Prop validation only happens in debug mode, which exposed an issue with products that allow entering custom attribute values (e.g. Acoustic Bloc Screen). When a custom value is left empty, it is read as `false` when custom attributes are retrieved from the frontend. As a result, the `custom_value` key in the `customPtavs` prop passed to the product configurator contains a boolean, whereas the prop expects a string. This commit ensures that an empty string is passed instead of `false` when opening the configurator for a line with an empty custom attribute value. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284482
This fixes how product names and descriptions appear in accounting line descriptions when space is limited. Product names will no longer be mistakenly shown in italic after wrapping, making accounting entries easier to read.
Original PR description
This commit removes the CSS hack used to make the description italic when a product is present in an AML. Instead, the product name and description are rendered separately using two spans in the readonly state. The previous `:first-line` approach did not handle line wrapping correctly: when the column was too narrow, part of the product name could wrap onto the next line and incorrectly appear italic. Rendering the two parts separately avoids this issue. Before | After -- | -- <img width="414" height="192" alt="image" src="https://github.com/user-attachments/assets/a178a35c-6d55-4982-a9c3-2fe727c626cc" /> | <img width="399" height="198" alt="image" src="https://github.com/user-attachments/assets/4716f93a-6d47-4631-a982-db43d9d38ef0" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284232
This change makes an internal website editor test more reliable by waiting for the interface to finish updating before checking popup visibility. It helps reduce random CI failures, improving development stability without changing behavior for end users.
Original PR description
The test `undoing something on a target outside s_popup closes it` had a few fails in CI: the `fa-eye-slash` was not set as expected. This commit adds a `waitSidebarUpdated` call just before to ensure owl has no pending rendering when checking the eye. The fix is similar to aaf0f54d1feda60becb0bfbad578b366715c0172 which is about a similar failure in another test. runbot-938967 Forward-Port-Of: odoo/odoo#284381
This fix adjusts restaurant appointment point-of-sale tests so they continue to work after POS data reloads clear browser storage. It keeps the production behavior unchanged while preventing test failures and improving confidence in future updates.
Original PR description
A recent PR in the community repository introduced a full clear of both `localStorage` and `sessionStorage` when reloading POS data. While this is the intended behavior in production, it breaks the test framework. This commit mocks the `clear` methods directly within the tour steps right before the reload action. This ensures the test survives the page reload and keeps its state, without polluting the core production code with test-specific logic. task-6456447 Forward-Port-Of: odoo/enterprise#129010 Forward-Port-Of: odoo/enterprise#128091
This fix prevents a manufacturing test cleanup from accidentally touching stock rules outside the intended route. It reduces the risk of test failures caused by unrelated demo or company data being removed while keeping the change internal to test behavior.
Original PR description
`test_check_update_qty_mto_chain` was removing `stock.rule` records from other companies using `mto_route.rule_ids.search()`. Calling `search()` on a recordset does not restrict the search to the records already present in that recordset, so the domain was effectively applied to all `stock.rule` records. With demo data, this could attempt to unlink an unrelated stock rule that is still referenced by an existing stock move, causing a `stock_move_rule_id_fkey` foreign key violation. This commit restricts the search explicitly to rules belonging to `mto_route` before unlinking them. [error-940031 ](https://runbot.odoo.com/odoo/error/940031) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282930
This fixes an issue where archiving or deleting one user could wrongly remove a shared contact from restricted discussion channels, even if another active user for that contact still had access. Contacts are now only unsubscribed when none of their remaining users qualifies for the channel, helping teams avoid accidental loss of communication access.
Original PR description
Before this commit, archiving or deleting a user removed its partner from every group restricted channel, even when another user of that partner was still active and in the group the channel requires. This happens because the members to unsubscribe are searched on partner_id alone, so the search cannot tell whether the partner keeps another user. This commit fixes the issue by unsubscribing a partner only when none of its remaining users has the group the channel requires. Forward-Port-Of: odoo/odoo#284354 Forward-Port-Of: odoo/odoo#283807
UPS shipping rate checks now follow UPS documentation by allowing phone numbers between 1 and 15 digits. This prevents valid customers in countries with shorter phone numbers, such as Luxembourg, from being blocked when requesting UPS shipping rates.
Original PR description
**Steps to reproduce:** - Create a contact with a phone number that has 9 characters - Setup an UPS carrier, a configuration that works is UPS Saver as Service Type and UPS Package/customer supplied…
**Steps to reproduce:** - Create a contact with a phone number that has 9 characters - Setup an UPS carrier, a configuration that works is UPS Saver as Service Type and UPS Package/customer supplied as a package type - Create a quotation, put the created contact as a client - Try adding a shipping and getting the rates - An User Error appears, the phone number is too short **Why the fix:** Before this commit, any phone number that was less than 10 characters would raise an User Error, but some countries, such as Luxembourg, use phone numbers that are nine characters long or even less. If we check the official UPS documentation (https://developer.ups.com/tag/Shipping?loc=en_EN#operation/Shipment), we can see in the Ship_to/Phone section, that the phone number should be a number between 1 and 15, not saying it should be 10 characters or more. <img width="495" height="473" alt="image" src="https://github.com/user-attachments/assets/fed82987-ffb8-4b84-b282-6c3d3b4f304e" /> After this commit, we adapt the way we prevent the user from inputing phone numbers to fit the official UPS documentation. opw-6307577 Forward-Port-Of: odoo/enterprise#128632 Forward-Port-Of: odoo/enterprise#122831
The German tax report XML now preserves cents for the Kz83 amount instead of rounding it down to a whole number. This helps ensure reported tax values remain accurate, for example keeping 26.40 as 26.40 rather than 26.00.
Original PR description
Description of the issue this commit addresses: The German tax report XML casts Kz83 to an integer before formatting it. This truncates decimal values, causing amounts such as 26.40 to become 26.00. --- Desired behavior after this commit is merged: This commit preserves the Kz83 decimal value and formats it with two decimal places in the German tax report XML. --- task-6414439 Forward-Port-Of: odoo/enterprise#125607
Employees and managers can now mark multiple appraisals as done from the list view without encountering an error. The completion notification is now handled separately for each appraisal, making the batch action reliable.
Original PR description
Steps to reproduce: - select multiple appraisals and try to mark as done from list view. Issue: - The completion notification uses an appraisal variable assigned by a previous loop, raising an UnboundLocalError. Furthermore, message_notify() requires a singleton. Fix: - notify and post the completion message for each appraisal explicitly. task-6479018 Forward-Port-Of: odoo/enterprise#128207
Odoo now correctly excludes temporary wizard screens from reference selections used by sales and marketing tracking. This prevents irrelevant internal options from appearing to users and keeps selections cleaner and less error-prone.
Original PR description
Various places mistakenly used `model.is_transient()` to filter the transient models, where the model is `ir.model` record itself, which always returns False since `ir.model` is a regular persistent model. As a result, transient models (wizards) were never filtered out and allowed into the `utm_reference` Reference field selection. This commit fixes it by using `self.env[model.model].is_transient()` to call `is_transient` on the actual model. Task-6458883 Forward-Port-Of: odoo/odoo#283824 Forward-Port-Of: odoo/odoo#282711
The accounting dashboard now shows the full invoice or bill amount for documents marked "To Check," instead of only the remaining unpaid balance. This avoids understating the value of documents that still need review after partial payments.
Original PR description
Currently, the "To Check" links on the dashboard display the residual amount of invoices and bills. Since the entire document needs to be checked regardless of partial payments, showing the remaining balance is misleading. This commit updates the `selects` list in `_get_to_check_payment_query` to use `amount_total` instead of `amount_residual`, ensuring the dashboard reflects the full value of the documents. Task-6478415 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284171
Employees who dismiss the attendance location warning will now see the pop-up close as expected. This prevents confusion when location access is blocked and users choose not to continue with check-in or check-out.
Original PR description
Steps to reproduce: -------------------------------------------- 1. Install Attendance module. 2. Enable `Device & Location Tracking` & `Attendance from Backend` in settings. 3. Block location access…
Steps to reproduce: -------------------------------------------- 1. Install Attendance module. 2. Enable `Device & Location Tracking` & `Attendance from Backend` in settings. 3. Block location access from the browser for this site (Site settings) 4. Try to checkIn/checkOut from the Dot in the systray 5. We'll have one confirmation pop-up asking to Proceed Anyway OR Discard Observation: -------------------------------------------- On clicking the discard button, Nothing happens. Issue: -------------------------------------------- In `confirmChecking()`, the `cancel` callback was defined as an arrow function using an expression body. In JavaScript, an assignment expression returns the assigned value. Since `this._attendanceInProgress` is set to `false`, the callback implicitly returns `false`. `ConfirmationDialog.execButton()` treats a `false` return value as a signal to keep the dialog open (used intentionally to block closing on validation failure) This caused the dialog to never call `this.props.close()`, leaving it permanently open when Discard was clicked. https://github.com/odoo/odoo/blob/5e84fdd99e34836a15cadc4fdf4b6bc449727e58/addons/web/static/src/core/confirmation_dialog/confirmation_dialog.js#L75-L89 Solution: -------------------------------------------- Change the `cancel` callback from an expression body to a block body, A block body arrow function returns `undefined` by default. This ensures `execButton` does not interpret the return value as a 'keep dialog open' signal, and correctly calls `this.props.close()` to dismiss the dialog. opw-6462439 Forward-Port-Of: odoo/odoo#284093 Forward-Port-Of: odoo/odoo#281702
API documentation pages now display bullet points and lists with proper styling. This makes generated documentation easier to read and helps users understand reference information more clearly.
Original PR description
Bullet points and lists coming from the generated html by docutils were not properly styled. This commit fixes those cases. task-6484990 Forward-Port-Of: odoo/odoo#283835
This change updates internal subscription-related tests so they stay aligned with recent changes in the related Odoo codebase. It helps maintain confidence that subscription flows continue to work as expected, without changing customer-facing functionality.
Original PR description
See also: - https://github.com/odoo/odoo/pull/280403 Forward-Port-Of: odoo/enterprise#128610 Forward-Port-Of: odoo/enterprise#127041
The timesheet timer now excludes archived projects from its project dropdown, even when those projects were used in past timesheets. This prevents users from accidentally selecting inactive projects and keeps time tracking choices aligned with current project availability.
Original PR description
Steps to reproduce: ---------------------------------- 1. Install the `timesheet_grid` module. 2. Create a project and add any timesheet to it. 3. Archive the project. 5. From the systray timer,…
Steps to reproduce:
----------------------------------
1. Install the `timesheet_grid` module.
2. Create a project and add any timesheet to it.
3. Archive the project.
5. From the systray timer, click on the Project field.
Observation:
----------------------------------
The archived project is visible in the dropdown.
Issue:
----------------------------------
In Odoo, standard search views and `name_search` calls on `project.project` automatically respect `active_test=True`. When you open the timer, the frontend passes `{'timesheet_timer_search': True}` in the context to `name_search` with an empty query string. `name_search` overrides standard searching to retrieve recently used projects first by querying `account.analytic.line` via `_get_recently_used_records ('project_id', ...)`. `account.analytic.line` stores past timesheet logs. Even after a project is archived, historical timesheet records for that project still exist in `account.analytic.line`. Because `_get_recently_used_records` runs a `_read_group` query on `account.analytic.line` (which has no active field of its own), it fetched the `project_id` from historical timesheet entries without checking if the referenced project was active.
Solution:
----------------------------------
In `name_search`, explicitly append `[('active', '=', True)]` to the `project_domain` used when querying `_get_recently_used_records`. Standard form/list views using `_domain_project_id` already benefit from Odoo's default ORM `active_test=True` mechanism during standard `project.project` searches.
Note:
----------------------------------
Another solution was to add `active = true` in `getTimesheetTimerFieldInfo` https://github.com/odoo/enterprise/blob/22eb84cdc94ba334d42bad32fb491d35c8147c94/timesheet_grid/static/src/services/static_timesheet_timer_service.js#L322-L328
Fixing it in Python ensures that any call passing `timesheet_timer_search` in context (e.g. mobile widgets, custom RPCs, or python wizards) will benefit from the fix, rather than only patching a single OWL JS service.
opw-6445528
Forward-Port-Of: odoo/enterprise#127374A payroll-related test now uses the correct wage value depending on how employee pay is stored. This helps prevent false test failures and keeps pay gap reporting checks reliable across payroll configurations.
Original PR description
Without `hr_payroll`, the contract wage is stored in `wage`. With `hr_payroll`, hourly employees use `hourly_wage` instead. This commit uses `_get_contract_wage_field()` so the test sets the correct field in both cases. [error-237750](https://runbot.odoo.com/odoo/error/237750) Forward-Port-Of: odoo/enterprise#127398
Users can now decline a signature request with a reason without triggering an error screen. The signing workflow now closes the decline window before showing the confirmation message, making the process smoother and more reliable.
Original PR description
Version: 19.4 Steps to reproduce: - Create a sign request with a signature and send it to a user - Decline the document as administrator with a reason Issue: Opening the thank you dialog before closing the decline dialog caused both actions to be processed together. This made the thank you dialog get built twice and both attempts were already destroyed before orm.call, raising a traceback. Fix: Close the decline signature dialog first, then open the thank you dialog. Task id - 6471923 Forward-Port-Of: odoo/enterprise#128345
The Belgian salary configurator now handles cases where no company bike is available. This prevents an error when users select the company bike option and keeps the offer setup process running smoothly.
Original PR description
Steps to Reproduce: - install l10n_be_hr_contract_salary module. - make sure that there is no model with vehicle type bike in fleet. - create an offer in recruitment. - open salary configurator. - click on company bike checkbox. Issue: - traceback occurs when enabling the company bike option without a configured bike. Reason: - the company bike depreciated cost value is empty when no bike is available, but the code tries to split it into bike options and vehicle ID resulting in a traceback. Solution: - Use the condition to check if the company bike depreciated cost is available before spliting the value. - Set the depreciated cost to 0 when no bike is selected. task-6468987 Forward-Port-Of: odoo/enterprise#127898
The guided tour flow has been reorganized so the interactive tour player manages the end-of-tour experience directly. This makes tour completion tracking more reliable, especially in automated scenarios where success is now confirmed only after the completion message appears.
Original PR description
…teractive onTourEnd was an externally-injected callback whose completion the interactive step player had to blindly trust and separately re-derive (rainbow man message, tour pointer) to know what actually happened. TourInteractive now owns pointer setup/teardown and the full end-of-tour sequence (reward, consume, chaining) itself, and in robot mode only reports the tour as succeeded once the rainbow man is confirmed in the DOM instead of right before it's requested. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change centralizes how Odoo detects and uses debug mode across many apps. It should make developer and support tools more consistent without changing normal day-to-day business workflows.
Original PR description
This commit introduces a new plugin `DebugModePlugin` which gives some utility functions: - `isActive`: checks that odoo is in debug mode or in a specific mode if the mode is given in parameter. - `toList`: lists the debug modes (`debug=assets,test` gives `["assets", "test"]`). - `toString`: returns the raw debug value (`debug=assets,test` gives `"assets,test"`). This commit also replaces all occurrences of `env.debug` and some of `odoo.debug` by the plugin.
The HTML builder has been updated to rely on newer internal component patterns instead of deprecated ones. This helps keep the website editing tools maintainable and ready for future framework updates, with little expected visible change for users.
Original PR description
See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update refreshes internal code used by several Odoo apps to align with the newer interface framework. It helps keep calendar, timesheet, knowledge, and signing features easier to maintain without changing day-to-day user workflows.
Original PR description
- community: https://github.com/odoo/odoo/pull/281421 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This internal cleanup replaces the previous way apps checked debug mode with a shared plugin. It helps keep behavior consistent across affected Odoo apps without changing day-to-day user workflows.
Original PR description
This commit replaces all occurrences of `env.debug` by the new plugin `DebugModePlugin`.
The Documents app internals were reorganized to remove outdated technical dependencies and simplify how document views are managed. This should make future maintenance and upgrades easier without changing the day-to-day user experience.
Original PR description
- community: https://github.com/odoo/odoo/pull/284726 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update replaces a deprecated internal frontend mechanism with the newer standard approach across several Odoo apps. It helps keep the interface code easier to maintain and reduces upgrade risk, without changing visible business workflows.
Original PR description
- community: https://github.com/odoo/odoo/pull/281946 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The mail system now uses one internal change-tracking approach instead of two overlapping mechanisms. This reduces unnecessary presence update messages during user activity and makes the messaging code easier to maintain without changing expected user-facing behavior.
Original PR description
Before this commit, a record reacts to what it reads in two ways: `Record.onChange`, and a raw owl effect. Such an effect only sees a relation change when it reads the record as its proxy, which only `static new` has, so three models override `static new` for nothing else. There is no need for the raw effect, as `Record.onChange` runs the same body on a change and compares the values its dependencies return, so a bus channel that comes back equal keeps its subscription. This commit registers the four raw effects as onChange, from `setup`. An onChange resolves the proxy when its two functions run instead of when they are registered, which is what a `setup` registration needs. `effectWithCleanup` has no caller left, so it goes. Note that the self user or guest sends one `update_presence` when its status changes, where the effect sent one on every click and keystroke while the server still reported away or offline.
Several internal text field length limits were removed across accounting, documents, payroll, expense, and localization modules. This reduces avoidable data-entry constraints and keeps enterprise modules aligned with the related core platform cleanup, with minimal expected business impact.
Original PR description
https://github.com/odoo/odoo/pull/284290
The Point of Sale number entry logic has been reorganized into a plugin, making it easier to maintain and extend across related POS features. This is an internal cleanup with little expected day-to-day impact for users, but it should support more reliable future updates.
Original PR description
Convert the number buffer service into a plugin