Friday, September 11, 2026
16 changes · saas-19.4
Enhancements to existing features
Obox actions are now retained for 24 hours instead of 3 hours. This gives teams more time to investigate and debug issues up to a day after they occur, with no expected impact on end users.
Original PR description
We now keep obox actions for 24h instead of 3h to be able to debug until one day after. Forward-Port-Of: odoo/enterprise#130965
The Mexico electronic invoicing flow now records when an automatic cancellation cannot be completed. This gives support and accounting teams clearer information to investigate cancellation issues that were previously ignored silently.
Original PR description
In the current state, when an edi document is set to cancelled, the journal entry will attempt to cancel. However, if the cancellation throws a `UserError`, the flow simply continues. This PR adds a logger call to record the failure and help investigate the potential causes. Forward-Port-Of: odoo/enterprise#123511
The Belgian payroll configuration now includes an updated value for the training time off threshold. This helps payroll calculations stay aligned with the latest required parameter for Belgian HR payroll processing.
Original PR description
add new value to the training_time_off_threshold salary rule param. task-6545545 Forward-Port-Of: odoo/enterprise#131080
Log entries now show the real execution time even when tests use simulated dates. This makes runbot logs easier to interpret and helps teams analyze how long test steps actually took, while keeping simulated-time details available when needed.
Original PR description
When using faketime the logs are not showing the real time but the faketime one which can be confusing when listed in the runbot interface. Before the usage of the JSONFormatter, the logs were using the PostgreSQL time, which is the real time. This restores the previous behaviour. Having the faked time oustide JsonFromater is also painful: long running faketimed tests end up with most of their logs stamped to nearly the same real date, preventing any analysis of execution time based on the logs. One drawback of this change is the inability to identify at first sight whether a log was faketimed or not, but at this point it is just a tradeoff, and the faked_created field on the record still allows getting this info if needed. Forward-Port-Of: odoo/odoo#287455 Forward-Port-Of: odoo/odoo#287159
Resolved issues and error corrections
The Contracts page under Employee Records no longer shows Kanban as a selectable view because that view is not supported. This avoids user confusion and keeps the available display options aligned with what actually works.
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
Odoo now avoids trying to refresh a record after its discussion panel has already been closed during view navigation. This prevents an unnecessary error message when users ask the AI assistant to open another view while a full message composer is still open.
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#287744
Forward-Port-Of: odoo/odoo#287125Switching to another view through Ask AI while a full message composer is open no longer triggers an error. The system now avoids trying to refresh a chatter area that has already been closed, making navigation smoother and preventing disruptive error messages.
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#131184
Forward-Port-Of: odoo/enterprise#131112This fixes a mismatch between product identifiers sent to Google Analytics 4 and those used in Google Merchant Center. It helps ensure product performance and advertising data line up correctly across Google tools.
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#287745 Forward-Port-Of: odoo/odoo#287590
This fix stops non-product display lines from being selected or copied into manufacturing stock movements. It helps keep manufacturing and inventory records accurate by ensuring only valid sales order lines are linked during production confirmation.
Original PR description
Issue: ====== before this commit, user was able to select a display SOL and at MO confirmation the SOL was copied to the stock move, so we end up with a stock move linked to a display SOL, which is not correct. Solution: ========= - add a domain on the SOL field as first guard layer - add check on the SOL on MO confirmation to prevent copying a display SOL to the stock move opw-6473017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287491 Forward-Port-Of: odoo/odoo#286534
The quotation document form now clearly marks the attachment upload as required before saving. This helps users understand they must select a file first, avoiding confusion when creating quote documents.
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
When a timesheet date is changed from a linked task, the Timesheet Assistant now updates right away instead of showing the old date until a page refresh. This keeps the assistant in sync and helps users avoid confusion when reviewing or editing timesheet entries.
Original PR description
Steps to Reproduce: - Install timesheet_grid and activate Timesheet Assistant - Open a timesheet and click the task external link - Change the timesheet date from the task form and save Issue: When the timesheet date is changed from the task, the assistant still shows the old date until the page is refreshed Fix: Reload assistant timesheets after the linked task is saved and refresh or clear the selected timesheet based on the new date task-6454988 Forward-Port-Of: odoo/enterprise#130265
The payslip form now keeps wage and worked-days figures contained within their summary cards, even on narrower screens or when amounts are unusually long. This prevents visual overflow and makes payroll information easier to read without changing payroll calculations.
Original PR description
The worked days/wage stat cards on the payslip form used flex-basis-*/bg-100 utility classes but no min-width guard, so the monetary fields (basic_wage, net_wage, sum_worked_days) could overflow past the card's border on narrower screens or with large amounts. Add min-w-0 on the cards so they can shrink within their flex row, and text-break on the big-number fields so long values wrap inside the card instead of spilling out of it. Forward-Port-Of: odoo/enterprise#131031
This fix adjusts Odoo's internal test setup so password checks no longer trigger unnecessary session changes during automated tests. It reduces random test failures and helps keep development and release validation more stable without changing customer-facing 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
This change fixes a test setup issue in the Purchase Stock module when running on databases without demo data. It ensures internal reordering rule tests can run reliably in clean environments, reducing false failures for quality checks.
Original PR description
Steps to reproduce ------------------ 1. install purchase_stock in a database without demo data 2. run any test in TestReorderingRule 3. observe the error: can't write on invisible field 'tracking' Note: This fix is only relevant when you run the test on an empty database, the demo data enables the Lots & Serial Numbers. Forward-Port-Of: odoo/odoo#286519
This update prevents self-ordering kiosks from showing an unnecessary warning about failing to contact the IoT box on the local network. It helps keep the kiosk checkout experience smoother by avoiding confusing popups in configurations where they should not appear.
Original PR description
This PR fixes the test where iot request triggers a "failed to contact your iot box on local network popup" Forward-Port-Of: odoo/enterprise#129433 Forward-Port-Of: odoo/enterprise#128388
Fixed a quotation display issue where enabling the optional Related Intervention column could cause section totals to appear in the wrong place or be cut off. This keeps amounts aligned correctly, making quotations easier to read and reducing confusion for sales and field service users.
Original PR description
Steps to reproduce: --- - Install `industry_fsm_sale` module. - Create a quotation. - Add a section line, then a product line below it. - Enable the optional `Related Task` column from the column…
Steps to reproduce: --- - Install `industry_fsm_sale` module. - Create a quotation. - Add a section line, then a product line below it. - Enable the optional `Related Task` column from the column selector. Issue: --- - When the Related Task optional column is enabled, the section line's aggregated Amount value appears in the wrong column or is clipped. Root cause: --- - `getSectionColumns()` computes the section title's colspan as `columns.length - sectionCols.length + 1` [1]. This formula assumes all non-section columns sit in the middle of the list, with the aggregated amount column (`price_subtotal`) anchored at the right end. - The `task_id` [2] field was added via `position="inside"`, which appends it at the end of `<list>` after `price_subtotal` — breaking that assumption by placing a non-section column after the aggregated amount column. - This makes the section title colspan one unit too wide when `task_id` is enabled, shifting the section's aggregated Amount cell past the `price_subtotal` header column. Fix: --- - Changed the xpath to insert `task_id` after the `discount` field, placing it in the middle of the column list where the colspan formula correctly absorbs it into the title span and keeps the amount column aligned. [1]: https://github.com/odoo/odoo/blob/ed22e3c299d6606f8014e2ffdd4a30f5c7be83ec/addons/account/static/src/components/section_and_note_fields_backend/section_and_note_fields_backend.js#L449 [2]https://github.com/odoo/enterprise/blob/2de1512bce6e2bef16ebd45629cbaf0839bebcbf/industry_fsm_sale/views/sale_order_views.xml#L9-L11 Before: <img width="1254" height="262" alt="image" src="https://github.com/user-attachments/assets/7a62c22c-b002-49d9-a75c-f569987f565e" /> After: <img width="1230" height="337" alt="image" src="https://github.com/user-attachments/assets/951f213a-09af-4b07-be30-d69dae2cc51e" /> opw-6472638 --- Forward-Port-Of: odoo/enterprise#130889 Forward-Port-Of: odoo/enterprise#129125