Tuesday, July 28, 2026
25 changes · master
Resolved issues and error corrections
This update replaces shared editable defaults with safer fixed values in record search settings across many Odoo Enterprise modules. It reduces the risk of rare cross-record side effects and prepares the codebase for stricter automated quality checks, with no expected change to day-to-day user workflows.
Original PR description
Mutable default values share state across all instances of the class. This can lead to bugs when the attributes are changed in one instance, as those changes will unexpectedly affect all other instances.[^1] Most `_rec_names_search` are defined as lists, but could be defined as immutable tuples instead. Found using the linter at odoo/odoo#217724. This linter will be merged only after all existing findings are resolved. This merge contains 2 commits: 1. The execution of the `tuple-rec_names_search` upgrade-code script. 2. The fixes to address the (true/false)-negatives of the script. task-6396049 [^1]: https://docs.astral.sh/ruff/rules/mutable-class-default/
This fix removes an outdated setting from the FedEx delivery integration setup. It helps keep the shipping connection logic consistent after a previous change, reducing the chance of confusion or minor configuration issues.
Original PR description
Follow up of 6b5d4eb which forgot to remove the now unused `make_return` key. ----- Ticket: opw-6101620
This update adjusts several scheduling, map, subscription, and WhatsApp-related screens to work correctly with the newer interface framework rules. It prevents missing buttons or broken popovers in Gantt and map views while keeping the change internal and low risk for users.
Original PR description
Follow-up to the community change that makes the owl3 compatibility layer throw on `static defaultProps`. Owl 3 ignores that attribute; defaults must go through `useProps(...).optional(default)`.…
Follow-up to the community change that makes the owl3 compatibility layer throw on `static defaultProps`. Owl 3 ignores that attribute; defaults must go through `useProps(...).optional(default)`.
Remove the remaining `static defaultProps` and fold the defaults into the props schema:
- web_gantt: GanttPopover -> `props = useProps(ganttPopoverProps)`, defaults become `.optional(() => ...)`. Export `ganttPopoverProps` (props is now an instance field, so `GanttPopover.props` no longer resolves).
- web_map: MapPopover -> `props = useProps({...})`.
- whatsapp phone_field: the `patch(PhoneField, { defaultProps, props })` augmented dead statics; augment the exported `phoneFieldProps` schema instead, folding `enableWhatsAppButton: true` into `.optional(true)`.
Fix consumers broken by `props` becoming an instance field:
- appointment: AppointmentGanttPopover built its schema from `GanttPopover.props.concat(...)`; build on the exported `ganttPopoverProps`.
- sale_subscription: the `patch(Product, { props })` override augmented the now-dead static `props`; augment the exported `productProps` schema instead.This fix prevents leftover collaboration test activity from affecting an unrelated Knowledge tour. It improves build reliability by avoiding misleading errors during automated validation, with no expected change for end users.
Original PR description
This aims to fix Runbot build error #937788 ([1]). A collaboration error was thrown during a tour which makes no use of collaboration. This makes sure the bus from the previous test doesn't persist when running this tour so it doesn't interfere. [1]: https://runbot.odoo.com/odoo/runbot.build.error/937788 Forward-Port-Of: odoo/enterprise#125509
Uploading a document no longer causes an error when Auto Sort immediately moves it to another folder. This keeps the Documents workflow stable for users, with no visible change when the moved file is no longer in the current folder.
Original PR description
When Auto Sort is enabled, an uploaded document can be moved to a different folder as part of the sort. The subsequent model reload only fetches records for the current folder to select/scroll to the new record. But, the new document's is absent from `env.model.root.records`. `newRecords` ends up empty, making `newRecords[0]` undefined, which then crashes accessing record.resId. To fix this, we just return early because if the record isn't in the current folder, there's nothing to select or scroll to anyway, so returning early here doesn't change anything visible behavior, it just avoids the crash. Steps to reproudce: 1.Go to Documents. 2.Go to Company->Inbox 3.Go to the gear icon and make sure the "Auto Sort" is enabled with "Move to folder" 4.Add a new document that's sortable. 5.You'll get the error. opw-6281558 Forward-Port-Of: odoo/enterprise#121069
Users with IoT access but without Point of Sale access can now enable the LNA setting on IoT box records without seeing an access error. This removes an unnecessary permission-related interruption and helps IoT administration tasks run smoothly.
Original PR description
Before this commit, if a user who has IoT permissions but not POS permissions tries to enable LNA on an IoT box record, they will receive an Access Error. After this commit, a `sudo` is added to the `onchange` handler fixing the issue. task-6392548 Forward-Port-Of: odoo/enterprise#124656
The salary attachment form now shows the refund option again, matching the data already stored in the system. This helps payroll users correctly identify salary attachments that should be treated as refunds without relying on a separate wizard.
Original PR description
In an old PR (https://github.com/odoo/enterprise/pull/109195) the is_refund field was removed from the salary attachment view, although the field itself was not removed from the db. In a later PR (https://github.com/odoo/enterprise/pull/114188) the field was removed from the database but later reverted (https://github.com/odoo/enterprise/pull/123728). As it stands now, the field is in the database and is present in the view of a wizard but not in the standard form view of the salary attachment. This PR is reintroducing it. Task: 6415857 Forward-Port-Of: odoo/enterprise#125420
The U.S. accounting reports now handle deleted Profit and Loss summary lines without showing an error. This prevents interruptions when users customize report layouts and keeps the report accessible.
Original PR description
## Steps to Reproduce: 1. Install the Accounting module with demo data. 2. Enable developer mode. 3. Go to Reporting > Profit and Loss. 4. Click Configuration and delete the 'Gross Profit' line. 5. Return to the report. ## Error: `ValueError: External ID not found in the system: l10n_us_reports.pl_gross_profit` ## Cause: The report assumes the summary lines always exist and tries to fetch XML IDs. If any of these lines has been deleted, looking up will raises an error. ## Fix: Only apply the bold class to summary lines whose XML IDs are available. sentry-7601831925 Forward-Port-Of: odoo/enterprise#125200 Forward-Port-Of: odoo/enterprise#124011
This update prevents Swiss payroll processing from failing when a related payroll rule has been archived. It helps payroll teams continue monthly value handling without unexpected system errors caused by inactive rules.
Original PR description
Forward-Port-Of: odoo/enterprise#103677
Audit reports now refresh the number of invalid records when a check is reviewed successfully. This prevents users from seeing outdated anomaly counts after a check has been corrected, improving confidence in audit cycle results.
Original PR description
Problem: Sometimes after an audit check passes (gets reviewed successfully), the count of invalid records in the audit report is not updated. Steps to reproduce: 1. Add a check for an audit cycle 2. Make sure the check's domain is satisified by at least one record 3. Check the audit report and see the check you added 4. The check status should show an anomaly and the count of invalid records will be greater than 0 5. Now, edit the check so that the domain is not satisfied by any record 6. Check the audit report again and see the check you edited 7. The check status should show "Reviewed" but the count of invalid records will still be greater than 0, which is not correct Cause: When updating the status of an audit check, the count of invalid records is not updated, only the status gets updated. opw-6264177 Forward-Port-Of: odoo/enterprise#125491 Forward-Port-Of: odoo/enterprise#119227
The AI-powered SEO autofill now generates page titles and metadata in the website page's language instead of the user's personal language. This prevents multilingual websites from receiving SEO content in the wrong language, improving consistency for visitors and search engines.
Original PR description
The SEO "Fill with AI" autofill used the user's language for generation. On a website whose language differs from the user's, the generated seo metadata was therefore in the wrong language. This commit fixes this by using the page language instead. Forward-Port-Of: odoo/enterprise#123786 Forward-Port-Of: odoo/enterprise#123447
This fix prevents an error that could occur when multiple equity transactions are processed at the same time. It helps ensure equity transaction calculations complete reliably without interrupting users.
Original PR description
When the ``_compute_security_price`` method is called on multiple records, a traceback will appear. Traceback: ```py ValueError: Expected singleton: equity.transaction(1, 2) ``` https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/equity/models/equity_transaction.py#L218 The method filters newly created records using ``self._origin.id``. Since ``self`` is the whole recordset, accessing ``self._origin.id`` on multiple records raises a singleton error. sentry-7626410485 Forward-Port-Of: odoo/enterprise#125307
Accounting users no longer see a technical error when running auto reconciliation with no bank statement lines available. Instead, the system shows a clear warning, helping users understand that there is simply nothing to reconcile.
Original PR description
Currently, an error occurs when user tries to reconcile when there are no bank statements to reconcile. Steps to replicate: - Install `accountant` with demo. - Open Accounting and Click `To…
Currently, an error occurs when user tries to reconcile when there are no bank statements to reconcile. Steps to replicate: - Install `accountant` with demo. - Open Accounting and Click `To Reconcile` on the Bank Journal. - Go to the list view > Select all > From the Cog menu > Reset to draft. - Again select all and delete all the statement lines. - From Cog menu click on `Run Auto Reconciliation` > Run. Error: ``` SyntaxError: syntax error at or near ')' LINE 44: WHERE st_line.id IN () ``` Cause: - Error occurs because the [search] returns no results and the method `_try_auto_reconcile_statement_lines()` is called on an empty recordset. - Later in the flow the function `_partner_mapping()` [1] is call which makes the `self.ids` as empty tuple [2] this causes the query to have a syntaxerror. Solution: - When there are no statement lines to reconcile we show a warning notification. [search]: https://github.com/odoo/enterprise/blob/ec408cb9a569f321afc99f4065a7a0f545d4faf4/account_accountant/wizard/bank_rec_auto_reconcile_wizard.py#L21-L27 [1]: https://github.com/odoo/enterprise/blob/ec408cb9a569f321afc99f4065a7a0f545d4faf4/account_accountant/models/account_bank_statement.py#L427 [2]: https://github.com/odoo/enterprise/blob/1516209ee077cda03155686d1377eb70080538f1/account_accountant/models/account_bank_statement.py#L620 sentry-7615011817 Forward-Port-Of: odoo/enterprise#124804
This fixes an error that could occur when users loaded more partner-grouped trial balance lines for Colombian reports. The trial balance now handles empty column information correctly, so users can continue reviewing report details without interruption.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451 Forward-Port-Of: odoo/enterprise#124506 Forward-Port-Of: odoo/enterprise#124102
Fixed an issue where very large sales commission achievement records could not be opened because their identifiers were not handled correctly in the browser. Users can now access these records without seeing an erroneous “record does not exist” message.
Original PR description
Steps to reproduce: - Open an achievement with id > JS limit Issues: - We get a pop-up saying the record does not exists The reason we get this error is because since we are browsing a record with an id greater than JS limit the browser truncate it. In order to solve this issue the following PR was made #108751. A field `id_str` was added but it still wasn't working as we weren't retrieving the `id_str`. We now do this by passing `id_str` in the context and retrieving it on the `web_read`. Forward-Port-Of: odoo/enterprise#123757 Forward-Port-Of: odoo/enterprise#113701
The project forecast view was updated so its subtask button correctly connects to the current subtask action. This prevents a small interface mismatch and helps users access subtasks reliably from project task views.
Original PR description
Issue --- The inherited xpath still targets the old action-based subtask button Fix -- Update the inherited xpath to target action_open_subtasks. task-5966684 Forward-Port-Of: odoo/enterprise#124721 Forward-Port-Of: odoo/enterprise#123035
This update keeps planning field service activity tracking working with the latest mail tracking changes. It is a small internal compatibility fix that helps ensure logged updates continue to use the correct notification category.
Original PR description
Rename `_track_subtype` to `_track_log_get_default_subtype` to align with the updated mail tracking. Related Commit https://github.com/odoo/odoo/pull/248505/changes/9c1ce65cdd924b50df3eeef5c69cac110d1eb26b Forward-Port-Of: odoo/enterprise#125666
This fix prevents an intermittent error when the signing document preview is closed or removed while still loading. It improves stability in the Sign app and helps keep automated checks from failing unexpectedly.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
This update fixes an unstable automated test in Web Studio that could fail unpredictably. It helps keep the quality checks reliable so future changes can be validated with fewer false alarms.
Original PR description
runbot-error-940371 Forward-Port-Of: odoo/enterprise#125319
This fix ensures Belgian payroll structures keep their accounting journal settings when a new Belgian company or branch is created. It prevents missing payroll accounting configuration, reducing manual cleanup and helping payroll setup work correctly for new entities.
Original PR description
Steps to reproduce: 1. A structure related to BE, and set journal_id. 2. Create a new BE company or branche of the existing company. 3. Go to the created structure, the journal_id is empty. Root cause: After creating a company, _configure_payroll_account should be triggered to finish the configuration. Setting the journal_id for the existing structures (with the same company country) is part of that configuration. The method responsible to call the configuration, is _load_payroll_accounts in account_chart_template.py (hr_payroll_account), and it should call the following method: _configure_payroll_account_generic_coa. This method was deleted in master and that was the problem. task-6394082
AI chat now continues to suggest reopening the most relevant previous conversation even after the user reloads the page. This makes it easier for users to resume recent work while avoiding duplicate prompts when that chat is already open.
Original PR description
Purpose: -------- When launching an AI chat, users can be suggested to reopen the latest non-empty chat matching the same interface key and record. This suggestion used to rely on chats already present in the frontend store, so it was lost after a page reload. With this commit, the suggested channel is selected by the backend whenever the AI channel is added to the store and included in its channel data. This keeps the suggestion available after a page reload while hiding it when the previous chat is already open, but not when it is minimized. Task-6354153 Forward-Port-Of: odoo/enterprise#123044
Changing a pricelist on a subscription order now correctly refreshes the related pricing calculations. This helps prevent incorrect subscription prices or totals after sales teams update pricing terms.
This update fixes an unreliable automated test in Web Studio that could fail unpredictably. It helps keep validation runs stable so development teams can detect real issues faster and avoid delays caused by false test failures.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
Payroll module upgrades are now protected from a crash that could happen when optional payroll warning checks ran too early. This helps businesses complete payroll updates more reliably without being blocked by missing temporary setup data.
Original PR description
task-6345962 Forward-Port-Of: odoo/enterprise#122247
WhatsApp conversation headers now use the correspondent's uploaded photo instead of a generated initials icon when one is available. This makes the chat header match the member list and gives users a more consistent, recognizable experience in Discuss.
Original PR description
Unlike live chat, WhatsApp did not override channel avatar generation. The generic implementation therefore always generated an initials SVG for the channel. This gave the channel its own avatar cache key and prevented the client-side avatar URL from falling back to the correspondent's uploaded photo. As a result, the partner photo appeared in the member list but not in the Discuss header. Override WhatsApp avatar generation to return no channel avatar when the WhatsApp partner has an uploaded image. The existing client-side logic then falls back to the correspondent's avatar URL. Before: <img width="653" height="179" alt="image" src="https://github.com/user-attachments/assets/9ec5bf86-bce4-4c5b-b2ba-b09c9b6c8282" /> After: <img width="478" height="203" alt="image" src="https://github.com/user-attachments/assets/f3318257-113a-4652-9f76-522ed60e3b80" /> task-6425285