Tuesday, September 1, 2026
22 changes · saas-19.3
Resolved issues and error corrections
The mobile invoice line view now shows the line description when no product is selected. This prevents blank invoice cards and makes productless invoice lines easier to identify on mobile devices.
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
This update fixes how the translation test module applies temporary changes so they remain compatible across tenants and after the module is uninstalled. It reduces the risk of test-related behavior leaking into other environments or causing cleanup issues.
Original PR description
Fix patch for test_translation_mode Patch tools in a compatible way which will work for other tenants. Patch tools in a compatible way which will work after uninstallation. python code translation is not patchable by design. 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
The Ecuador electronic invoicing module now installs correctly even when optional payment features are not installed. This prevents setup failures in automated environments and keeps withholding portal pages from showing a misleading paid badge when that badge is available.
Original PR description
When installing l10n_ec_edi with --skip-auto-install we receive an error on Runbot. Anchored on the sidebar title (always present on account.portal_invoice_page) rather than div[name='invoice_paid_badge'], which only exists when account_payment (not a dependency of this module) is installed and inherits this view to add it. Hides the account_payment "Paid" badge, if present, without requiring it to exist. runbot-237864 Forward-Port-Of: odoo/enterprise#129291 Forward-Port-Of: odoo/enterprise#126918
The website shop search bar now shows its placeholder text in the visitor's selected website language. This improves the shopping experience for multilingual websites by avoiding untranslated English text in localized storefronts.
Original PR description
Problem: The search bar placeholder text is not being translated. Steps to reproduce: 1. Install e-Commerce 2. Go to Website > Configuration and add another language for the website 3. Go to Website > Shop 4. See how the search bar placeholder text is "Search" instead of being in the website's language Cause: The text was not extracted for translation because it is set inside `t-value=`. To be available for extraction, it should either be set inside `t-valuef.translate=` or should be the data content between the tags. opw-6486429
The Polish bank account verification process now handles mixed partner lists where some records are missing a tax ID or bank account. This prevents unexpected errors and lets valid partner verifications continue more reliably.
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
This change makes an internal website test reliable when multiple test suites run at the same time. It ensures the test starts from the expected setup, preventing false failures caused by demo data from other modules.
Original PR description
# Before this commit: The image controller performance test expects the admin partner to be unpublished. In parallel test runs, the website_partner demo data publishes the admin partner, causing the…
# Before this commit:
The image controller performance test expects the admin partner to be
unpublished. In parallel test runs, the website_partner demo data
publishes the admin partner, causing the test to follow a different
code path and fail.
However, during parallel test execution, the website_partner module
installs its demo data, which updates the admin partner:
```
<record id="base.partner_admin" model="res.partner">
<field name="is_published">True</field>
</record>
```
As a result, user_admin.website_published becomes True.
# After this commit:
The test explicitly restores the required precondition by setting the
admin partner's is_published value to False before executing the
performance check.
As a result, the image controller always follows the expected
"unpublished" code path, making the test deterministic regardless of
whether website_partner or any other module with demo data has already
been installed during parallel testing.
Runbot-241102
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prInvoice responses received through the French PDP flow are now sent back through a single channel instead of being duplicated through PDP and classic Peppol. This reduces duplicate chatter and keeps invoice communication cleaner for users.
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
The Belgian payroll attendance test was updated to avoid failures when demo employee data changes the company worker count. This keeps automated checks stable without changing payroll behavior for users.
Original PR description
The FFE employer contribution rate depends on the company's current worker count. Additional demo employees installed on runbot can move the company across the applicable threshold and change the expected payslip amounts. This commit update the test expectations according to the computed worker count. [error-939674](https://runbot.odoo.com/odoo/error/939674) Forward-Port-Of: odoo/enterprise#126887
This fixes an issue where automated mobile tests could randomly miss a tap when the app took longer than expected to process it. It makes test results more reliable, reducing false failures in quality checks 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#284971This fixes a flaky mail test by ensuring the emoji suggestion menu is closed before the test submits a message. It helps keep automated validation reliable without changing the user-facing mail experience.
Original PR description
Before this commit, "[text composer] Posting message should transform relevant data to emoji." posted no message on runbot:
Failed to find 1 of ".o-mail-Message-body:text('test ...')"
(Timeout of 10 seconds). Found 0 instead.
This happens because "test :P :laughing:" leaves the emoji suggestion of the shortcode it just typed pending, and Composer.onKeydown returns without posting when the NavigableList takes the Enter. The fetch behind that suggestion is debounced by 250ms, so the test posts only while the debounce has not fired.
This comes from "[IMP] web,*: emoji loader": the search reads the emoji data the mail test helpers preload, so the list has an entry to offer where it had none.
This commit types a trailing space, which closes the suggestion and leaves the Enter to post.
https://runbot.odoo.com/odoo/error/946650
Forward-Port-Of: odoo/odoo#285616Users can now add a new group in grouped list views that show totals without triggering an error. This prevents interruptions in everyday workflows such as organizing CRM records by contact.
Original PR description
Adding a new group on a grouped list view with aggregates gives a traceback. This comes from `getFieldCurrencies` and `computeAggregates` which didn't guard for group with no currency aggregates (like a newly created group). Steps to reproduce: - open a list view (CRM) - group by a m2o (Contact) - click on 'Add a Contact' - press Enter => Traceback Forward-Port-Of: odoo/odoo#285438 Forward-Port-Of: odoo/odoo#285325
Manufacturing bills of materials now prevent combo products from being selected as components. This avoids using configurable sales bundles as if they were physical items, reducing incorrect manufacturing 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
Product variant prices now keep the same minimum decimal display settings as the product template price they come from. This prevents reports created in Studio from showing prices with too few decimal places, improving consistency and avoiding confusion in pricing 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 fix prevents one timed-out mail test from continuing to run checks and causing many unrelated tests to fail afterward. This improves the reliability of automated test results, making failures easier to diagnose and reducing noise for developers.
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 web test runner now records its final memory information before reporting the test result. This prevents failed test runs from showing an extra misleading error, making build failures clearer and easier to diagnose.
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#284957The online shop now more precisely identifies the intended product option inputs instead of accidentally matching unrelated fields. This reduces the chance of incorrect behavior on product pages and helps keep the shopping experience reliable.
Original PR description
The selector was matching unrelated inputs because it wasn't specific enough. Forward-Port-Of: odoo/odoo#283742 Forward-Port-Of: odoo/odoo#283464
This fix ensures Odoo's web test runs stop and report a clear failure when required test dependencies cannot be fetched. It prevents builds from hanging until a timeout, helping teams identify infrastructure or setup issues faster and keep validation pipelines moving.
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#284980The Indian payroll settings now validate EPF employee IDs using the correct 15-character format. This prevents companies from saving outdated or incorrect EPF identifiers and gives clearer guidance when entering the value.
Original PR description
Steps to reproduce: - Install Indian localization, and use an Indian company - Go to Settings under Payroll > Indian Localization - Tick the "Employee Provident Fund (EPF)" - Insert a EPF Employee ID Issue: The "valid" format is not correct: XX/XXX/1234567/000/1234567 with the first series of 7 numbers having a flexible range from 1 to 7. The first series of 7 numbers must always equal to 7 (it represents the establishment ID), and the last series of number should be dropped as it represents the employee's unique PF account number. Solution: - Modify the constraint for the variable: - Remove last 7 trailing digits from the constraint. - Make the length of the first series of 7 digits strictly equal to 7. - Update placeholder value and help info. Task: 6482315 Forward-Port-Of: odoo/enterprise#128777 Forward-Port-Of: odoo/enterprise#128421
The Kenya OSCU invoice form no longer shows an empty space when there is no validation message to display. This keeps the form layout cleaner and avoids distracting gaps for users reviewing invoices.
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 an upgrade warning when employee data is temporarily missing version information during migration. It helps make upgrades cleaner and more reliable without changing day-to-day HR functionality.
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
Event agenda pages now scroll more smoothly in Firefox and Safari when many agenda items create a horizontal scrollbar. This prevents the agenda from shaking or jumping during sideways scrolling, 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
AvaTax invoice PDFs now keep section or divider rows aligned with the rest of the invoice table when the Taxes column is hidden. This prevents uneven borders and possible blank gaps on longer printed invoices, improving the professional appearance of customer documents.
Original PR description
Steps: 1. Turn on AvaTax for a company (connect it to Avalara). 2. In Settings > General Settings > Invoicing, set the Document Layout to Boxed (Box), just for a clear view. 3. Create a customer…
Steps: 1. Turn on AvaTax for a company (connect it to Avalara). 2. In Settings > General Settings > Invoicing, set the Document Layout to Boxed (Box), just for a clear view. 3. Create a customer invoice: - Use the customer with an AvaTax fiscal position and proper address details. - Add a product with an AvaTax category. - Add a section line (a divider/heading row). - Compute Taxes for the AvaTax. 4. Print the invoice as a PDF. 5. Look at the section/divider row. Its cell border does not line up with the other rows. On longer invoices, this can also cause a big blank gap at the bottom of a page. Cause: When an invoice is computed by AvaTax, the Taxes column is hidden from the PDF (this is intentional, since AvaTax shows tax differently). But a different part of the same template decides how wide the section row should be. This part does not know the Taxes column was hidden, so it still counts it. That makes the section row's width wrong by one column, which breaks the table layout in the PDF. Fix: Instead of hiding the Taxes column only in one place, fix it at the source: the variable that decides (does this invoice show a Taxes column) now also checks if the invoice is an AvaTax invoice. Every other part of the template that uses this variable (the header, the tax cells, and the section row width) automatically gets the right answer, since they all read from the same place. Result: - Section rows on AvaTax invoices now have the correct width. opw - 6455674 Forward-Port-Of: odoo/enterprise#129097