Monday, September 21, 2026
38 changes · saas-19.4
Resolved issues and error corrections
The Source PO button now appears only on subcontractor resupply receipts, preventing unrelated purchase orders from being shown on normal product receipts. This reduces confusion for purchasing and warehouse teams by ensuring the button links only to the relevant subcontracting purchase order.
Original PR description
After a recent change, the smart button for Source POs uses the reference_ids on a stock.picking. This altered the logic to fetch all orders from any picking that has the same reference. However,…
After a recent change, the smart button for Source POs uses the reference_ids on a stock.picking. This altered the logic to fetch all orders from any picking that has the same reference. However, `subcontracting_source_purchase_count` should specifically relate to the resupply of subcontractor picking to their subcontracted purchase order. **Steps to Reproduce:** 1. Enable multi-step routes and subcontracting 2. Unarchive the MTO route 3. Create 4 products Finished Product, A, B, C, and set MTO on both A and B 4. Put 10 units of C in stock 5. Create a BoM for Finished Product using A and B as components 6. Create a subcontracted BoM for B using C as a component 7. Set the purchase vendor for product A as the vendor 8. Set the purchase vendor for product B as the subcontractor 9. Create and confirm a manufacturing order for Finished Product 10. Confirm the POs The two POs are: 1. Purchase Product A from its vendor 2. Subcontract Product B from its subcontractor and use Product C as a component **Current Functionality:** - Product A's receipt has a **Source PO** smart button pointing to the subcontracting PO for Product B (BUG) - Product B's receipt has a **Source PO** smart button pointing to its own PO (BUG) - Product C's picking has a **Source PO** smart button pointing to its own PO **New functionality:** - Product A's receipt has no **Source PO** smart button - Product B's receipt has no **Source PO** smart button - Product C's receipt has a **Source PO** smart button pointing to its own PO opw-6420168 Forward-Port-Of: odoo/odoo#278908
This fixes an issue where access rights created through Studio were not treated as read-only when they should be. It helps prevent unintended changes to Studio-generated security settings and keeps configuration behavior consistent.
Original PR description
task-6481613
This fixes an issue where access permissions created through Studio were incorrectly treated as read-only. Users managing Studio customizations can now adjust these permissions as expected, reducing friction when configuring roles and access.
Original PR description
task-6481613 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
New US companies using AvaTax now receive the correct tax accounts during accounting setup, even when the database has no demo data. This prevents taxes created from AvaTax calculations from missing their accounting account, helping invoices post correctly.
Original PR description
Steps to reproduce: - Create a DB and Install `Accounting` without demo data - In Companies > Create New Company with `US` Localization - Switch to US Company > Add `Avatax` Credentials - Create a…
Steps to reproduce: - Create a DB and Install `Accounting` without demo data - In Companies > Create New Company with `US` Localization - Switch to US Company > Add `Avatax` Credentials - Create a Product with `Avatax Category` - Create a Invoice > In Other Info `Fiscal Position` - `Automatic Tax Mapping (AvaTax)` > `Compute Taxes` - In Taxes check newly created tax does not have a account ID Issue: AvaTax fiscal position created from chart templates have empty `avatax_invoice_account_id` and `avatax_refund_account_id` fields on a fresh database without demo data. Problem: Both fields use [defaults] based on `company.account_sale_tax_id`. During initial CoA loading, `_load_data()` creates the AvaTax fiscal position before `_post_load_data()` sets `company.account_sale_tax_id`. The defaults therefore resolve to an empty recordset and no tax account is assigned. This issue does not occur in databases with demo data because the demo company is already loaded, so `company.account_sale_tax_id` is already set when the AvaTax fiscal position is created. Solution: Set the invoice and refund accounts explicitly in the AvaTax fiscal position template to ensure they are correctly assigned during CoA loading. [defaults]: https://github.com/odoo/enterprise/blob/de17c107651394025e9a3d5cbed8d81bcfc2e76d/account_avatax/models/account_fiscal_position.py#L9-L13 opw-6347128 Forward-Port-Of: odoo/enterprise#132005 Forward-Port-Of: odoo/enterprise#126604
Moving a document into a folder now correctly applies the folder's group access rights, even when the folder has no owner. This prevents group members from unexpectedly losing access to documents after drag-and-drop moves.
Original PR description
When moving a document into a folder (e.g., via drag and drop), the document fails to inherit the group access rights defined on the destination folder if that folder does not have an owner. While…
When moving a document into a folder (e.g., via drag and drop), the document fails to inherit the group access rights defined on the destination folder if that folder does not have an owner. While direct uploads correctly apply the groups, moved documents only inherit partner access rights in this scenario, potentially leaving group members without the expected access. This occurs because group access rules were inadvertently filtered out during the rights sync when the system evaluated the missing folder owner. This commit ensures that group-based access rules are correctly retained and applied to the document when it is moved into a folder, regardless of whether the destination folder has an owner. Steps to reproduce: - Create a new folder and ensure the "Owner" field is empty. - Add a group to the folder's access rights. - Drag and drop a file from elsewhere into that folder. - Notice the document doesn't inherit the group from the parent folder. Task-6585315 Forward-Port-Of: odoo/enterprise#132235
Shop sidebar category links now stay clickable for public visitors even when some related categories are not visible to them. This prevents shoppers from encountering inactive category navigation and helps maintain a smoother browsing experience.
Original PR description
# How to reproduce - Create the following categories : - Category A - Category B, Child of Category A - Category X - Category Y, Child of Category X - Category Z, Child of Category X - Create a…
# How to reproduce - Create the following categories : - Category A - Category B, Child of Category A - Category X - Category Y, Child of Category X - Category Z, Child of Category X - Create a published product for category B & Z - Go to the Shop page - Enable the Sidebar Categories - Log out - Go to the Shop page # The issue The link for the Category Z is broken and clicking the Category does nothing. # Cause When rendering the recursive template for the categories : https://github.com/odoo/odoo/blob/8cefaf36e2b4ce6db869dba63874c933060b702b/addons/website_sale/templates/shop_page_templates.xml#L1291 https://github.com/odoo/odoo/blob/8cefaf36e2b4ce6db869dba63874c933060b702b/addons/website_sale/templates/shop_page_templates.xml#L1310 The rendering engine will fetch the values for the `website_url` field for every `child_id` of every Category because of the prefetch mechanism, even the one public users dont have access to : https://github.com/odoo/odoo/blob/ceae1f02580601bf179fc36e449112a88c3dff8d/addons/website_sale/security/ir.access.csv#L16 During the compute of that field, the records will be ordered in this way : 1) Category B => User has read access 2) Category Y => User does NOT have read access, because no product 3) Category Z => User has read access So an access error will be raised here for the 2nd Category : https://github.com/odoo/odoo/blob/ceae1f02580601bf179fc36e449112a88c3dff8d/addons/website_sale/models/product_public_category.py#L149 Which will be intercepted by the fallback of the getter, that retries the compute with only the first record. This will succeed because the user has access to that record : https://github.com/odoo/odoo/blob/ceae1f02580601bf179fc36e449112a88c3dff8d/odoo/orm/fields.py#L1827-L1828 The issue is that the call to `super()` at the start of the compute already assigned a value to all the records, so all Categories have a value in the cache for `website_url`, even after the fail of the compute : https://github.com/odoo/odoo/blob/8cefaf36e2b4ce6db869dba63874c933060b702b/addons/website/models/mixins.py#L255-L258 So when trying to access Category's Z `website_url`, we'll get '#', without any recomputation being done because of the cache value opw-6481175
The AI website builder now saves custom styling to the correct website and checks styles more accurately before saving. This prevents errors that could break a website after using AI-generated custom design changes.
Original PR description
[FIX] ai_website: save custom css scoped Before this commit, if you had multiple websites, AI wouldn't save custom css in the correct website's bundles, which caused the following broken flow: - open…
[FIX] ai_website: save custom css scoped
Before this commit, if you had multiple websites, AI wouldn't save
custom css in the correct website's bundles, which caused the following
broken flow:
- open css editor, make any changes, and save it
- open the AI website builder agent and ask it to make all buttons red,
writing a custom css for that
=> you get a traceback, and after reloading your website is broken.
Note that this isn't an issue in 20.0 as this behavior has been changed.
Related to task-6578231
---
[FIX] ai_website: validate custom SCSS with bundle url rewriting
When AI used url($var) in scss, it would break the style compilation and
display an error. This happened because compiling replaced relative urls
with the absolute path. It wasn't caught before saving the custom css,
because we preprocessed css content inline, which doesn't rewrite
relative url()s.
To directly check it, you can just ask it to save this custom css:
`'$img: "a.png"; #test { background: url($img); }'`
=> Style compilation will fail.
Also, this commit updates some already present nested `with` statements
in tests to remove Ruff warnings.
task-6578231This fixes an issue in the website page editor where using the keyboard arrow keys on certain size or filter number fields showed a preview but did not keep the new value. Editors can now adjust these settings with the keyboard and trust that the change will remain after clicking away.
Original PR description
When a BuilderRange is displayed with its optional number input, using ArrowUp/ArrowDown updates the preview but does not save the new value. The range component passes its handler through onKeydown, while BuilderNumberInputBase only calls onKeydownArrow after handling arrow keys. As a result, the debounced commit is skipped. Steps to reproduce: - Drop a s_social_media inner snippet - Click on the snippet, then click on the "Size" input - Use "ArrowUp" to increase the value of the number input - Click anywhere on the page => The size goes back to the previous one. task-6385984 Forward-Port-Of: odoo/odoo#286809 Forward-Port-Of: odoo/odoo#283504
Vendor bill users can now find purchase order lines by searching for the related purchase order name, not just the line description. This makes matching bill lines to purchases easier and reduces manual lookup when processing supplier invoices.
Original PR description
Issue: ------------------------------------- When creating a vendor bill, the Purchase Order Line field on the bill line allows selecting a purchase order line. However, the search only matches the…
Issue: ------------------------------------- When creating a vendor bill, the Purchase Order Line field on the bill line allows selecting a purchase order line. However, the search only matches the POL name and does not allow searching by the purchase order name. Steps to reproduce: ------------------------------------- 1. Install the `purchase` module. 2. Go to Vendor Bills, click New, and select a vendor. 3. Add the Purchase Order field to the bill line using the optional fields. 4. Click Add a line and open the Purchase Order selection. 5. Try to search for the line using the purchase order name. The purchase order line cannot be found. Cause of the issue: ------------------------------------- The `purchase.order.line` model does not define `_rec_names_search`, so the record search only considers the purchase order line's `name` field. Solution: ------------------------------------- Define `_rec_names_search` with both `name` and `order_id` so that POLs can also be searched using their related purchase order name.
Creating a Saudi Arabia contact and choosing a Tax Identification Number no longer crashes when no VAT number has been entered. The system now leaves the Saudi tax ID blank until VAT information is available, improving contact setup reliability.
Original PR description
## Steps to Reproduce: - Install the `l10n_sa` and `contacts` modules. - Create a new contact and set the country to **Saudi Arabia**. - Click the "**+**" sign next to the TIN field. - Select "**Tax Identification Number**". ## Error: `TypeError: 'NoneType' object is not subscriptable` ## Cause: The onchange method tries to extract the SA TIN from the VAT even when the VAT is not set. This causes an error when slicing the None value. ## Fix: Skip populating the SA TIN when the VAT is not set. sentry-7716910106
The website configurator now handles temporary failures of the external website setup service without crashing. This keeps users moving through website creation, including the color palette step, even when that service is unavailable.
Original PR description
bug: configurator_missing_industry raised an uncaught RPC_ERROR when the IAP website API was unreachable, breaking the color palette step of the website configurator. steps: - Go in settings and set in the system parameters `website.website_api_endpoint` to anything that won't work - Create a new website - Traceback at the palette step fix: Wrap the IAP calls in a try/except for AccessError. task-6325919 Forward-Port-Of: odoo/odoo#280675
This fix prevents Chilean demo accounting setup from trying to post demo entries meant for non-Chilean partners. It helps companies and evaluators install Chilean localization alongside other localizations without demo data setup failures.
Original PR description
When several localization modules are installed at once (with demo data), loading the chilean demo data fails and the chilean demo company ends up without any accounting demo data. Steps to reproduce: - Install `l10n_cl` together with the other localizations and the enterprise addons, with demo data enabled Issue: Error while loading accounting demo data ValidationError: Document types for foreign customers must be export type (codes 110, 111 or 112) or you should define the customer as an end consumer and use receipts (codes 39 or 41) Analysis: Demo methods will posts every move of the chilean company, not only the ones prepared by the module. In combination with other modules loading their own demo data it may raise the said error. Forward-Port-Of: odoo/odoo#288590
This fixes a leftover reference in the self-ordering point of sale IoT flow after the related feature was removed elsewhere. It helps prevent unnecessary or failing calls, improving reliability without changing the customer-facing experience.
Original PR description
Remove last reference to `last_order_preparation_change` that was removed here. https://github.com/odoo/odoo/pull/250692
PINT electronic invoices are now generated through the newer UBL export path instead of the older BIS 2.0 process. This helps modernize e-invoicing support and prepares the system for retiring legacy export logic with minimal user-facing disruption.
Original PR description
Problem --------- Currently, PINT uses the old BIS2.0 export. Objective --------- Decouple the exports as an effort to remove the old BIS implementation. no-task --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288139 Forward-Port-Of: odoo/odoo#283585
Fixes an issue where Helpdesk teams linked to multiple community forums could hit an error when visitors clicked “Ask the community.” Users are now shown the correct forum listing page, including when eLearning forum integration is installed.
Original PR description
### Steps to Reproduce: 1) Install `website_helpdesk_slides_forum` module 2) On a Helpdesk team, link 2 (or more) forums under `Commnity Forums`. 3) Click on website smart button and then click `Ask…
### Steps to Reproduce: 1) Install `website_helpdesk_slides_forum` module 2) On a Helpdesk team, link 2 (or more) forums under `Commnity Forums`. 3) Click on website smart button and then click `Ask the community` button. ### Error: ``` odoo.addons.base.models.ir_qweb.QWebException: Error while render the template KeyError: '_forums' Template: website_helpdesk_slides_forum.helpdesk_forums ``` ### Root Cause: https://github.com/odoo/enterprise/blob/1bdd673c5fd19e335dc0948d2beed7a282e5e172/website_helpdesk_forum/controllers/website_forum.py#L18-L22 On clicking the "Ask the Community" button calls the `helpdesk_forums` controller. A single forum redirects straight to it. Several forums get rendered through `get_template_xml_id()`, with only `forums` in context. `get_template_xml_id()` is overridden in `WebsiteSlidesForumHelpdesk`, which points to : https://github.com/odoo/enterprise/blob/1bdd673c5fd19e335dc0948d2beed7a282e5e172/website_helpdesk_slides_forum/views/helpdesk_templates.xml#L3-L5 a primary copy of the inner partial `forum_all_all_entries`. That partial needs `_forums` (and, once extended by website_slides_forum, courses_discussions too), both only ever set by the page template's own t-call: [Reference](https://github.com/odoo/odoo/blob/23af2b443735c6d3a2f64e44f9ea5da45638b052/addons/website_forum/views/forum_forum_templates_forum_all.xml#L18-L19) Since `helpdesk_forums` is rendered directly instead of going through `website_forum.forum_all`, `_forums` is never set, hence `KeyError` occurs. The base `website_helpdesk_forum` module has the same root cause one level up, surfacing as a different error: https://github.com/odoo/enterprise/blob/1bdd673c5fd19e335dc0948d2beed7a282e5e172/website_helpdesk_forum/controllers/website_forum.py#L24-L25 `website_helpdesk_forum.forum_all` does not exist anywhere in the codebase. A team with multiple forums, without `website_helpdesk_slides_forum` installed, hits ``` ValueError: View 'website_helpdesk_forum.forum_all' in website 1 not found ``` Instead of a listing page. ### Fix: - Both `get_template_xml_id()` implementations now return the real, working `website_forum.forum_all` page template, which already sets `_forums/courses_discussions` through its own `t-call` and wraps the result in website.layout. - `helpdesk_forums()`'s render values are now built through an overridable `_get_helpdesk_forums_render_values()` hook instead of a hardcoded dict, so subclasses can extend the context. - `website_helpdesk_slides_forum` uses that hook to set `hide_forum_slides_link=True`, and adds one small non-primary view inheriting `website_slides_forum.forum_all_all_entries` that conditions the `/slides` promo link (not the "Course" badge, which doesn't navigate anywhere) on `not` `hide_forum_slides_link`. This targets the link element itself rather than a `t-call` site in `forum_all`, so it correctly applies whether `website_slides_forum` groups a given forum as "regular" or "course-linked". **opw-6332175** Forward-Port-Of: odoo/enterprise#131734 Forward-Port-Of: odoo/enterprise#124104
The system now prevents users from creating API keys that are already expired. This helps avoid mistakes when following copied documentation or examples, reducing confusion and failed integrations.
Original PR description
Prevent creating API keys that are already expired. One typical case is when you copy/paste the documentation and end up creating keys that are already expired, without noticing. Forward-Port-Of: odoo/odoo#288154 Forward-Port-Of: odoo/odoo#286548
This fixes an issue where users creating reordering rules for shared manufactured products in multi-company setups could see an access error, even though the rule was created. Odoo now uses the correct company-specific bill of materials first, avoiding unnecessary checks against bills of materials from other companies.
Original PR description
#### Issue: When creating a reordering rule for a shared manufactured product in a multi-company database, saving the rule may raise an `AccessError` on `mrp.bom`. The orderpoint is still created,…
#### Issue: When creating a reordering rule for a shared manufactured product in a multi-company database, saving the rule may raise an `AccessError` on `mrp.bom`. The orderpoint is still created, but the user sees a record-rule error if the product also has BoMs in companies that are not currently active. #### Example: A product is shared across multiple companies, and each company has its own BoM for that product. In the reproduced case, the active company has the correct variant BoM. However, the orderpoint computation first checks the broader product-template BoM relation, which may include BoMs from the other companies. As a result, Odoo can try to access a BoM from another company while the user is only working in the active company, causing an access error. #### Steps to reproduce: Use a multi-company database with MRP enabled. Create or use a shared product available to multiple companies. Create BoMs for that product in more than one company. Set the active company to the company where the reordering rule should be created. Create a reordering rule for the product. Save the reordering rule. Note the AccessError related to mrp.bom. #### Root Cause: The MRP orderpoint computations read `product_id.bom_ids` directly. This is the product-template BoM relation and can include BoMs from other companies for a shared product. Reading fields on those BoMs, such as `product_uom_id`, can hit the standard `mrp.bom` multi-company record rule. #### Fix: Prefer `product_id.variant_bom_ids` before falling back to `product_id.bom_ids` in the affected orderpoint computations. This avoids reading template-level BoMs from other companies when the product has a variant-specific BoM for the current reordering-rule use case. opw-6253743 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278936 Forward-Port-Of: odoo/odoo#267411
This update adjusts an automated stock workflow test so it works correctly when the Turkish Nilvera e-Dispatch module is installed. It prevents a false test timeout caused by a different screen identifier, improving reliability without changing user-facing stock behavior.
Original PR description
### Steps to reproduce: - Install `l10n_tr_nilvera_edispatch` (e.g. the `tr` country build) - Run `test_basic_stock_flow_with_minimal_access_rights` > The tour times out on step 6/31, "check that at…
### Steps to reproduce: - Install `l10n_tr_nilvera_edispatch` (e.g. the `tr` country build) - Run `test_basic_stock_flow_with_minimal_access_rights` > The tour times out on step 6/31, "check that at least one picking is present in the view". ### Cause of the issue: The step triggers on `.o_stock_list_view_view`, a class the web client derives from the `js_class` of `stock.vpicktree`: https://github.com/odoo/odoo/blob/71c040ae236c9487afc49559486a588f21ccb37b/addons/stock/views/stock_picking_views.xml#L66-L70 https://github.com/odoo/odoo/blob/71c040ae236c9487afc49559486a588f21ccb37b/addons/web/static/src/views/utils.js#L45-L68 `l10n_tr_nilvera_edispatch` overwrites that attribute to plug in its e-Receipt upload button, so the root carries `o_l10n_tr_edispatch_tree_view` instead and the trigger never matches: https://github.com/odoo/odoo/blob/71c040ae236c9487afc49559486a588f21ccb37b/addons/l10n_tr_nilvera_edispatch/views/stock_picking_views.xml#L4-L13 Only the class name changes: `L10nTrNilveraEdispatchListView` spreads `StockListView`, so the rendered list is identical. runbot-947260 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288404 Forward-Port-Of: odoo/odoo#288255
This update fixes test setup issues affecting the Purchase app and Units of Measure feature. It makes automated purchase walkthroughs more reliable and ensures units of measure are properly enabled or disabled during tests, reducing false failures and improving confidence in the feature.
Original PR description
> ### [FIX] purchase: tour trigger > This commit replaces a trigger which used the button URL because this button's URL can differ if the tour is run in debug mode (eg.: `/odoo/purchase?debug=assets` instead of `/odoo/purchase`). > ### [FIX] uom: correct group > This commit fixes `_enable_uom` and `_disable_uom` `UomCommon` class methods to correctly enable/disable the UoM feature. > > Before that, the user has CRUD accesses to UoM but the feature wasn't enabled as expected, which means `_enable_uom` wasn't enough to display UoM fields in view when this field use the group `uom.group_uom` to be display. > > This issue was spotted while working on the `purchase` test/tour `test_catalog_vendor_uom`. When launch locally on a DB without demo data and only with `purchase` installed, the units of measure weren't visible during the tour, and if the tour is paused and we go in the settings, we can see the UoM setting is unticked. Forward-Port-Of: odoo/odoo#283451
This fixes time off balances so approved future leave is counted against an employee's allocated days. Businesses will see more accurate remaining leave balances when employees book time off in advance.
Original PR description
**Steps to reproduce:** - Create and validate an allocation of 10 days. - Take and validate a leave of 5 days in the future. - Issue: the allocation's `virtual_remaining_leaves` still shows 10 instead of 5. **Issue:** `hr.leave.allocation._compute_leaves()` calls `_get_consumed_leaves()` with `ignore_future=True`, which filters the leaves domain to `date_from <= today`. A validated future leave is excluded from the query before it can be deducted, even though the allocation grants its days upfront and isn't gated by any accrual plan. This flag was intentionally dropped from this call by (odoo/odoo#193685), then came back by accident via a forward-port of (odoo/odoo#249441). **Solution:** Drop `ignore_future=True` from `_compute_leaves()` Task-6534125 Forward-Port-Of: odoo/odoo#288073 Forward-Port-Of: odoo/odoo#287626
Fixes an issue where editing booking notes from the POS schedule view could fail with an error when saving. Staff can now update appointment notes reliably without interruption during point-of-sale operations.
Original PR description
Editing the notes of a booking from the POS gantt view raised an error when saving the field. **Step to reproduce:**…
Editing the notes of a booking from the POS gantt view raised an error when saving the field.
**Step to reproduce:** https://app.tango.us/app/workflow/Create-Booking-in-Bookings-App-b045c76169c8432b8516c6bbd0f366e6
> TypeError: ids is not iterable (cannot read property undefined)
at Object.addPendingAttachments (https://125652949-saas-19-4-all.runbot316.odoo.com/web/assets/fb4fcbe/point_of_sale.assets_prod.min.js:25792:32)
at HtmlField._commitChanges (https://125652949-saas-19-4-all.runbot316.odoo.com/web/assets/fb4fcbe/point_of_sale.assets_prod.min.js:25759:104)
The POS HTML field uses a reduced set of editor plugins that does not include the MediaPlugin. Since the booking notes field relies on the same HTML field, extracting the pending attachment ids returns undefined instead of an empty array.
This undefined value is then passed to `addPendingAttachments`, which expects an iterable and raises a TypeError.
To avoid this, wrap `addPendingAttachments` in the POS appointment HTML field setup and only call the original method when attachment ids are available.This update corrects outdated Belgian payroll salary test steps after related product and UX changes. It helps keep automated validation reliable by removing checks for a retired feature and aligning expected payroll values with the current configuration.
Original PR description
Error 1:
Drop the automatic extra legal allocation 's test: this feature was remove
in this task 5362345; but the test was not removed
Error 2:
Due to some UX change the IP display change and the test was not up-to-date
Error 3:
Due to a misconfiguration the public transport value was wrong.
runbot_error-242808
Forward-Port-Of: odoo/enterprise#131958This update prevents an error when editing sale order line list views in Odoo Studio after a sale order is confirmed. Users can now customize the sale order line view without the screen crashing, while normal sales behavior remains unchanged.
Original PR description
Steps to produce: ---- - Install sales and studio module. - Create new product and make sale order using it. - Confirm the sale order and open the studio. - Click on sale order line > Click on edit…
Steps to produce: ---- - Install sales and studio module. - Create new product and make sale order using it. - Confirm the sale order and open the studio. - Click on sale order line > Click on edit list view. Issue: --- - Clicking the `edit list view` button raises a traceback: `TypeError: Cannot read properties of undefined (reading 'locked')` Root cause: --- - The issue was introduced by [commit]. - `saleProductMixin.hasConfigurationButton` reads the parent sale order's `locked` field by walking up the model tree: https://github.com/odoo/odoo/blob/973218b9d60ebe715f0bf5a9bdc54b036b002e9b/addons/sale/static/src/js/sale_product_mixin.js#L68 - This works in a normal form view because `model.root` is the sale order Record, and Record always has a `.data` object containing its field values. - In Studio's list editor, `model.root` is no longer the sale order Record. Studio replaces it with a `StaticList` - the list of order lines itself. so, it can render the `subview` directly: https://github.com/odoo/enterprise/blob/a6c971daad566043e073b2cb6f2fd18794b49fb0/web_studio/static/src/client_action/view_editor/editors/list/list_editor.js#L73-L77 - `StaticList` holds a collection of child records. It has no field values of its own, so it never sets .data. Accessing `model.root.data` returns undefined. Solution: --- - The `locked` check is only meaningful when a full sale order record tree exists above the line, which isn't guaranteed for every rendering context. Falling back to `undefined` when `root.data` is absent keeps the check inert rather than crashing, without changing behavior in the normal runtime path where `root.data` is always a valid `Record`. [commit]: https://github.com/odoo/odoo/commit/84f4c84adfba546ba940175411363a865d8f7c3a opw-6566217 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The accounting prediction logic now uses the most recent previous entries instead of older records. This helps ensure suggested accounting values are based on current business activity, improving relevance and reducing incorrect predictions.
Original PR description
This commit: https://github.com/odoo/enterprise/pull/38830/changes#diff-6f6931855e0903ff0d3f2b39bd5703ceaef9bdf9a516862b83f38d2d5b21a232 change the order of the predictive queries, removing the sorting order by date. Based on the current docstring: https://github.com/odoo/enterprise/blob/66682012145e5116ebec0183102bc5e930c2c343/account_accountant/models/account_move.py#L676 this is not correct, as we expect to retrieve the previous 100 entries, rather than the oldest ones. Correcting the query order ensures that the most recent entries are considered for predictive purposes. opw-6558929 Forward-Port-Of: odoo/enterprise#132022 Forward-Port-Of: odoo/enterprise#131731
This fix makes website editor color options and the shop product comparison bar display correctly when users work in languages such as German. Longer translated labels now fit better, and styling no longer depends on English text, improving consistency for multilingual users.
Original PR description
Steps to reproduce: - Set the user language to German. - Open a color picker with the `Theme` tab in the website editor. - Check the color presets and the reset button. - Open the product comparison bar on the shop page. => Long labels do not fit and some styles are missing. Before this commit, long labels did not fit in the color preset picker. Some CSS selectors also relied on English `title` values, so their styles were not applied in other languages. After this commit, the preset picker adapts to long labels and the CSS selectors use dedicated classes that work in every language. task-6259086 Forward-Port-Of: odoo/odoo#289008 Forward-Port-Of: odoo/odoo#286426
This fixes a VAT validation issue where child contacts could incorrectly show an invalid VAT status when processed before their parent company. Parent company VAT results are now calculated first, so related child records correctly reuse the verified result.
Original PR description
**Description of the issue/feature this PR addresses:** When a batch recompute of `vies_valid` contains both a parent (commercial) partner and a child sharing the same VAT, and the child happens to…
**Description of the issue/feature this PR addresses:**
When a batch recompute of `vies_valid` contains both a parent (commercial) partner and a child sharing the same VAT, and the child happens to be iterated before its parent, the child ends up with `vies_valid=False` instead of the parent's real, freshly-checked value.
**Current behavior before PR:**
`_compute_vies_valid` loops over `self` in whatever order the batch happens to have:
```python
for partner in self:
...
if partner.parent_id and partner.parent_id.vies_vat_to_check == partner.vies_vat_to_check:
partner.vies_valid = partner.parent_id.vies_valid
continue
status = partner._check_vies_iap()
partner._update_vies_status(status)
```
`Field.compute_value()` removes the whole batch from the "to compute" queue *before* running this loop (it does so upfront, in case the method does not assign every record). So when the loop reaches a child and reads `partner.parent_id.vies_valid` to reuse it, that field is no longer marked "to compute" for the parent, and reading it just returns whatever is currently cached/stored — which, if the parent has not been processed yet in this same loop, is still the old/default value. The child copies that stale value and, being a stored field, keeps it forever: nothing re-triggers its computation afterwards.
Example:
```python
parent = env['res.partner'].create({'name': 'Parent Co'})
child = env['res.partner'].create({'name': 'Child Address', 'parent_id': parent.id})
child.vat = 'BE0477472701' # queues the child's compute first
parent.vat = 'BE0477472701' # queues the parent's compute second
child.vies_valid # False, even though the VAT is valid
parent.vies_valid # True
```
**Desired behavior after PR is merged:**
Every partner without a parent is always computed before any child that may reuse its value, regardless of the batch's original order — so the child correctly ends up with the parent's real `vies_valid`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287351
Forward-Port-Of: odoo/odoo#279927This fixes an issue where batch payments could remain marked as sent even after the related bill and payment were fully paid. Businesses will see more accurate payment statuses, reducing confusion during payment tracking and reconciliation.
Original PR description
A payment on a journal without outstanding account has no journal entry, so it is matched as soon as it is paid. When the bill it pays is reconciled later on, _compute_state turns it to 'paid', but assigning a field from within a compute doesn't notify the fields depending on it: is_matched stays False and any batch payment holding that payment stays in 'sent' state. Mark is_matched for recomputation explicitly, as 18.0 already does since d8de234. Steps to reproduce: - On the Bank journal, leave the outstanding account empty on the outbound payment method line - Post a vendor bill - Register a payment on it - Put that payment in a batch payment and validate the batch - Create a MISC entry and reconcile the bill with it - Issue: bill and payment are 'Paid' but the batch stays 'Sent'. Forward-Port-Of: odoo/odoo#288981 Forward-Port-Of: odoo/odoo#288460
This change updates purchase email template data so migrated databases can correctly refresh the template logic. It prevents an error when users edit only the unit price on a confirmed purchase order line, improving reliability for purchasing workflows.
Original PR description
In this commit: eadf127 the `track_po_line_template` template was added in a `noupdate` file. The commit specifies: “put their declaration in no update when not done if template has no technical code or complex dependency on underlying code;” However, this is not actually the case for the two templates in this file. This did not cause any error in v17, but errors started appearing later because of #254602, which modified this code and the related Python code, leading to an error when no product quantity is changed. Steps to reproduce in a 19.3 database migrated from v19: - Create a purchase order with one product line and confirm it. - Only change the unit price of that line. - Error: "Error rendering template: ..." While this can also be considered a migration issue, I think the simpler and more logical solution is to remove the noupdate from this file. opw-6518729 Forward-Port-Of: odoo/odoo#288463
The French PDP e-invoicing module now records the actual status code when it receives an unsupported lifecycle status. This makes issue investigation easier by replacing unclear blank or `None` log entries with useful information.
Original PR description
Currently we just log `None` in case we receive a lifecycle with an unsupported (on community side) status. After this commit we log the status code at least. task-None before fix <img width="711" height="120" alt="image" src="https://github.com/user-attachments/assets/1f939cf4-17b7-49cb-8b31-5cc594fdeadd" /> after fix <img width="700" height="116" alt="image" src="https://github.com/user-attachments/assets/1b8b3853-f2da-4426-9c49-1d135d1c7824" /> Forward-Port-Of: odoo/odoo#286429
This fix makes a manufacturing test reliable across different time zones when checking date-based serial numbers. It helps avoid false test failures in automated validation, improving confidence in release checks without changing user-facing behavior.
Original PR description
**PROBLEM**
In `test_generate_serial_button_sequence()` we generate a serial number based on the day of the year. In ir_sequence, we use the time based on the environment timezone, but in the test, we don't use any timezone. This can lead the assertion to fail, since the day of the year can differ with the timezone used.
**REPRO STEPS**
1. edit the freeze_time in the test to `freeze_time('2024-01-15T23:00:00')`
If your timezone is UTC+2, then the time according to your timezone will be `2024-01-16T01:00:00`
So, without in UTC+0, it's the 15th day of the year, but in UTC+2 it's already the 16th.
Remove the timezone in the last assertIn() (ie, remove the fix).
(if your timezone is different, adjust the freeze_time accordingly)
2. run the test and see it fails.
runbot-237780
Forward-Port-Of: odoo/odoo#285647Product option pills in the sales configurator now keep consistent spacing when they wrap onto multiple lines. This prevents cramped rows and makes product choices easier to read for users configuring sales orders.
Original PR description
Pill-style attribute values used Bootstrap's list-inline/list-inline-item, which only sets margin-right between items. When pills wrapped onto a new line, the rows touched with no vertical gap. Fix: Switch the pill list to a flex container with gap-2, matching the spacing website_sale already uses for its own attribute-value lists, so wrapping rows get the same gap as pills on the same row. opw-6584507 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#289176
Fixes a mobile checkout issue where the order summary could stay fixed over the address form when the Android keyboard was open. Customers can now fill in checkout details more easily, reducing friction during purchase completion.
Original PR description
The mobile summary element hides the address form on Android Steps to reproduce: 1. Install eCommerce 2. On android (or using browserstack) and without being logged in, go to the eCommerce 3. Add any…
The mobile summary element hides the address form on Android Steps to reproduce: 1. Install eCommerce 2. On android (or using browserstack) and without being logged in, go to the eCommerce 3. Add any product to the cart and go to checkout 4. Click on "Checkout" to enter the address details 5. Open the keyboard by clicking inside the first input 6. The virtual keyboard opens, enter a name and click on "Next" in the virtual keyboard 7. Do this a couple of times: the cart summary element doesn't scroll and the input field is hidden behind it Similar problem happens when you scroll a bit after clicking in the first input: the cart summary element displayed at the bottom is still visible (on top of the virtual keyboard) which hides part of the page and makes it difficult to navigate the page and fill in the details Issue: `sticky-bottom` keeps the element at the bottom of the screen Solution: Remove class `sticky-bottom` from `o_mobile_summary` when we click in one of the input opw-6500503 Forward-Port-Of: odoo/odoo#287464
This fixes an issue where updating the cart summary could break the rental date picker after customers used quick reorder from the cart. The cart summary is now refreshed without disrupting the existing page element, keeping the shopping flow responsive and avoiding customer frustration.
Original PR description
`updateCartSummary` refreshes `o_wsale_shorter_cart_summary` via `replaceWith`, detaching the node and inserting a new one. `reorderProduct` in quick_reorder.js ends up restarting an interaction on the previous node instead of the new one. For rental products, this leaves the daterange picker rendered but inert after a quick reorder from the cart. This commit updates the existing node instead of replacing it, so its identity is preserved. Issue present since PR: https://github.com/odoo/odoo/pull/234965 Forward-Port-Of: odoo/odoo#288559
Reloading an Italian POS session now correctly restores the fiscal printer selection. This prevents payment screens from failing after a browser refresh, helping cashiers continue sales without interruption.
Original PR description
Steps to reproduce: - Set up an Italian fiscal printer; - Open a POS session; - Reload the browser page; - Create an order and proceed to the payment screen. **Issue**: The page fails to load, triggering an error in the console (`Cannot read properties of undefined (reading 'displayText')`), because the fiscal printer is not registered as the default printer following the page reload. **Solution**: Relocate the printer selection so it triggers on every POS reload rather than only during initial session creation. [opw-6499079](https://www.odoo.com/odoo/project/49/tasks/6499079)
Creating an onsite event from the Onsite action now uses the current user's employee record when no employee is provided. This prevents errors and ensures the new event appears in the expected kanban view for users.
Original PR description
The Onsite action only sets the hr_skills_event_add_employee key in its context, without any employee. Reading default_employee_id directly then raised a KeyError. Even before that, no attendee was added, so the new event did not match the domain of the action and stayed hidden in the kanban view. We now fall back on the employee of the current user. taskid-6361432 Forward-Port-Of: odoo/odoo#288241
The Colombian Libro Diario report now works correctly when comparison options are enabled and no longer fails with a server error. It also includes legally required journal entries that do not have a partner or label, helping ensure the report is complete and compliant.
Original PR description
## [FIX] l10n_co_reports: fix UNION ALL crash with multiple column groups ### Issue: Any comparison mode (Period, Analytic, etc.) in the Libro Diario raises an Odoo Server Error ### Cause: Each…
## [FIX] l10n_co_reports: fix UNION ALL crash with multiple column groups
### Issue:
Any comparison mode (Period, Analytic, etc.) in the Libro Diario raises an Odoo Server Error
### Cause:
Each sub-query in the `UNION ALL` had its own `ORDER BY` SQL only allows one global `ORDER BY` on a `UNION ALL`, or parentheses around each query — neither was the case
### Steps to reproduce:
- Install `l10n_co_reports` and `accountant`
- Enable Developer Mode in Settings
- Open the Libro Diario report and click the gear icon (top right)
- In the Options tab, enable Period Comparison
- Enable the Comparison for the Previous Period
Before the fix, an error is raised
------------------------------
## [FIX] l10n_co_reports: include partnerless entries in Libro Diario
### Issue:
Journal entries without a partner are excluded from the report but are legally required to appear
### Cause:
`_get_domain` called `super()` which adds `('partner_id', '!=', False)` to the domain, filtering out all partnerless entries
The SQL query also used a `JOIN` instead of `LEFT JOIN` on `res_partner`, excluding lines with no partner at the DB level
### Notes:
`NULL` values for `partner_name` or `line_label` caused the JS to hide the corresponding column headers
`header.js` matches columns to their header by `column_group_index`/`expression_label` and skips `None` values
Fixed by using `COALESCE` to return an empty string instead
### Steps to reproduce:
- Install `l10n_co_reports` and `accountant`
- Create a Journal Entry without a partner or label
- Open the Daily Journal Report
Before the fix, the entry doesn't appear
After the fix, check that PARTNER and LABEL headers are visible
opw-6430728
Forward-Port-Of: odoo/enterprise#132066
Forward-Port-Of: odoo/enterprise#129674Subscription renewals and upsells now handle cases where the original cancelled subscription no longer has a next invoice date. This prevents users from seeing an error when confirming related quotations, improving reliability for subscription sales workflows.
Original PR description
## Steps to Reproduce: - Install the Subscriptions module with demo data. - Create a quotation containing a subscription product. - Set a recurring plan and confirm the quotation. - Create an upsell…
## Steps to Reproduce: - Install the Subscriptions module with demo data. - Create a quotation containing a subscription product. - Set a recurring plan and confirm the quotation. - Create an upsell quotation or a renewal quotation. - Cancel the original subscription. - Remove the recurring plan from the cancelled subscription. - Open either the upsell or renewal quotation and confirm it. ## Error: `TypeError - '>=' not supported between instances of 'datetime.date' and 'bool'` ## Cause: Since Commit https://github.com/odoo/enterprise/commit/315be581a4212b46191e0c4f82b02a2c3fde51dc#diff-07cf1dda5423f99452a763a54fb6e7fdbb861e19b1a9dca00cab093a832490a9, `plan_id` is no longer required when a subscription is in the cancelled state. During the confirmation of an upsell or renewal quotation, the parent subscription's next invoice date is used for several date validations. However, if the parent subscription is cancelled and its plan is removed, the `next_invoice_date` is computed as False. Comparing a date object with a boolean value leads to an error. ## Fix: This commit adds an extra check before using the next invoice date. sentry-7661150764 Forward-Port-Of: odoo/enterprise#131808 Forward-Port-Of: odoo/enterprise#128093
An unused line in maintenance request creation was removed because it did not change any data. Maintenance teams are already assigned automatically when requests are created, so this cleanup has no impact on day-to-day use.
Original PR description
The create method assigned request.maintenance_team_id to itself, a no-op that reads and writes the same value and has no effect. This line originally set the team from the equipment as a fallback when creating a request. PR #196181, while refactoring mail alias handling from equipment category to team, replaced that assignment with a self-assignment, turning it into dead code. maintenance_team_id is a required field and is already a stored compute depending on equipment_id, so it is computed correctly on create without this line. Removing it has no functional impact. Forward-Port-Of: odoo/odoo#289007 Forward-Port-Of: odoo/odoo#286132