Tuesday, September 1, 2026
22 changes · saas-18.4
Resolved issues and error corrections
Fixes a problem where choosing a website theme could leave key design elements, such as the header and footer, unchanged. This ensures newly selected themes are fully applied during setup, giving users the expected website appearance.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283174
Mobile invoice views now show the invoice line description when no product is selected. This prevents blank cards, making productless invoice lines easier to identify and review on phones.
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
The Guatemala electronic invoicing localization now uses the updated tax calculation for regular gasoline containing 10% alcohol. This matters because, from August 22, only 90% of the gallons are taxable, keeping new customer accounting templates aligned with government rules.
Original PR description
Starting August 22nd Regular Gasoline is changing to a version that contains 10% alcohol. Because of this, the government is only taxing 90% of the gallons since the 10% alcohol portion is exempt. This will update COA for new customers, any current dbs who need to use the new formula can manually update theirs to include the * 0.9 portion. task-6483303 Forward-Port-Of: odoo/enterprise#129483 Forward-Port-Of: odoo/enterprise#129412
The Polish bank account verification flow now handles partner records that are missing tax or bank account details without crashing. This lets users verify mixed partner selections more reliably, while incomplete records are skipped or handled safely instead of interrupting the process.
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 fixes address positioning on German DIN5008 invoices sent by post, so recipient and invoice information blocks align correctly in snailmail letters. Regular DIN5008 invoice layouts remain unchanged, reducing the risk of unintended formatting changes.
Original PR description
**Steps to reproduce:** - Install l10n_din5008 and Accounting. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer…
**Steps to reproduce:** - Install l10n_din5008 and Accounting. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer invoice using the DIN5008 report layout. - Select Send by Post. - Enable Developer Mode and navigate to Settings → Technical → Email → Snailmail Letters. - Open the generated letter and send it. **Observed behavior:** The address blocks are incorrectly aligned when the DIN5008 report is rendered for snailmail. The information block and recipient address do not follow the expected vertical positioning. **Cause:** The DIN5008 layout previously applied vertical alignment rules to its table cells. These rules were removed while adapting the layout to the invoice table structure and its customizations, such as the position column and line numbering. While this alignment is no longer required for the regular DIN5008 invoice layout, the snailmail layout relies on it to correctly position the sender/invoice information and recipient address blocks. **Fix:** Add a `snailmail` class to the DIN5008 invoice section when `snailmail_layout` is present in the rendering context. Restore the required vertical alignment rules scoped to this class so they only affect snailmail reports, without changing the regular DIN5008 layout. **References** * **PR:** [#201225 – DIN5008 layout improvements](https://github.com/odoo/odoo/pull/201225) * **Ticket:** [6387869](https://www.odoo.com/odoo/project/49/tasks/6387869) opw-6387869
French PDP invoice responses are now sent through only the PDP channel instead of being duplicated through both PDP and classic Peppol. This reduces duplicate chatter and keeps invoice communication clearer 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
This fixes an inventory issue where packaged delivery quantities could be assigned to the wrong order line when processing whole packages. Businesses avoid unnecessary backorders and stuck transfers after the shipment has already been handled.
Original PR description
### Steps to Reproduce: 1. Make sure that the Sale and Inventory modules are installed 2. Enable Multi-Step Routes and Packages in Inventory Configurations 3. Warehouse configuration > Outgoing…
### Steps to Reproduce: 1. Make sure that the Sale and Inventory modules are installed 2. Enable Multi-Step Routes and Packages in Inventory Configurations 3. Warehouse configuration > Outgoing shipments > Select Pick then Deliver (2 steps) 4. Routes > Deliver in 2 steps (pick + ship) > Pull From > Destination Location > Select WH/Output 5. Routes > Deliver in 2 steps (pick + ship) > Push To > Action > Change to Pull From 6. Operation Types > Delivery Orders > Packages > Enable Move Entire Packages 7. Go to any product, ex. Drawer > On Hand > Set original on hand qty to 16 and new lot to 50 8. Create a new SO and make 2 lines, with the same product, and change the second line's price to something else, ex. 80.0 9. Deliveries > WH/PICK/00001 > Set quantity to 4 > Put in Pack > Validate and Create Backorder 10. WH/PICK/00002 > Put in Pack > Validate 11. WH/OUT/00012 > Mark PACK0000001 Done > Save. Observe how the first line quantity is changed from 3 to 4 12. Mark PACK0000002 Done > Save > Validate > Observe how it's asking for a backorder even though we already packed all 5 items. ### Description of the issue/feature this PR addresses: Instead of using the `product_qty` from the stock move, use the quantity of the move line to correctly allocate the quantities in StockPackageLevel ### Current behavior before PR: In the Shop Floor when loading packages, marking the package level as done causes issues on the quantity processed on the corresponding move lines. On stock transfers, we currently allocate the Quantity Done to the wrong product line. The total quantity is correct, but the distribution across lines does not match the Demand values. This causes the transfer to remain stuck in Reserved, even though the shipment was already processed operationally. ### Desired behavior after PR is merged: The correct quantity from the move line is used and this resolves the issue with quantity distribution not matching move line quantities when using packages. opw-6040640 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#242487
Invoice pages in the customer portal now show the same limited salesperson information as sales order pages. City and phone details are no longer displayed, helping avoid unintended exposure of personal contact information.
Original PR description
This change aligns the salesperson's information shown to customers on the invoice view with those shown on the sales order view. Now city and phone number are not shown and both views are consistent. This information can be personal information not supposed to be leaked to customers especially the salesperson's city in case of home office. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278497
This fixes an issue where automated mobile tests could randomly miss a tap when the app was busy processing related work. The change makes test results more stable and helps prevent false failures during quality checks.
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#284971Product variant prices now inherit the same minimum decimal display settings as their product templates. This ensures reports and Studio customizations show prices consistently, avoiding confusing differences such as 19.50 appearing as 19.5.
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
The website editor no longer shows theme background choices for tab sections because those choices did not work reliably in this version. This prevents users from selecting an option that would have no effect, making page editing clearer and more predictable.
Original PR description
The theme background options (`o_cc` classes) on the `s_tabs` snippet's tabs doesn't work since 18.4 (html_builder refactor). It was not supported either in previous versions. We decided to fix it so it would be useable in master (20.0) but leave stable versions as is, by restraining the available tabs and removing the theme one. task-5951656
A problem in the mail test helpers caused one timed-out test to keep running checks and incorrectly fail many later tests. This fix stops those repeated checks once the failing test is done, making test results clearer and reducing false failure noise for release validation.
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#285585This fix changes the order of final browser test cleanup so memory information is logged before the test result is reported. It prevents failed test runs from producing 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 Frontdesk app now explicitly includes a required planning view component so it can install correctly in setups that do not auto-install related apps. This prevents installation failures in specific single-app deployment scenarios and improves reliability for customers using Frontdesk on its own.
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
This fix prevents restaurant POS orders from losing their order lines when the same table is used across multiple devices before payment. It ensures paid orders keep the correct products and totals, reducing the risk of incorrect sales records and follow-up corrections.
Original PR description
Steps to reproduce: - Restaurant config with two POS devices on the same session - Device A: open a table, add two products, press Order (the order is synced as a draft, its lines get server ids) -…
Steps to reproduce:
- Restaurant config with two POS devices on the same session
- Device A: open a table, add two products, press Order (the order is synced as a draft, its lines get server ids)
- Device A: remove both lines, without syncing
- Device B: touch the same order, so device A re-reads it from the server through the synchronisation websocket
- Device A: pay and validate the order
Issue:
The order is saved as paid, with its total and its payment, but without any orderline. The lines are deleted on the server: odoo.models.unlink: deleted pos.order.line records with IDs: [...]
Cause:
Removing an orderline queues an unlink command in
models.commands['pos.order'].unlink['lines_<order id>'] (delete_ in related_models.js). That command is only discarded by clearCommands(), which syncAllOrders() calls after a successful sync, so it stays pending in between.
Any read of the order in that window puts the line back: a deleted record counts as missing in missingRecursive(), so it is fetched again and loadData() re-creates it with its server id.
serialize() then emits both the update of the live line and the still pending unlink, and sync_from_ui writes
lines: [[1, id, {...}], [3, id]]. The ORM applies commands in order, and pos.order.line.order_id is ondelete='cascade', so Command.UNLINK deletes the line right after writing it.
Fix:
Skip a removal command when the record is still linked to the parent at serialization time. A record cannot be both linked and removed in the same payload, so the pending command is stale and dropping it keeps the local state. Genuine removals, where the record is no longer linked, are still sent.
opw-6401146
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#285427
Forward-Port-Of: odoo/odoo#284695This fix prevents web test runs from hanging until a long timeout when required dependency data cannot be fetched. Instead, the test run reports the fetch failure immediately, helping teams identify infrastructure issues faster and reducing wasted build 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#284980Argentine export invoices now send the correct recipient identification information in the QR validation data. This prevents ARCA from showing the wrong ID type and allows these invoices to be verified as valid legal documents on the official ARCA page.
Original PR description
Before this change we were sending id type code 0 and this generate two problems * ARCA verification page it was wrongly taking "CI Policia Federal" as the identification type of the receptor * We were not able to validate the expo invoice, we get always an error With this change the expo invoice can be checked as a real legal document in the ARCA page https://servicioscf.afip.gob.ar/publico/comprobantes/cae.aspx Forward-Port-Of: odoo/enterprise#126704
Fixes Polish e-invoicing so K_12 taxes are correctly treated as reverse charge in KSeF XML exports. This helps invoices using the 0% EU U tax report the right reverse charge status and tax base, reducing compliance and reporting errors.
Original PR description
**PROBLEM** K_12 taxes needs to be reported as reverse charge tax. **STEP TO REPRODUCE** 1. Create an invoice with the tax 0% EU U. 2. Send the invoice the ksef. 3. Open the xml, an notice P_18 value is 2 (meaning no reverse charge), and there is no tag P_13_10. expected behavior: P_18 = 1, P_13_10 = base for the tax. opw-6460338 Forward-Port-Of: odoo/odoo#281934
Event agenda pages now scroll more smoothly in Firefox and Safari when many agenda items create a horizontal scrollbar. This improves the visitor experience by preventing the agenda from shaking or jumping during sideways scrolling.
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
The Kenya electronic invoicing form no longer leaves an empty gap when there is no validation message to show. This keeps the invoice form layout cleaner and avoids visual confusion for users.
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
Accountants can now generate BOE files for Spanish Modelo 115 tax reports without needing company access-rights permissions. This removes an incorrect access error caused by the export wizard trying to save company-related data that users were not actually editing.
Original PR description
Users who only have accounting rights (not the Settings > Users Companies > Access Rights group) get an access error on the Companies model when generating the BOE file for the Modelo 115 tax…
Users who only have accounting rights (not the Settings > Users Companies > Access Rights group) get an access error on the Companies model when generating the BOE file for the Modelo 115 tax reports, even though exporting a BOE file has nothing to do with editing company configuration and should be available to any accountant. Steps to reproduce: ------------------- * Log in as a user with accounting rights only (not part of the Companies > Access Rights group) * Go to Accounting > Reporting > Tax Return, open the Mod 115 report * Click the gear icon > BOE > Generate BOE > Observation: An AccessError is raised: "You are not allowed to modify 'Companies' (res.company) ... This operation is allowed for the following groups: Access Rights", even though the user is not trying to edit the company. Why the fix: ------------ The BOE wizard shared by Mod 111/115/303 declares a `company_partner_id` field, related to `company_id.partner_id`, with `readonly=False`. That field is invisible in every view and only exists to compute the domain of `partner_bank_id`; it was never meant to be edited by the user. Because it is declared writable, the ORM attaches an inverse to the related field, so saving the wizard (which happens when generating the BOE, since the field, though invisible, is still part of the view and thus of the saved values) writes `company.partner_id` back onto `res.company`, even though the value never actually changes. That implicit write requires write access on res.company, which is only granted to the Access Rights group, causing the error for regular accountants. Dropping `readonly=False` keeps the field as a plain readonly related field, still usable for the bank account domain, without ever triggering that spurious write. opw-6388869 Forward-Port-Of: odoo/enterprise#129841 Forward-Port-Of: odoo/enterprise#126661
This update adds a missing dependency needed by the Ecuador electronic invoicing module. It prevents installation failures in cases where the related payment component was not automatically installed, improving reliability for affected deployments.
Original PR description
Since #83178 `l10n_ec_edi` hooks a view on the div named `invoice_paid_badge`. That div was added (/ named) in the autoinstall module `account_payment`, but `l10n_ec_edi` only depends on `account_edi` which only depends on `account`, leading to the view failing when installing without auto install. https://runbot.odoo.com/odoo/error/946047