Friday, September 11, 2026
11 changes · saas-19.1
Resolved issues and error corrections
The Contracts page no longer offers a Kanban view option because that view is not available or needed. This prevents users from selecting a view that would not work, making navigation clearer and avoiding confusion.
Original PR description
We don't have a Kanban view for contracts, but we still allow users to select that view type. After discussion with the team, we've deemed that view unnecessary. Instead of implementing the Kanban view, we'll just remove that option from the "Employee Records" (Contracts) page. opw-6475797 Forward-Port-Of: odoo/odoo#284829
The Timesheets Assistant sample data now uses regular project tasks instead of task templates. This helps generated sample activities appear with the right task links, making demos and onboarding data more accurate.
Original PR description
The Timesheets Assistant sample data generator searches project.task with `is_template != False`, so it collects template tasks instead of regular ones and the generated activity never links to a task. Task-6566451
The project overview now shows the upcoming milestone based on the milestone deadline rather than creation order. This keeps the project list aligned with the milestone list and helps users see the correct next deliverable.
Original PR description
Issue: The project list could display the first created unreached milestone as the next milestone, even when another milestone had an earlier deadline. This made the project overview inconsistent…
Issue: The project list could display the first created unreached milestone as the next milestone, even when another milestone had an earlier deadline. This made the project overview inconsistent with the milestone list. Steps to reproduce: - Create a project with milestones enabled. - Create MS1, then MS2. - Give MS1 a later deadline than MS2. - Open the project list and display the Next Milestone column. Cause: `_compute_next_milestone_id()` aggregated unreached milestones as an `id:recordset` and selected its first element. The ORM orders that aggregate by database ID, so creation order was used instead of the milestone model's deadline order. https://github.com/odoo/odoo/blob/765174be270813442df6c497456fe2864517da0b/addons/project/models/project_project.py#L209-L218 https://github.com/odoo/odoo/blob/765174be270813442df6c497456fe2864517da0b/odoo/models.py#L364-L377 Solution: Retrieve unreached milestones through their normal ordered search before grouping them per project. This preserves batched computation while ensuring that the selected record follows the established milestone order. opw-6496938 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287355 Forward-Port-Of: odoo/odoo#285933
This fix prevents test logins from unnecessarily rotating password hashes and session IDs during automated runs. It reduces random test failures caused by overlapping requests seeing inconsistent session states, improving confidence in test results without changing normal user behavior.
Original PR description
The test harness patches the CryptContext object to spend less time hashing to decrease total test runtime. Because the hash parameters have changed, every first login (per transaction) per user will result in a hash rotation. The session_id is also rotated when the password hash rotates. When multiple requests are sent to the server while a session rotation is underway, the session datastore holds either a valid, or expired, or logged-out user session. This is a source of indeterminism in tests that can be prevented by always returning None value for replacement hash. REF Runbot; https://runbot.odoo.com/odoo/error/242811 REF Runbot; https://runbot.odoo.com/odoo/error/233722 Forward-Port-Of: odoo/odoo#287350 Forward-Port-Of: odoo/odoo#285710
The quotation document form now clearly shows that an attachment must be added before saving. This prevents confusion when users create quote documents, because the required step is shown on the upload field instead of a locked name field.
Original PR description
When trying to save an empty quotation document from the form view, the save is blocked because the `name` field is required. However, `name` is readonly when no attachment has been selected. As a result, the form doesn't display the required-field decoration on that field, which is confusing. The attachment field should be marked as required in the view instead. This makes it clear that an attachment must be selected first, after which the `name` field becomes available and can be filled in. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287400
This fix ensures product identifiers sent to Google Analytics match the identifiers used in Google Merchant Center feeds. This helps businesses get more consistent advertising and ecommerce reporting for website shop products.
Original PR description
Commit d0bf183b053eb0133e6f7e5e04481ca07bff6bb3 fixes a mismatch between GA4 `item_id` and GMC `id` but was missing the fix in `_get_google_analytics_data` method opw-6443326 Forward-Port-Of: odoo/odoo#287590
This fix prevents an error that could appear when users ask the AI assistant to open another view while a full email composer is still open. The system now avoids refreshing a record that has already been closed, making navigation smoother and preventing unnecessary error popups.
Original PR description
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is…
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is closed. Closing that dialog then calls the chatter's onCloseFullComposerCallback, which reloads the parent record through reloadParentView(). However at that point the chatter no longer exists, so the reload's RPC call gets rejected with "Component is destroyed", and nothing is left to catch it.
How to reproduce:
- Open "Ask AI" from the top bar.
- Open an opportunity in CRM, then open the mail composer (click either 'Send message' or 'Log Note'), then click the enlarge button so it opens as a full composer dialog.
- Ask the agent (the one you pre-opened) to open another view, e.g. "show me all my contacts in the US", "show me the contact view of Abigail Peterson"
Current behavior:
The requested view opens correctly, but an UncaughtPromiseError ("Component is destroyed") is raised.
Expected behavior:
Switching views while a full composer dialog is open should not raise any error. The chatter's parent record should simply not be reloaded if the chatter has already been destroyed by the time its full composer dialog closes.
task: 6365003
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287125This fixes an error that could appear when the AI assistant opened another view while a full email composer was still open. Users can now switch views smoothly without seeing a disruptive error message.
Original PR description
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is…
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is closed. Closing that dialog then calls the chatter's onCloseFullComposerCallback, which reloads the parent record through reloadParentView(). However at that point the chatter no longer exists, so the reload's RPC call gets rejected with "Component is destroyed", and nothing is left to catch it.
How to reproduce:
- Open "Ask AI" from the top bar.
- Open an opportunity in CRM, then open the mail composer (click either 'Send message' or 'Log Note'), then click the enlarge button so it opens as a full composer dialog.
- Ask the agent (the one you pre-opened) to open another view, e.g. "show me all my contacts in the US", "show me the contact view of Abigail Peterson"
Current behavior:
The requested view opens correctly, but an UncaughtPromiseError ("Component is destroyed") is raised.
Expected behavior:
Switching views while a full composer dialog is open should not raise any error. The chatter's parent record should simply not be reloaded if the chatter has already been destroyed by the time its full composer dialog closes.
community: https://github.com/odoo/odoo/pull/287125
task: 6365003
Forward-Port-Of: odoo/enterprise#131112Image upload fields now apply the Android camera workaround only in Chromium-based Android browsers that need it. This prevents unnecessary document picker options in other environments, especially the native app, while keeping camera access available where Android would otherwise hide it.
Original PR description
Since Android 14, Chromium sends a file input accepting only images straight to the photo picker, which has no "Camera" entry. The image fields work around it by appending `dummy/allowAndroidCamera`…
Since Android 14, Chromium sends a file input accepting only images straight to the photo picker, which has no "Camera" entry. The image fields work around it by appending `dummy/allowAndroidCamera` to their accept attribute: a mimetype which is not an image is enough to get the generic chooser, and its camera, back. https://issues.chromium.org/issues/40937303 That invalid mimetype was appended for everyone, while only the browsers based on Chromium on Android need it: - the issue is an Android one, the desktop file dialogs are not concerned - the native app builds its own file chooser out of the accept attribute, and the invalid mimetype makes it offer the document picker on a field which only accepts images - Firefox and Safari are not based on Chromium and are not affected The workaround is now limited to the browsers needing it, and the expression moved from the template to a getter, since it is no longer a simple concatenation. Code made by Claude Supervised by RFR --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286270 Forward-Port-Of: odoo/odoo#285643
This fixes an issue where spreadsheet formulas could fail after changing locale settings, such as French decimal formatting, when reading a single related invoice total. Users can now calculate with those values normally instead of seeing errors caused by numbers being treated as text.
Original PR description
Steps to reproduce:
- insert a sale.order list into a spreadsheet
- change the locale to FR_fr
- add the formula in A1: =ODOO.LIST(1, 1, "invoice_ids.amount_total"
- in A2: =A1+1 => error
The value for the "amount_total" is stringified
to something like "4.5" because of the `[].join(",")` but "4.5" is not interpreted as a number in the FR locale where the decimal separator is "," and it should be "4,5"
With this commit, when there's a single record in the x2many, we fallback on the "normal" case and return the real value.
When there are multiple values, we volontarily keep the current behavior. We can't "just format it" because we join with "," and it wouldn't work if "," is also the decimal separator. This is a known and accepted limitation, especially in stable
Task: 6307092
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#270279This fix prevents spreadsheet actions from converting multi-value linked records into plain text. Business users benefit from more reliable spreadsheet behavior when working with document-related data and filters.
Original PR description
See community PR task-6307092 Forward-Port-Of: odoo/enterprise#120701