Thursday, September 10, 2026
13 changes · 19.0
Resolved issues and error corrections
Product cards in the website's Dynamic Products snippet now keep the correct spacing when the Chips layout is selected. This prevents cramped or broken-looking product displays outside the shop page, improving storefront presentation for visitors.
Original PR description
Steps to reproduce: --- - Install the website_sale module with demo data. - Go to /shop and switch the product layout to Chips. - Exit the editor. - On the home page, open the editor and add the…
Steps to reproduce: --- - Install the website_sale module with demo data. - Go to /shop and switch the product layout to Chips. - Exit the editor. - On the home page, open the editor and add the Dynamic Products snippet. Issue: --- The Products snippet has collapsed card padding when the Chips layout is active. Root cause: --- - The Chips card layout defines `--_padding-base` using `var(--o-wsale-products-grid-gap)` with no fallback value. https://github.com/odoo/odoo/blob/4307f657c73a860c755e1499138a878268882f7a/addons/website_sale/static/src/scss/product_tile.scss#L632 - When the Products snippet renders outside /shop, the variable is undefined, causing the `calc()` to resolve to a guaranteed-invalid value which collapses the card padding. All other layouts are unaffected because they either do not use `--o-wsale-products-grid-gap` in their padding chain, or already provide a `16px` fallback at the point of use. https://github.com/odoo/odoo/blob/4307f657c73a860c755e1499138a878268882f7a/addons/website_sale/static/src/scss/product_tile.scss#L407-L410 Solution: --- - 16px matches the default value of `shop_gap` on the website model, ensuring correct padding whenever the variable is not explicitly set. https://github.com/odoo/odoo/blob/4307f657c73a860c755e1499138a878268882f7a/addons/website_sale/models/website.py#L128 ### Before: <img width="1456" height="563" alt="image" src="https://github.com/user-attachments/assets/c28ab183-0af3-4a2a-858d-b85d9995eb07" /> ### After: <img width="1427" height="550" alt="image" src="https://github.com/user-attachments/assets/e0ba80ec-10ad-433f-bf9a-acbaffd56a76" /> opw-6511483 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents an installation error that could occur when Latin American checks and stock accounting are installed together for companies outside Argentina. It makes the accounting setup handle missing template data safely, improving reliability during module installation.
Original PR description
**Steps to Reproduce** 1. Install the **l10n_latam_check** module. 2. Install the **stock_account** module. An error occurs: `AttributeError: 'NoneType' object has no attribute 'items'` **Cause**…
**Steps to Reproduce**
1. Install the **l10n_latam_check** module.
2. Install the **stock_account** module.
An error occurs: `AttributeError: 'NoneType' object has no attribute 'items'`
**Cause**
During the `stock_account` post-init process,
`_configure_stock_account_company_data()` calls `_get_chart_template_model_data()`
to retrieve all `account.account` template data associated with the company's chart template and its
parent templates.
When `l10n_latam_check` is installed, `_get_chart_template_model_data()` executes all registered
`account.account` template methods, including `_get_latam_check_outstanding_account_account()`.
This method only returns account definitions when the company country code is included in
`_get_third_party_checks_country_codes()` (only `'AR'`). For companies
belonging to other countries, the method implicitly returns `None`.
Since `_get_chart_template_model_data()` directly iterates over the result using `.items()`,
the installation flow attempts to execute `.items()` on a `None` value raising:
`AttributeError: 'NoneType' object has no attribute 'items'
`
**Solution:**
```
data = func(self, template_code)
if data is not None:
for xmlid, values in data.items():
model_data[xmlid].update(values)
```
**Note:** This change applies only to Version 19. Forward port must be disabled for Version 19.1 and later releases, as the issue has been resolved.
opw-6516131This fix ensures product identifiers sent to Google Analytics 4 match the identifiers used in Google Merchant Center feeds. This helps keep ecommerce reporting and advertising product data consistent, reducing confusion in campaign and sales analysis.
Original PR description
Commit d0bf183b053eb0133e6f7e5e04481ca07bff6bb3 fixes a mismatch between GA4 `item_id` and GMC `id` but was missing the fix in `_get_google_analytics_data` method opw-6443326
Switching to another view through the AI assistant while a full message composer is open no longer triggers an error. The system now avoids trying to refresh a record area that has already been closed, making navigation smoother for users.
Original PR description
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is…
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is closed. Closing that dialog then calls the chatter's onCloseFullComposerCallback, which reloads the parent record through reloadParentView(). However at that point the chatter no longer exists, so the reload's RPC call gets rejected with "Component is destroyed", and nothing is left to catch it.
How to reproduce:
- Open "Ask AI" from the top bar.
- Open an opportunity in CRM, then open the mail composer (click either 'Send message' or 'Log Note'), then click the enlarge button so it opens as a full composer dialog.
- Ask the agent (the one you pre-opened) to open another view, e.g. "show me all my contacts in the US", "show me the contact view of Abigail Peterson"
Current behavior:
The requested view opens correctly, but an UncaughtPromiseError ("Component is destroyed") is raised.
Expected behavior:
Switching views while a full composer dialog is open should not raise any error. The chatter's parent record should simply not be reloaded if the chatter has already been destroyed by the time its full composer dialog closes.
community: https://github.com/odoo/odoo/pull/287125
task: 6365003This fixes an error that could appear when users asked the AI assistant to open another view while a full-size message composer was still open. The system now avoids trying to refresh a record that has already been closed, making navigation smoother and preventing unnecessary error popups.
Original PR description
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is…
Asking the AI agent to navigate to a different view calls doAction with clearBreadcrumbs, which tears down the current form view (and its chatter) before the still-open full mail composer dialog is closed. Closing that dialog then calls the chatter's onCloseFullComposerCallback, which reloads the parent record through reloadParentView(). However at that point the chatter no longer exists, so the reload's RPC call gets rejected with "Component is destroyed", and nothing is left to catch it.
How to reproduce:
- Open "Ask AI" from the top bar.
- Open an opportunity in CRM, then open the mail composer (click either 'Send message' or 'Log Note'), then click the enlarge button so it opens as a full composer dialog.
- Ask the agent (the one you pre-opened) to open another view, e.g. "show me all my contacts in the US", "show me the contact view of Abigail Peterson"
Current behavior:
The requested view opens correctly, but an UncaughtPromiseError ("Component is destroyed") is raised.
Expected behavior:
Switching views while a full composer dialog is open should not raise any error. The chatter's parent record should simply not be reloaded if the chatter has already been destroyed by the time its full composer dialog closes.
task: 6365003
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix prevents an error from interrupting the French PDP document retrieval scheduled task when Odoo is running with demo data. It helps keep demo environments stable and avoids confusing failures during testing or demonstrations.
Original PR description
Issue: _call_peppol_proxy raised a traceback while called. Steps to reproduce: - in demo mode - run cron: "PDP: Retrieve new regulatory documents" no-task Forward-Port-Of: odoo/odoo#287374
The Point of Sale product configurator no longer shows add-on price badges when a fixed pricelist means those extras will not be charged. This prevents staff from seeing misleading prices and helps ensure customers are quoted accurately at checkout.
Original PR description
Steps to reproduce: - Create a pricelist "TAKEAWAY" with a fixed price of 10.00 on a product whose sales price is 20.00 - Create a preset "TAKEOUT" and set its pricelist to "TAKEAWAY" - Add to that…
Steps to reproduce: - Create a pricelist "TAKEAWAY" with a fixed price of 10.00 on a product whose sales price is 20.00 - Create a preset "TAKEOUT" and set its pricelist to "TAKEAWAY" - Add to that product an attribute with variant creation "Never", with a value carrying an extra price of 1.00 - In the POS, switch to the preset "TAKEOUT" and click the product Issue: The configurator advertises the attribute value with a "+ $ 1.00" badge, but that extra is charged nowhere: the title of the popup and the resulting order line both stay at the 10.00 of the pricelist. Cause: A fixed pricelist rule replaces the whole price of the product, the attribute extra prices included: _compute_price on product.pricelist.item returns fixed_price and never reaches _compute_base_price, the only place where _get_attributes_extra_price is taken into account. getPrice is a faithful port of that and overwrites `basePrice + price_extra` with rule.fixed_price. The configurator, however, rendered its badges out of value.price_extra alone, without ever asking what the pricelist of the order does with it. Fix: Only advertise an extra price when the price of the product actually reflects it, the way website_sale already does with the show_extra_price of _get_additionnal_combination_info. Asking getPrice covers more than a fixed rule: a rule based on another pricelist recurses with no extra either, and a full discount leaves nothing of it. Combo items keep their badges, since computeComboItems adds their extras on top of the combo price, like _get_combo_item_display_price does. opw-6528187 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents Odoo from crashing when a user clicks an old file link in an HTML field after the original attachment has been deleted. Instead of showing a client error, the editor now handles the missing file safely, improving reliability for users working with embedded attachments.
Original PR description
Clicking a stale /web/content/<id> link in an HTML field crashed the client after the related attachment had been deleted. **Steps to reproduce:** 1. Open any record with an HTML field (e.g. Project…
Clicking a stale /web/content/<id> link in an HTML field crashed the client after the related attachment had been deleted. **Steps to reproduce:** 1. Open any record with an HTML field (e.g. Project > Task description). 2. Upload a file into the HTML field to embed an attachment link. 3. Save the record. 4. Delete the uploaded attachment from Chatter > Files, or from Settings > Technical > Attachments. 5. Reopen the record and click the embedded file link. **Client Error:** `TypeError: Cannot destructure property 'mimetype' of '(intermediate value)' as it is undefined at LinkPopover.loadAsyncLinkPreview` `TypeError: Cannot destructure property 'type' of '(intermediate value)' as it is undefined at LinkPopover.updateDocumentState` When the attachment is missing, ormService.read returns an empty array, so fetchAttachmentMetaData returned undefined instead of entering its catch block. LinkPopover then crashed while destructuring that result in loadAsyncLinkPreview and updateDocumentState. Return a safe fallback metadata object when the attachment cannot be found so both code paths keep working without crashing. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Contracts page in Employee Records no longer offers a Kanban view option that did not actually exist. This avoids user confusion and keeps the available view choices aligned with what the system supports.
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
This fix helps Odoo handle PDF processing reliably on systems that ship with older PDF libraries, such as Ubuntu 22.04. It reduces the risk of PDF-related failures when deployments use different library versions.
Original PR description
Ubuntu Jammy (22.04 LTS) ships with PyPDF2 v1.26.0 by default, which uses legacy camelCase method names like `addTransformation`. Modern `pypdf` versions use snake_case (`add_transformation`). Add `PageObject.addTransformation` to `_pypdf.py` mapping to `add_transformation` to maintain cross-version API compatibility between PyPDF2 1.x and newer `pypdf` releases. runbot-946875
Spreadsheet cells now show the correct data when opened in Hoot debug test mode. This prevents misleading test screens caused by animations getting stuck, improving confidence in spreadsheet testing without changing customer-facing behavior.
Original PR description
If you try to open a spreadsheet in debug mode in the Hoot tests, you will often end up with cells with wrong displayed data. That's because cell animations don't work in hoot (it patches `requestAnimationFrame`), so we end up with cell animations stuck in the first frame of the animation. We can simply disable the cell animations in the Hoot tests, as animations are not relevant to the tests. Task: [4909027](https://www.odoo.com/odoo/2328/tasks/4909027)
Social posts now format content more accurately by tightening the rules used to interpret post text. This reduces the chance that messages are displayed differently from what users intended when creating them.
Original PR description
This commit fixes an issue for the social post formatter mixin's regexes being too lenient. The rendering of some elements could be incorrect from what the user initially wanted to create as a post. Now the regexes have been narrowed down so that the resulting formatted value is more in line with what the user wanted. task-6026857 Forward-Port-Of: odoo/enterprise#110323
The Missing E-Invoice check now opens a list limited to the invoices that actually need attention. This prevents users from seeing unrelated or all eligible invoices, reducing confusion during Indian GST return review.
Original PR description
The `missing_einvoice` check passed custom `views` but no explicit `domain`, so its action ignored the `moves` recordset and instead opened all matching `account.move` records — an unfiltered list when no invoices were missing, and every eligible invoice (not just the flagged ones) otherwise.
Guard the action to only build when `moves` is non-empty, and pass `domain=[('id', 'in', moves.ids)]` so it's always scoped to the invoices actually found.
task-6544790