Saturday, September 12, 2026
30 changes · master
Enhancements to existing features
This update aligns subscription portal and rental cart behavior with recent platform changes. It helps keep sales subscriptions and online rentals working consistently after related updates in the main Odoo system.
Original PR description
task-6359070 See also: - https://github.com/odoo/odoo/pull/275286
This update rewrites the internal review instructions to make pull request reviews more consistent and accurate. It helps reviewers check the right version of the code, consider related enterprise changes, and verify affected areas before reporting issues.
Original PR description
Follow-up to #285015. Rewrites `skills/odoo-review/SKILL.md` after running 10 pr reviews with various models, with and without the skills and seeing what worked well and what didn't - The guidelines files often weren't read - The enterprise part of the PR was often ignored - A wrong / stale version of master was often used for the diff - Consumers of changed interfaces were not checked consistently This PR improves the reviewer behaviour in those regards
The accounting dashboard onboarding has been refined to make tax return setup clearer and more relevant. Companies marked as not subject to VAT will no longer see unnecessary tax report and return options, reducing confusion during configuration.
Original PR description
This commit makes minor improvements in the account onboarding dashboard. - Adds helper for Tax Return kanban card and updates the action button string. - Hides some Tax settings if the company is "Not Subject to VAT" (check added in community)
The Belgian payroll configuration now includes an updated value for the training time off threshold used in salary rule calculations. This helps keep payroll processing aligned with current requirements for Belgian HR payroll.
Original PR description
add new value to the training_time_off_threshold salary rule param. task-6545545 Forward-Port-Of: odoo/enterprise#131162 Forward-Port-Of: odoo/enterprise#131080
Kanban views embedded inside forms now use tighter, more consistent spacing instead of keeping the standalone view layout. The “New” button in kanban views also gets a visual refresh, making the interface cleaner and easier to use.
Original PR description
A kanban inside a form kept the padding and the gap of the standalone view: the form neutralizes them through `--KanbanRecord-margin-*`, but ENT rewrites them, at the same specificity. We now set the specificity directly in COM so the contextual adaptation takes the priority. This commit also improves the design of `o-kanban-button-new` inside the kanban renderer. ENT: https://github.com/odoo/enterprise/pull/131135 task-6527607 | Before | After | |--------|--------| | <img width="1388" height="712" alt="Screenshot 2026-09-09 at 15 03 52" src="https://github.com/user-attachments/assets/cdfe4895-4cc4-45a7-b5ba-2c2f52204d99" /> | <img width="1383" height="677" alt="Screenshot 2026-09-09 at 15 03 12" src="https://github.com/user-attachments/assets/2b5048af-b8a4-49fe-9f45-94fde40cc2b5" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
The attendance Gantt test setup now limits its data to the company created for the test. This prevents unrelated demo company records from affecting results, making quality checks more stable without changing business features.
Original PR description
Some tests in `hr_attendance_gantt` could include employees from other companies, making their expected employee counts depend on unrelated demo data. This commit adds the test company to the common domain so the gantt data only includes employees created for the test case. [error-945955](https://runbot.odoo.com/odoo/error/945955) Forward-Port-Of: odoo/enterprise#128108
Code cleanup and technical improvements
This internal cleanup changes several mail and live chat values so they are calculated only when needed instead of stored separately. This reduces unnecessary data updates and helps keep messaging behavior simpler and more reliable without changing what users see.
Original PR description
Before this commit, a value like isVideoStreaming or offlineMembers is a field with a compute. Nothing else writes it, so the field only stores what the compute makes. This commit declares each of them as a computed instead, made on read. A member list writes nothing when it sorts now, so its FIXME goes. https://github.com/odoo/enterprise/pull/131284
The invoice form now hides Ecuador reimbursement details from users who do not have accounting access. This prevents access errors when non-accounting users open invoices, improving reliability without changing accounting workflows.
Original PR description
The reimbursement lines are added to the invoice form without any group restriction, while their model can only be accessed by accounting users. As a result, opening an invoice form as a user without accounting rights can raise an AccessError when the form view tries to retrieve the reimbursement subview. This commit restricts the reimbursement page to the groups allowed to access reimbursement lines. [error-946579](https://runbot.odoo.com/odoo/error/946579) Forward-Port-Of: odoo/enterprise#129981
Website forms now ignore fields without a name when saving page settings. This prevents confusing repeated error popups caused by invalid form markup while keeping normal form saves working as expected.
Original PR description
On save, the form option collects the `name` of every non-custom form input on the page and sends the list to `formbuilder_whitelist`. An input with an empty name (hand-edited or generated markup) yields '', which the server rejects with a ValueError since it matches no field of the model. As the whitelist RPC is fired without being awaited, the save itself succeeds and the broken field persists in the page, so every subsequent save of that page then raises the same unexplained RPC error dialog, forever. Skip nameless inputs: a field that doesn't post anything has nothing to whitelist. task-6251785
The Contracts page under Employee Records no longer offers a Kanban view option that was not actually available. This prevents users from selecting a view that would not work and keeps the page choices clearer.
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 generator now selects regular project tasks instead of template tasks. This ensures generated sample activities can be linked to tasks correctly, making demo or onboarding data more useful and 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 Forward-Port-Of: odoo/enterprise#131248
Updated the point of sale and stock-related test coverage so product loading limits are checked consistently when stock features are installed. This reduces false test failures and helps keep checkout product loading behavior reliable across module combinations.
Original PR description
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching…
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching code: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L190 This allowed us to completely override (not extend) the ordering of the loaded products in our new pos_stock module: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/pos_stock/models/product_template.py#L42-L65 Notice the difference in point_of_sale: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L403-L416 This was causing problems with our existing test for this feature in point_of_sale because we were explicitly examining the ordering of the products; obviously this ordering would be different when pos_stock is installed alongside point_of_sale. Thus, we must decouple our original test for this feature so that ordering can be examined independently in each module's tests. ## Now: We have one test in point_of_sale that just makes sure our limited products loading feature actually caps the number of products loaded. This test will work correctly whether or not pos_stock is installed. In addition, we have one more test in point_of_sale and pos_stock that explicitly examines the ordering of the products in these limiting conditions when both modules are installed. The point_of_sale test will be skipped when pos_stock is installed because the latter module defines conflicting ordering. runbot-243064 Forward-Port-Of: odoo/odoo#283621
Image fields now apply an Android camera compatibility workaround only for Chromium-based Android browsers that need it. This prevents other browsers and the Odoo mobile app from showing unnecessary or confusing file picker options while preserving camera access where it was missing.
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#287923 Forward-Port-Of: odoo/odoo#285643
Fixed an issue where saving a message after opening edit mode could incorrectly mark it as edited, even when no content was changed. This keeps chatter message history more accurate and avoids confusion for users reviewing communication records.
Original PR description
Steps to reproduce: ------------------------------------- 1. Open the chatter of any record 2. Open the full composer for the Log Note 3. Add some text and paste some images > Post the log note 4.…
Steps to reproduce: ------------------------------------- 1. Open the chatter of any record 2. Open the full composer for the Log Note 3. Add some text and paste some images > Post the log note 4. Click on the Edit option 5. Save the message without editing anything Observation: ------------------------------------- You will notice that the (edited) label appears even though the message wasn't edited at all, only the edit mode was made active. Issue: ------------------------------------- When a message is posted via the mail composer, the email conversion pipeline injects MSO conditional comments like `<!--<![endif]-->` and `<!--[if mso]>...<![endif]-->` into the HTML body. These comments are added by the `_hideForOutlook` and `createMso` https://github.com/odoo/odoo/blob/083e091eaa7d983f6c826c02b0d0652a821227fb/addons/mail/static/src/views/web/fields/html_mail_field/convert_inline.js#L1978-L1988 https://github.com/odoo/odoo/blob/083e091eaa7d983f6c826c02b0d0652a821227fb/addons/mail/static/src/views/web/fields/html_mail_field/convert_inline.js#L1699-L1707 functions to ensure Outlook compatibility, they wrap responsive elements so that Outlook receives simplified table-based fallbacks while modern clients see the original layout. The stored message body on the server retains these comments. When a user clicks "Edit" on such a message, the body is loaded into the OdooEditor. The browser's DOM parser treats `<!--<![endif]-->` as standard HTML comment nodes, which are not preserved in `innerHTML` serialization. So the editor returns the body without these comments, even if the user made no changes. The `edit()` method in then compares `updatedBodyEl.innerHTML` (from editor, no comments) against `messageBodyEl.innerHTML` (from server, has comments), finds a difference, and sends a update to the backend, which stamps the message with the (edited) label. Solution: ------------------------------------- Before comparing innerHTML, strip all HTML comment nodes from both the original and updated body elements. This is done on throwaway DOM elements created solely for comparison. The actual body sent to the server (`body` parameter) is never modified. Note: ------------------------------------- An alternative approach would be to strip comments at the string level using a regex (`html.replace(/<!--[\s\S]*?-->/g, '')`) before creating the DOM elements. This is valid since HTML comment syntax `(<!--...-->)` is strictly defined and no nesting is allowed, so the regex is reliable. This commit also preserve images while trimming empty message boundaries. Newer test covers this issue. opw-6328529 Forward-Port-Of: odoo/odoo#287502 Forward-Port-Of: odoo/odoo#274927
This fixes a display issue where mega menu content could touch the edge of the mobile website preview. Mobile menus now keep the expected spacing, making navigation look cleaner and easier to read.
Original PR description
Steps to reproduce: - Open a website in mobile preview. - Add a mega menu and select the "Odoo Menu" template. - Open the mega menu. => Its content touches the left edge of the mobile panel. Before this commit, the mega menu rework [1] removed the horizontal padding override required by nested `.container` elements. After this commit, mega menu containers keep the expected grid gutter on mobile. [1]: https://github.com/odoo/odoo/commit/ff5423bc3aa75e47b210ce98f3efba8c75459a5a
Website theme previews now adjust text and icon colors when users choose darker color palettes. This prevents hard-to-read elements in the configurator, making theme selection clearer and more reliable.
Original PR description
Steps to reproduce: - Open the website configurator. - Select a dark color palette. - Preview the "Eclipse" theme. => The shaped icons in the Features section are hard to see. Before this commit, static theme previews kept the text colors compiled for their original palette when `bg-o-color-X` backgrounds changed. This could result in dark text on a dark background. After this commit, configurator previews recompute the text color for each palette background and keep shaped icons readable. task-6485048
This change fixes how the mail app tracks whether a conversation is currently in focus when it is open in more than one view. It prevents one view losing focus from incorrectly marking the whole conversation as unfocused while another view is still active.
Original PR description
Before this commit, the Thread component writes isFocusedByThread on the record it displays and the record turns that flag into isFocusedCounter. The problem is that two views of the same thread share the one flag, so the first to lose the focus clears it while the other still has it. This commit keeps the focus in the component and lets each view hold its own share of the counter, so a thread is focused as long as one of its views is.
The quotation document form now clearly shows that an attachment must be selected before saving. This prevents confusion when creating quote documents by highlighting the required step directly on the attachment 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
The certificate setup screen no longer shows an error banner simply because no password was entered for a key file. Users will only see the warning when they provided a password and it is incorrect, reducing confusion during certificate configuration.
Original PR description
When adding a key file without entering a password, an error banner is immediately displayed, incorrectly suggesting that the password may be invalid. Only show the error banner when a password was provided and is incorrect. Also refactored the compute function to avoid repeated try-except blocks. task-6299175 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286307 Forward-Port-Of: odoo/odoo#283589
This update corrects a small configuration screen issue in Belgian payroll settings caused by improperly closed fields. It helps ensure the settings page loads and displays as intended for users managing payroll configuration.
Original PR description
Found some fields that has closed bracket too soon in payroll_config_settings_views.xml. This PR expected to remove too son '/>' closures. task-6522569
Payslip summary cards now keep wage and worked-days values inside their borders on smaller screens or when amounts are long. This improves readability and avoids broken layouts for payroll users reviewing payslips.
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 update fixes a failing automated test in the Expense Stripe module after related platform changes. It helps keep quality checks reliable so future updates can be delivered with confidence.
Original PR description
After the changes made in the community PR, a test failed. task-6299175
This fixes internal typing issues in the web and messaging code so translation text and date/time values are handled more consistently. The change helps developers catch mistakes earlier, reducing the risk of small translation or scheduling-related defects reaching users.
Original PR description
See individual commits for details.
Opening or refreshing a live chat avatar now avoids changing the underlying chat member history. This prevents unnecessary system notifications and helps keep live chat behavior stable for users.
Original PR description
Before this commit, the avatar of a livechat is picked by sorting livechat_channel_member_history_ids, which sorts the relation itself: a read of the avatar reorders the records stored on the channel and notifies everything that reads them. This commit sorts a copy.
Live chat conversations with public visitors now show the visitor conversation avatar in the Discuss header instead of a generic thread icon. This makes live chat threads easier to recognize and improves consistency in the customer support interface.
Original PR description
Before this commit, the Discuss content header showed the thread icon instead of the avatar for a livechat held with a public visitor. This was because `showThreadAvatar` relied on `hasCorrespondentAvatar`, i.e. on a correspondent with an uploaded photo to display. A public visitor is a guest with no uploaded image, so it was false. The header now shows the avatar of any thread backed by a channel. Related Enterprise PR: https://github.com/odoo/enterprise/pull/130678 Task-[6526300](https://www.odoo.com/odoo/project/1519/tasks/6526300) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Live chat conversations with public visitors now show the visitor conversation avatar in the Discuss header instead of a generic thread icon. This makes WhatsApp-related chat views clearer and more consistent for support teams handling visitor conversations.
Original PR description
Before this commit, the Discuss content header showed the thread icon instead of the avatar for a livechat held with a public visitor. This was because `showThreadAvatar` relied on `hasCorrespondentAvatar`, i.e. on a correspondent with an uploaded photo to display. A public visitor is a guest with no uploaded image, so it was false. The header now shows the avatar of any thread backed by a channel. Related Community PR: https://github.com/odoo/odoo/pull/286960 Task-[6526300](https://www.odoo.com/odoo/project/1519/tasks/6526300)
The mail notification popover now reads notification information directly instead of going through an internal proxy. This is a small internal cleanup that simplifies the code and reduces maintenance risk without changing user-facing behavior.
Original PR description
Before this commit, the notification popover reads isFollowerNotification through _proxy. A relation gives the proxy of each record, so notification._proxy is the notification. This commit reads the field from the notification. Nothing outside the model reads _proxy any more.
This update simplifies how the Mail app defines certain internal default values. It does not change user-facing behavior, but helps keep the code easier to maintain and less prone to future mistakes.
Original PR description
Before this commit, suggestedRecipients wraps its default array in fields.Attr, and _resolve declares no value at all. This commit declares both with the value alone. https://github.com/odoo/enterprise/pull/131312
This update simplifies internal field definitions across several Odoo Enterprise apps and fixes an issue where social conversations waiting for an operator were not visible in the Livechat tab. Business users benefit from more reliable livechat handling, while the broader cleanup reduces technical complexity without changing day-to-day workflows.
Original PR description
Before this commit, these models wrap the default value of a field in fields.Attr. This commit declares those fields with the value alone, which leaves no fields.Attr in enterprise. Counterpart of "[REF] mail: declare a plain value without fields.Attr". https://github.com/odoo/odoo/pull/287950
This update streamlines how WhatsApp discussion information is managed behind the scenes. It removes an unnecessary internal field, helping keep the codebase cleaner and easier to maintain without changing the user experience.
Original PR description
Enterprise counterpart of "[REF] mail: drop the compute-only fields for computeds", which explains the why. https://github.com/odoo/odoo/pull/287867