Tuesday, September 1, 2026
22 changes · saas-19.1
Resolved issues and error corrections
Mobile invoice views now show the invoice line description when no product is selected. This prevents blank cards from appearing, making invoice review clearer for users working on phones or small screens.
Original PR description
Invoice lines can be created without a product. However, the mobile kanban view does not handle such lines properly and displays an empty card without a name or image. This commit adapts mobile kanban view to show invoice line's name when `product_id` is not set. Before | After -- | -- <img width="469" height="277" alt="image" src="https://github.com/user-attachments/assets/3b367581-b73d-4b12-a487-1a54c3b88470" /> | <img width="406" height="300" alt="image" src="https://github.com/user-attachments/assets/107d7294-90e8-49c6-826a-9be75c6b799f" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285608 Forward-Port-Of: odoo/odoo#284755
Fixes an issue in the HTML editor where replacing a selected URL link with a pasted URL updated the destination but kept the old visible text. Users now see the newly pasted URL as the link label too, reducing confusion and preventing misleading links in edited content.
Original PR description
**Current behavior before PR:** Steps to reproduce the issue: - Create a link via typing a valid URL + space. - Copy/Paste a different URL from the browser. - Select the entire link you just created. - Paste the copied URL on top of it. Notice that the label is still the old URL even though the URL actually changed. This happens because after commit [1] When pasting a URL over an active text selection, selected content is converted into a link pointing to the pasted URL. This should not be the case if selected content is a link with same label and URL. **Desired behavior after PR is merged:** If a link is entirely selected and its label is the same as URL then it should replace the existing link label with new URL. [1]: https://github.com/odoo/odoo/commit/d356043a67e1d7291bd1302b1e90a2d9a07718da task-6456004 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Polish bank account verification process no longer fails when checking several partners where some are missing tax or bank details. This prevents an error from interrupting the verification of valid partners and makes the process more reliable.
Original PR description
When we check for multiple partners with some valid and some being incomplete (no vat or no bank account), a traceback is raised This was due to a bracket accessor, changed into a get in this commit. no-task Forward-Port-Of: odoo/odoo#285631
Fixed an issue where slower mobile tap actions in automated tests could be mistaken for long presses, causing expected save actions to be skipped. This improves test stability for mobile workflows without changing end-user behavior.
Original PR description
Before this commit, MobileWebSuite.test_unit_mobile failed at random on the mail test "HtmlMail add icon and save inline html", which taps the save button of an html_mail field and waits for the…
Before this commit, MobileWebSuite.test_unit_mobile failed at random on the mail test "HtmlMail add icon and save inline html", which taps the save button of an html_mail field and waits for the write:
[verifySteps] expected the following steps
> Expected: [
"web_save",
]
> Received: []
This happens because a tap held longer than `LONG_TAP_DELAY` counts as a long press, and `_pointerUp` then dispatches no click at all. That delay spans the synthetic pointerdown and pointerup of a single `click()`, so the work a listener does during the press counts towards that delay: tapping save blurs the html field, which converts the whole editor content to inline styles, and under the load of a runbot build that conversion alone takes longer than the delay.
One solution could have been to raise `LONG_TAP_DELAY`, but a listener slower than the new value suppresses the click again.
This commit counts a tap as long only when the test releases the pointer itself, with `pointerUp`, so the work a listener does during a `click()` no longer suppresses the click.
https://runbot.odoo.com/odoo/error/946581
Forward-Port-Of: odoo/odoo#285640
Forward-Port-Of: odoo/odoo#284971Manufacturing bills of materials now prevent configurable combo products from being selected as components. This avoids using sales bundle items where physical manufacturing parts are expected, reducing confusion and incorrect production setup.
Original PR description
Version: --------- - 19.0+ Steps to reproduce: ------------------- - Install `mrp` and `sale_management` - Create a product of type `combo` - Go to Manufacturing > Products > Bills of Materials - Create or edit a BoM - Add a component line - Select the combo product Issue: ------ Combo products can be selected as BoM components. Since combo products represent configurable sales bundles rather than physical products, they are not meaningful manufacturing components. Before Commit: ------------------- - It was possible to select a product of type 'combo' as a component in a Bill of Materials. After Commit: ----------------- - Combo products are filtered out of the component picker and cannot be added as BoM components --- opw-6425024 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278861
This fix prevents users from deleting the image inside a website card cover while leaving behind an empty placeholder. It avoids broken card settings and potential errors when editing website snippets.
Original PR description
It was possible to remove the image inside a card cover while keeping the figure wrapper. The card option would then still consider that there was a cover image even though the image was gone, which could also lead to a traceback. Steps to reproduce: - Insert the `s_three_columns` snippet - Click on the image of one card - Either press "Enter", "Delete", "Backspace" - Hover the "Cover Image" options => The image is removed but the `<figure>` is still there, so the option is still considered active (leading to a traceback) task-6081728 Forward-Port-Of: odoo/odoo#283106 Forward-Port-Of: odoo/odoo#280086
This update fixes typos and wording inconsistencies in the Point of Sale LNA checklist. It improves clarity for users reviewing the checklist without changing any business process or functionality.
Original PR description
Fixed some typos and inconsistencies on the LNA checklist document Task-[6330795](https://www.odoo.com/odoo/project/1737/tasks/6330795) 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 Forward-Port-Of: odoo/odoo#281950
Responses to invoices received through the French PDP system are now sent through only the PDP channel instead of both PDP and classic Peppol. This prevents duplicate chatter messages and reduces confusion for users following invoice communication history.
Original PR description
When responding to an invoice received through PDP, 2 responses were actually sent: one through PDP and the other through the 'classic' Peppol. This was done to allow more reliability, in case one channel is down when trying to respond, but this mainly creates cluttah' in the chattah' (call me busta rhymes yo) task-6522652 Forward-Port-Of: odoo/odoo#285596
This update adds test coverage to confirm that shared spreadsheets and spreadsheet editing continue to export correctly to Excel when images are included. It helps prevent regressions that could affect users sharing or downloading spreadsheet files with visual content.
Original PR description
Counterpart of https://github.com/odoo/odoo/pull/279788 Task-6432724
Users can no longer create order boxes from the point-of-sale printer settings. This helps ensure each order box is only set up when paired with a real physical device, reducing configuration mistakes.
Original PR description
We prevent users from creating oboxes from pos.printer model, as oboxes should be paired with an actual device.
Swiss payroll no longer records automatic pension mutation refreshes in employee history. This prevents routine background updates from cluttering the activity log, making important changes easier to find.
Original PR description
Calling `_create_or_update_snapshot` after writing on an employee recomputes `lpp_mutations`, deleting and recreating the linked records. Because `lpp_mutations` was tracked, every `write` on an employee generated unhelpful chatter entries, cluttering important history. This was especially noisy during frequent writes in hourly crons. Disable field tracking on `lpp_mutations` to improve chatter clarity and overall user experience. opw-6285407 --- Forward-Port-Of: odoo/enterprise#129481 Forward-Port-Of: odoo/enterprise#128033
This fix prevents automated test failures from being reported twice because a final memory log was written after the browser test had already ended. The memory information is still captured, but it is now logged before the final test result so teams see the real failure more clearly.
Original PR description
Before this commit, a build whose unit tests suite fails collects a second runbot error on top of the real one: odoo.addons.web.tests.test_js.WebSuite.test_unit_desktop.browser: Error received after…
Before this commit, a build whose unit tests suite fails collects a second runbot error on top of the real one:
odoo.addons.web.tests.test_js.WebSuite.test_unit_desktop.browser:
Error received after termination: [MEMINFO] tests done (after GC)
- used: 220535896 - total: 341990868 - limit: 4395630592
Note that the figures themselves are fine (220MB used of a 4.4GB limit): the error is not about memory, only about when the line is logged.
This happens because the runner logs that line after `stop()`, and `stop()` is what reports the suite result: the server settles the test on that report and kills the browser. The final major GC outlasts the report. A passing build escapes because the browser dies within milliseconds; a failing one stays up for the screenshot, long enough for the GC to finish and the line to land after termination.
This commit fixes the issue by moving `stop()` after the final cleanups and their memory log: the [MEMINFO] line is still logged, but before the result report, while the server still waits on the browser.
https://runbot.odoo.com/odoo/error/229655
Forward-Port-Of: odoo/odoo#284957This fixes an internal testing issue where a failed setup request could leave automated web tests waiting until a long timeout. Test failures are now reported promptly, helping teams identify build problems faster and reducing wasted CI time.
Original PR description
Before this commit, a unit test suite could go silent between two test files, and `browser_js` then waited out its whole timeout before failing with:
[ERROR] TypeError: Failed to fetch
at orm (web.assets_unit_tests.min.js)
FAIL: WebSuite.test_unit_desktop
AssertionError: Script timeout exceeded
This happens because `fetchDependencies` gives every addon a `Deferred` that only the success handler of the batched `all_dependencies` call resolves, and a loaded runbot host answers that call with `RuntimeError: can't start new thread`. Nothing then settles those deferreds, so the `Promise.all` waiting on them never returns, `stop()` is never called, and the browser holds the build until the timeout.
This commit rejects the deferreds of a failed batch and reports an error escaping `runTests` on the console, so the build fails on the fetch error instead of running out its timeout.
https://runbot.odoo.com/odoo/error/243504
Forward-Port-Of: odoo/odoo#284980Product variant prices now keep the same minimum decimal display as the product template price they come from. This prevents reports and Studio customizations from showing shortened prices, such as 19.5 instead of 19.50, improving consistency in customer-facing documents.
Original PR description
Issue: --- Record's `min_display_digits` is not inherited in case of a model inheritance. e.g. `list_price` is inherited to `product.product` from `product.template`, however it renders with fewer decimals than `product.template.list_price` in reports. Steps to reproduce: 1- Set a product's Sales Price to 19.5. 2- Add `product.product.list_price` to a report using studio. The variant's field renders with 1 decimal while `decimal.precision` is 2. Cause: --- This is missed in ee32a17495a10af18f0b5de0a295283c5059d3c2 which introduces minimum precision. opw-6465159 Forward-Port-Of: odoo/odoo#285336 Forward-Port-Of: odoo/odoo#285064
A mail test helper now stops repeating checks after a timeout instead of letting one failed test trigger many unrelated failures. This makes automated test results clearer and helps teams identify the real cause of a problem faster.
Original PR description
Before this commit, one test contains() reaching its 10 seconds budget made the 129 tests that ran after it fail with its own assertion, over 14 suites:
[HOOT] Test "@mail/message/link_preview/Delete all link previews at
once" failed:
Failed assertion:
3. [toBe] expected values to be strictly equal (Failed to find 1 of ".o-mail-Message-body:text(...)" (Timeout of 87 seconds). Found 0 instead.)
This happens because the tick re-schedules itself on the result of runOnce(), which is undefined on a failure, the crashing one included. The check keeps selecting every 500ms and logs its assertion against whichever test is running, until a tick lands between two suites and getFixture() throws.
This commit re-schedules a tick only while the check is not done, so the crashing one is the last.
https://runbot.odoo.com/odoo/error/946650
Forward-Port-Of: odoo/odoo#285585The Kenya e-invoicing form now hides the validation message area when there is no message to show. This removes an unnecessary gap in the invoice form, making the screen cleaner and easier to read.
Original PR description
When there is no validation message, an empty div causes a whitespace gap between the header and the sheet in the form view. This commit adds `invisible="not l10n_ke_validation_message"` to the div to prevent this issue. Forward-Port-Of: odoo/enterprise#129364 Forward-Port-Of: odoo/enterprise#129318
This fix prevents upgrade warnings when employee records temporarily have no version during the HR migration process. It helps keep upgrade logs cleaner and avoids a harmless but confusing error while employee data is being backfilled.
Original PR description
### Issue: A warning `IndexError: tuple index out of range` is logged on RunBot when upgrading from 18.0 to 19.0 for employees without any version ### Cause: `_get_version` on `hr.employee` falls…
### Issue: A warning `IndexError: tuple index out of range` is logged on RunBot when upgrading from 18.0 to 19.0 for employees without any version ### Cause: `_get_version` on `hr.employee` falls back to `versions[0]` when no version matches the given date But if the employee has no versions at all, `versions` is empty and `versions[0]` raises an `IndexError` ### Steps to reproduce: - Create a database with `hr_attendance` installed in 18.0 - Upgrade to 19.0 Before the fix, a warning is logged during the upgrade ### Notes: An employee without any version is a transient state during upgrade `hr/saas~18.4.1.1/end-migrate.py` backfills a version for every employee still missing one (`current_version_id IS NULL`) once the whole upgrade chain is done Since it only runs at the very end, an employee can still be found without a version by earlier steps (e.g. modules reloading their demo data), which is when this warning was logged Confirmed on an upgraded RunBot database that employees without a version before the upgrade do end up with one once fully completed runbot-241187 Forward-Port-Of: odoo/odoo#284467
This update keeps Odoo compatible with newer system versions of a certificate library used for secure connections. It prevents unnecessary warning messages and helps certificate-based email and connection features continue working reliably across different deployments.
Original PR description
pyOpenSSL 24.3.0 deprecated passing its own X509/PKey objects to Context.use_certificate()/use_privatekey(), and started accepting cryptography objects instead. Odoo pins pyopenssl 24.1.0, but the distro builds run the version shipped by the OS: since the test added by f0fb287c6502 covers that path, they now add a warning in the logs. Load the certificate and the key as cryptography objects when the installed pyOpenSSL supports them, keep the previous loaders otherwise. Reference: https://github.com/pyca/pyopenssl/commit/b0cb4b4 This fix is based on https://github.com/odoo/odoo/blob/a2b4f618328f3ce3f654fd2c1ee4410365706a7e/odoo/addons/base/models/ir_mail_server.py#L34-L46 runbot-944176 Forward-Port-Of: odoo/odoo#284802 Forward-Port-Of: odoo/odoo#277449
Event agenda pages now scroll horizontally more smoothly in Firefox and Safari when many agenda items are shown. This prevents visible shaking or stuttering, improving the browsing experience for event visitors.
Original PR description
On Firefox and Safari, horizontal scrolling on an agenda with many items stuttered. This was likely caused by triggering too many scroll events, without throttling them. Steps to reproduce: - On Firefox or Safari, run with demo data - Go to the "Design Fair Los Angeles" agenda (click on the event > Talks > Agenda. Alternatively, enter the URL directly: `/event/ID/agenda`, with the right event ID) - Resize the page (or open the dev tools) so that there is a horizontal scrollbar. - Scroll horizontally with a trackpad or with shift + mouse wheel. => The agenda stutters/shakes: as you go to the right, it sometimes slightly goes back left, and vice-versa. You might have to scroll from left to right and right to left a few times to see the issue. Forward-Port-Of: odoo/odoo#285237
Frontdesk now explicitly includes the component needed to load its planning timeline views. This prevents installation failures in setups where automatic optional apps are skipped, making deployments more reliable.
Original PR description
Installation of this module fails in single-app skip auto-install. Gantt is not a valid root element in views when web_gantt isn't installed. There is no error on other builds because of the auto-install dependency using the following chain; [frontdesk] ──[depends]──> [hr] ──[depends]──> [web] ──⚡[AUTOLOAD]──> [web_gantt] This change needs forward porting to v19. saas-19.1 already has a fix. REF Runbot; https://runbot.odoo.com/odoo/error/237890 Forward-Port-Of: odoo/enterprise#128592
Opening Project Update items from the activity menu now shows only updates that have the current user's activities for the selected timing bucket. This prevents users from seeing unrelated project updates and makes activity follow-up clearer and more accurate.
Original PR description
**Problem:** Opening a Project Update activity from the activity menu (the clock icon in the systray) lists every project update of every user, instead of the ones carrying the current user's…
**Problem:**
Opening a Project Update activity from the activity menu (the clock icon in the systray) lists every project update of every user, instead of the ones carrying the current user's activities.
**Steps to reproduce:**
1. Schedule an overdue activity on a project update
2. Have a colleague create another project update with no activity
3. Click the clock icon in the systray
4. Under "Project Update", click the "Late" count
**Current behavior:**
The list opens unfiltered and shows all project updates, including the ones of other users and the ones carrying no activity at all.
**Expected behavior:**
The list shows only the updates carrying the user's own activities, restricted to the bucket that was clicked.
**Cause of the issue:**
The activity menu never builds a "my activities" domain. `openActivityGroup` in `mail/static/src/core/web/activity_menu.js` narrows the generic act_window it opens purely through context keys — `search_default_filter_activities_my` plus `search_default_activities_overdue` / `_today` / `_upcoming_all` — and the only domain it forwards comes from `_get_activity_groups`, which is limited to `[('active', 'in', [True, False])]`. A `search_default_<name>` key is resolved against a filter of that name in the model's search view, and is silently dropped when no such filter exists. `project.update`'s search view never declared them, so every key the menu sends is discarded and the action opens on an empty domain.
**Fix:**
`project.project` and `project.task` — the addon's two other `mail.activity.mixin` models — already declare this block of invisible activity filters, as does every other model reachable from the activity menu. Declaring them on `project.update` is what makes the menu's context keys resolvable, and keeps the model consistent with the rest of the codebase instead of special-casing `project.update` on the client side.
opw-6416397
Forward-Port-Of: odoo/odoo#281511Code cleanup and technical improvements
This update restructures how Factur-X electronic invoices are generated, replacing an older template-based approach with a more structured internal method. The change should make future updates and localization needs easier to support while keeping the business output the same.
Original PR description
*= account_edi_ubl_cii_tax_extension, l10n_account_edi_ubl_cii_tests. Refactoring of the export of factur-x. The export now relies on a dict of nodes, and uses the function `dict_to_xml` to generate the xml instead of relying on a qweb template. task-5999127 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261572