Daily updates from Odoo
Monday, November 10, 2025
105 changes
23 changes
Resolved issues and error corrections
This change prevents the website editor from getting stuck when a parallax background uses zoom effects while being edited. It improves the editing experience by keeping the page responsive and avoiding the loading spinner interruption.
Original PR description
Steps to reproduce: 1. Open website in edit mode. 2. Drop a large snippet (e.g., s_company_team_detail). 3. Add a parallax snippet below it. 4. Set the parallax scroll effect to `Zoom in` or `Zoom out`. 5. Scroll to the top of the page while keeping the parallax snippet selected. Current behavior: - The page scrolls slightly and a loading spinner appears. - Nothing happens until the user interacts. - Clicking cancels the repositioning. - Scrolling resumes the repositioning (sometimes with a delay). Root cause: The transform applied by the zoom scroll effects conflicts with the editor’s overlay repositioning, leaving the editor stuck in a loading state. Fix: Temporarily disable the transform applied by the Zoom in and Zoom out scroll effects when in edit mode. task-4925787
Channel mentions are now restored correctly when a user edits a message using the ArrowUp shortcut. This makes editing behave the same way as using the Edit action, helping prevent mentions from being lost.
Original PR description
**Description of the issue this PR addresses:** ------------------------------------------------ When editing a message via the ArrowUp shortcut, any previously mentioned channels (e.g., `#general`)…
**Description of the issue this PR addresses:** ------------------------------------------------ When editing a message via the ArrowUp shortcut, any previously mentioned channels (e.g., `#general`) were not restored in the composer. This happened because the logic to restore mentions was only applied in the `onClick()` handler of the Edit message action. **Current behavior before PR:** --------------------------------- - Editing a message using ArrowUp does not restore mentioned channels - Editing via the Edit message action still works correctly **Desired behavior after PR is merged:** ----------------------------------------- - Mentioned channels are restored when entering edit mode via ArrowUp - Behavior is consistent with editing through the Edit message action - No mentions are lost in any edit scenario **Important: This PR should only be merged for versions saas-18.2, saas-18.3, and saas-18.4.** **Backport of https://github.com/odoo/odoo/pull/229546/commits/5878e398615596adcf09eef8acbbe5aa739918f3** **Task:** 5133698 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234995 Forward-Port-Of: odoo/odoo#231192
This update corrects two issues in DHL shipping requests so labels and export declarations can be processed successfully. It fixes a misspelled customer reference field and adjusts the shipment date/time format to match DHL’s requirements, preventing avoidable delivery errors.
Original PR description
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes…
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes validation errors when communicating with the DHL API. In addition, the datetime format used for the planned shipping date and time does not conform to the expected format specified by DHL. Steps to reproduce spelling issue: 1. Create a Sales Order with a customer reference and a deliverable product. 2. Validate the SO. 3. Go to the delivery, select DHL as carrier, and confirm. → Error: Validation error #/content/exportDeclaration: extraneous key [recepientReference] is not permitted. Steps to reproduce datetime issue: 1. Create a delivery using the DHL carrier. 2. Confirm the delivery. 3. Return the delivery. 4. Click "Print Return Label". → Error: Bad request #/plannedShippingDateAndTime is not well formatted (expected format: '2010-02-11T17:10:09 GMT+01:00'). Official DHL documentation: https://developer.dhl.com/sites/default/files/2025-11/dpdhl-express-api-3.1.1_swagger.yaml opw-5024363 Forward-Port-Of: odoo/enterprise#98981
This change fixes a visual issue where the breadcrumb label could briefly show the wrong name or flicker when moving between livechat sessions. It improves the user experience by keeping the session title consistent and readable during navigation.
Original PR description
Before this PR, The breadcrumbs flickered when navigating between livechat sessions. This occurred because the `FormController`…
Before this PR,
The breadcrumbs flickered when navigating between livechat sessions.
This occurred because the `FormController` ([@web/views/form/form_controller](https://github.com/odoo/odoo/blob/saas-18.3/addons/mail/static/src/core/web/discuss_patch.js#L16-L23))
updated the breadcrumb title inside the `onRendered` hook and set it to
`this.model.root.data.display_name` which is `undefined`, the `Discuss` component
also updated the breadcrumb title in a `useEffect` hook. ([@mail/code/web/discuss_patch.js](https://github.com/odoo/odoo/blob/saas-18.3/addons/mail/static/src/core/web/discuss_patch.js#L16-L23))
The two updates conflicted: the onRendered hook first set the title to
“Unnamed,” and then the useEffect hook replaced it with the correct title,
causing a brief flicker. Additionally, when navigating to another session with
the same thread.displayName, the useEffect hook did not trigger (since its
dependency did not change), but onRendered still ran, causing the breadcrumb
to remain “Unnamed”.
This PR fixes the issue by introducing a `LivechatFormController` which
updates the breadcrumbs when channel is fetched in store.
task-4671251
Before:

After:

task-4671251
Forward-Port-Of: odoo/odoo#233167This change fixes an error that appeared when users tried to upload a non-PDF file in the Sign app while debug mode was enabled. Instead of showing a traceback, the app now displays a clear message telling users the file type is not supported.
Original PR description
Version: - saas-18.3 Steps to reproduce: - Enable debug mode. - Try uploading a non-PDF file in the Sign app. Before: - Uploading a non-PDF file in debug mode caused a traceback error. - The TemplateAlertDialog component tried to use a message prop that wasn’t defined. After: - Replaced the use of the undefined message prop with the correct body prop to display the error message. Impact: - Fixes the traceback error in debug mode. - Shows a clear and user-friendly error message when uploading unsupported file types. task-4828439 Forward-Port-Of: odoo/enterprise#89081
This update prevents Shiprocket from failing when tax mapping is used but the expected GST tax labels are not available. It also makes the related test more reliable by explicitly using a 15% tax, so the check behaves consistently across different company setups.
Original PR description
Some other test adds a fiscal position with tax mapping. This creates 2 problems 1. The new taxes have a tag, which means we evaluate the right hand of…
Some other test adds a fiscal position with tax mapping. This creates 2 problems
1. The new taxes have a tag, which means we evaluate the right hand of
https://github.com/odoo/enterprise/blob/8d3fe30c627eada1186c15480876fb2e8f7ddb59/delivery_shiprocket/models/shiprocket_request.py#L239
However, since l10n_in is not installed,
`tax.env.ref(f"l10n_in.tax_tag_{gst}gst", False)`
does not return anything (False is not a fallback)
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/api.py#L588
So we end up looking for `None` in `tax_tag_ids`, which leads us to compare the `_name` properties, see
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/models.py#L6545-L6558
2. The test added in 4d5df93 was assuming the default company 15% tax, which was not always true
Solution
-----
1. Provide a fallback for the `ref` lookup
2. Force a 15% tax in the test
-----
runbot-232692
Forward-Port-Of: odoo/enterprise#99027
Forward-Port-Of: odoo/enterprise#97998Quality checks created from receipts now use the correct company instead of the currently active one. This prevents errors in multi-company setups when a receipt is confirmed from a different company than the one linked to the control point.
Original PR description
When creating quality checks per quantity, a multi-company error occurs if the active company differs from the one defined on the control point. Steps to reproduce: - Create a Quality Control Point for Company B and Product Table for the receipt operation with a per-quantity control. - Create a receipt in Company B for this product but leave it in draft. - Switch to Company A and try to confirm → error. Root cause: The company_id was not set when creating the quality check, causing it to default to `env.company` (A) instead of the stock move line’s company (B). opw-86993 Forward-Port-Of: odoo/enterprise#99024 Forward-Port-Of: odoo/enterprise#98655
This update prevents an access error that could occur when opening the Documents app after a company was archived. It ensures users only see folders they are allowed to access, improving reliability when managing documents across companies.
Original PR description
**Steps to reproduce:** - Add some folders - Create a new company - Assign some folders to the new company - Archive the company - Click on Documents app - AccessError is raised when opening it…
**Steps to reproduce:** - Add some folders - Create a new company - Assign some folders to the new company - Archive the company - Click on Documents app - AccessError is raised when opening it **Issue:** The issue seems to be related to caching issue on the field `type` when fetching the documents with `search_panel_select_range` and going through `_compute_display_name`: `folders = accessible_records.filtered(lambda d: d.type == 'folder')` This error was quite inconsistent and might be related to the cache missing some prefetched data on a record it shouldn't have been able to read. There is a need to ensure only the folders available to the user are able to be fetched. **Fix:** Added the `type` field in the `search_panel_fields` but this might not be needed if the issue comes from elsewhere. For now the issue was mitigated by explicitly checking for the user companies in the domain of the searchs, but it needs to be checked as this behavior might break other flows. opw-4931278 Forward-Port-Of: odoo/enterprise#99043 Forward-Port-Of: odoo/enterprise#96817
Products with a single non-variant option now correctly reuse the same cart line instead of creating a new one each time they are added. This prevents duplicate entries in the shopping cart and keeps the checkout experience consistent for customers.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have a product attribute with variant creation set to never; 2. have product using only this attribute, with only a single value; 3. open website editor on…
Versions -------- - 18.0+ Steps ----- 1. Have a product attribute with variant creation set to never; 2. have product using only this attribute, with only a single value; 3. open website editor on /shop; 4. enable add-to-cart button & save; 5. use button on the aforementioned product at least twice. Issue ----- Each time the product gets added, a new line is created. Cause ----- Because there's only a single value, the product configurator doesn't pop up by default when adding the product to the cart. Without the configurator pop-up, the `_cart_update` method doesn't receive any `no_variant_attribute_value_ids`, which are used find a matching line if the product template has any `no_variant` attribute. Solution -------- Instead of checking `product.product_tmpl._has_no_variant_attributes()`, to see if we should attempt to match `no_variant_attribute_value_ids`, check if the added product has any `no_variant` attributes that have more than one value or are optional (multi-checkbox). If not, a `no_variant` product behaves the same as a single-variant product. opw-5093175 opw-5137351 Forward-Port-Of: odoo/odoo#234958 Forward-Port-Of: odoo/odoo#233452
Amazon shipment updates now include the carrier code required in some countries, making delivery notifications more reliable. If the carrier cannot be matched exactly, the system sends a safe fallback so Amazon can still use the carrier name.
Original PR description
The `POST_ORDER_FULFILLMENT_DATA` feed that is used to push order delivery info to Amazon should follow the `OrderFulfillment` schema (see https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderFulfillment.xsd), but it was missing the `CarrierCode` element, which is required in some countries. This commit adds the missing element to the payload, with the formatted carrier name as a value. If the carrier name cannot be matched, "Other" is used as a fallback to signal Amazon that they should rely on the `CarrierName` instead. Forward-Port-Of: odoo/enterprise#99026
This fix allows sales orders created in a branch company to use payment providers set up on the parent company. It prevents customers from seeing a “No compatible payment providers found” message when paying online from a branch.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have a published payment provider; 2. create a branch company; 3. create a sales order in branch company; 4. enable online payment for sales order; 5. open sales order in portal view; 6. attempt to pay. Issue ----- No compatible payment providers found. Cause ----- The `payment.provider._check_company_domain` is set to the default exact match, so when it's used in `_get_compatible_payment_providers`, it's unable to find any providers for the branch company. Solution -------- Set `_check_company_domain` to `check_company_domain_parent_of`. opw-5214269 Forward-Port-Of: odoo/odoo#234821 Forward-Port-Of: odoo/odoo#234763
This update restores menu mode in the self-ordering flow so customers can browse and order as expected. It improves the reliability of the ordering experience and prevents interruptions at checkout.
Original PR description
Menu mode was broken in self ordering. This commit fix it. Forward-Port-Of: odoo/odoo#234460 Forward-Port-Of: odoo/odoo#232503
Grouping records by a property tags field now works correctly in list views, even when users search within the grouped results. This prevents an error that could interrupt normal CRM usage and keeps grouped views stable.
Original PR description
Step to reproduce: - open crm and add a property tags field in a lead - add that tags in few leads - go to list view and group by that property tags field - search for a lead (keep groupby as it is)…
Step to reproduce:
- open crm and add a property tags field in a lead
- add that tags in few leads
- go to list view and group by that property tags field
- search for a lead (keep groupby as it is)
Observation:
- we receive a traceback
```
File "/home/odoo/odoo/codebase/odoo/saas-18.4/addons/web/models/models.py", line 396, in web_read_group
self._open_groups(
File "/home/odoo/odoo/codebase/odoo/saas-18.4/addons/web/models/models.py", line 537, in _open_groups
info_opening['value']: info_opening
TypeError: unhashable type: 'list'
```
Cause:
- `formatter_property_tags` returns a list in case of tags field.
https://github.com/odoo/odoo/blob/5186fd202373a67f56688c234fcde15cc1997721/addons/web/models/models.py#L1176
- these values are used as a key for dict in `_open_groups`, hence only hashable values are allowed; list is not hashable
https://github.com/odoo/odoo/blob/5186fd202373a67f56688c234fcde15cc1997721/addons/web/models/models.py#L536-L539
Fix:
- cast the list to tuple
opw-5188961
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix allows duplicate payroll slips to be canceled even when they share the same work entries. The system now only resets work entries to draft when they belong to the payslip being canceled, avoiding unintended side effects on other slips.
Original PR description
previous behavior: - Cancelling duplicate payslips wasn't possible because they had the same work entries linked current behavior: - Allows to cancel a duplicate payslip without affecting the linked work entries - Work entries are only set to draft when they are linked to one payslip that is being cancelled - added `test_duplicate_payslips_cancellation` task-id: 5075882
This change corrects a failing automated test in the manufacturing accounting area after a previous update to how duration is calculated. It helps keep the test suite reliable so future changes can be validated with confidence.
Original PR description
### Issue: This is caused by changing the duration inverse in #233777. ### Cause: Before #233777, in duration inverse, only sum of `time_ids` was taken into account to calculate the `duration`. After that PR, `time_ids` with `get_working_duration` are also taken into account which cause this test fail. runbot-233742
This update corrects how tax report returns are generated when a country has multiple report types. It prevents duplicate or incorrect closing entries and ensures some reports move to a review-and-submit flow when a closing entry is not needed, improving the accuracy of tax reporting.
Original PR description
It's possible for different tax reports to exist in the same country, each with its own return type. However, this is an issue when they aren't configured to generate closing entries with distinct contents, since each of them will then repeat the content of the other. To fix this, when it's legitimate to make multiple closing entries, we make sure the closing entry only considers the tax move lines linked to the report's tax tags. If multiple reports must generate the same closing entry (typically because one of them is a simplified version of the other), we disable the generation of the return for one of them. Some reports also didn't need to generate a closing entry and were switched to a 'review_submit' state. task-5123564 Forward-Port-Of: odoo/enterprise#98158
This update adjusts Odoo’s email sending setup to work correctly on newer Debian Trixie systems. It prevents warning messages and connection issues when testing or using the built-in mail server, helping email features remain reliable across environments.
Original PR description
Forward-Port-Of: odoo/odoo#234020 Forward-Port-Of: odoo/odoo#232699
Point of Sale now sends orders to the server one at a time instead of in large batches. This reduces the risk of timeouts and missing orders, especially when some orders take longer to process, such as those that need invoicing. Loyalty coupon confirmation was also adjusted so it happens correctly for each order during this process.
Original PR description
`syncAllOrders` method is now splitting the list of orders to synchronize them one by one. This allows to have better control over each order synchronization and error handling. Some customer were experiencing issues when synchronizing too many orders at once, leading to lost orders or orders not being synchronized properly. For example, synchronizing orders that needs to be invoiced takes too long and can lead to timeout issues. By synchronizing orders one by one, we ensure that each order is properly synchronized before moving to the next one. --- Modification in `pos_loyalty` module to adapt to this change: The `confirm_coupon_programs` method is now called for each order individually, instead of being called once for all orders in the `payment_screen`. This ensures that coupon programs are confirmed correctly for each order even when orders synchronization is delayed Forward-Port-Of: odoo/odoo#233870 Forward-Port-Of: odoo/odoo#232073
This fix ensures that when a delivery is split into two, the original delivery’s availability status is recalculated correctly. It prevents the system from showing outdated stock information, which helps users trust the quantities shown during warehouse operations.
Original PR description
Steps to reproduce: - Create a storable product “P1” - Update its quantity to 10 - Create a delivery picking with 10 units of P1 - Confirm → The picking is in “Ready” state and the move is “Available” - Update the “Quantity” of P1 to 6 units in the picking → The move state is recomputed to “Partially Available”, since the demanded quantity exceeds the quantity done. https://github.com/odoo/odoo/blob/18.0/addons/stock/models/stock_move.py#L2207-L2208 - Split the picking Problem: A new picking is created with 4 units in quantity and its move is “Available”, but the original move with 6 units does not have its state recomputed. opw-5173374 Forward-Port-Of: odoo/odoo#232516
This change fixes an issue where saving a default value could fail if duplicate default records already existed. The system now selects only one matching record, which avoids an error and lets the save complete normally.
Original PR description
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found,…
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found, accessing `default.json_value` raises a singleton error.
This fix makes sure the search only picks one record, avoiding that crash.
Before fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(9,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
Traceback (most recent call last):
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5630, in ensure_one
_id, = self._ids
^^^^
ValueError: too many values to unpack (expected 1)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/odoo/odoo/odoo/odoo/addons/base/models/ir_default.py", line 107, in set
if default.json_value != json_value:
^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/odoo/odoo/orm/fields.py", line 1670, in __get__
record.ensure_one()
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5633, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: ir.default(4, 9)
```
After fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(10,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
True
```
opw-5228419
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#234944
Forward-Port-Of: odoo/odoo#234893This change makes the Belgian blackbox point of sale more resilient when the internet connection drops during order synchronization. If an order cannot be signed because the connection is lost, it is now returned to a draft state so the cashier can try again later instead of the order getting stuck.
Original PR description
When trying to sync orders while being offline, a `ConnectionLostError` is raised. This error was not handled in the pos_blackbox_be module. Now, if an order was not signed correctly by the blackbox, we put its state back to "draft", allowing the cashier to retry later (when the connection to bbox is re-established). Forward-Port-Of: odoo/enterprise#98778
When users click a channel in the Discuss Kanban view, Odoo now opens the channel form instead of doing nothing. This makes channel navigation work as expected and improves the experience for users managing discussions.
Original PR description
**Steps to reproduce:** Open 'Discuss' Click on 'Channel' in the menu to display channels in kanban view Click on any channel **Cause**: The action 'mail.discuss_channel_action' did not include form view in view_mode. **Effect**: Clicking on a kanban card does not display the form view. **Fix**: Open the form view of a channel when clicking on a kanban card. Task-5076555 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227668
This change fixes an issue where installing the Argentina withholding demo data could create duplicate taxes with the same name. It keeps the demo setup clean and avoids confusion when users review or configure taxes.
Original PR description
**Description of the issue/feature this PR addresses**: This pr is to avoid duplicated taxes when the demo data is installed. **Steps to reproduce**: 1. Install l10n_ar_withholding module with demo…
**Description of the issue/feature this PR addresses**: This pr is to avoid duplicated taxes when the demo data is installed. **Steps to reproduce**: 1. Install l10n_ar_withholding module with demo data. 2. Take position in "(AR) Responsable Inscripto" company. 3. Check the taxes created on "Invoicing > Configuration > Accounting > Taxes". 4. Delete the filter "Sale or Purchase". 5. Add custom filter: Argentina Withholding Payment Tax type (l10n_ar_withholding_payment_type) is in ["supplier", "customer"]. 6. You will see that there are duplicated taxes (duplicated names) with suffix (Copy). **Current behavior before PR**: Duplicated taxes are created when demo data is installed. <img width="1597" height="795" alt="image" src="https://github.com/user-attachments/assets/51b65037-bb89-4ec7-8adf-21636b68e405" /> **Desired behavior after PR is merged**: No duplicated taxes are created when demo data is installed. _Task latam side_: 1360. _Task Adhoc side_: 57627. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226992
14 changes
Resolved issues and error corrections
This update corrects two issues in DHL shipment requests: a misspelled customer reference field and an incorrect date/time format. As a result, DHL labels and return labels should now be created more reliably without avoidable validation errors.
Original PR description
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes…
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes validation errors when communicating with the DHL API. In addition, the datetime format used for the planned shipping date and time does not conform to the expected format specified by DHL. Steps to reproduce spelling issue: 1. Create a Sales Order with a customer reference and a deliverable product. 2. Validate the SO. 3. Go to the delivery, select DHL as carrier, and confirm. → Error: Validation error #/content/exportDeclaration: extraneous key [recepientReference] is not permitted. Steps to reproduce datetime issue: 1. Create a delivery using the DHL carrier. 2. Confirm the delivery. 3. Return the delivery. 4. Click "Print Return Label". → Error: Bad request #/plannedShippingDateAndTime is not well formatted (expected format: '2010-02-11T17:10:09 GMT+01:00'). Official DHL documentation: https://developer.dhl.com/sites/default/files/2025-11/dpdhl-express-api-3.1.1_swagger.yaml opw-5024363 Forward-Port-Of: odoo/enterprise#98981
Branch companies can now use payment providers set up at the parent company level when customers pay online from a sales order. This prevents checkout from failing with no compatible providers found and makes online payment work more smoothly across company structures.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have a published payment provider; 2. create a branch company; 3. create a sales order in branch company; 4. enable online payment for sales order; 5. open sales order in portal view; 6. attempt to pay. Issue ----- No compatible payment providers found. Cause ----- The `payment.provider._check_company_domain` is set to the default exact match, so when it's used in `_get_compatible_payment_providers`, it's unable to find any providers for the branch company. Solution -------- Set `_check_company_domain` to `check_company_domain_parent_of`. opw-5214269 Forward-Port-Of: odoo/odoo#234821 Forward-Port-Of: odoo/odoo#234763
When Odoo sends delivery information to Amazon, it now includes the carrier code required by Amazon in some countries. If the carrier cannot be matched exactly, Odoo will send a fallback value so Amazon can still process the shipment using the carrier name.
Original PR description
The `POST_ORDER_FULFILLMENT_DATA` feed that is used to push order delivery info to Amazon should follow the `OrderFulfillment` schema (see https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderFulfillment.xsd), but it was missing the `CarrierCode` element, which is required in some countries. This commit adds the missing element to the payload, with the formatted carrier name as a value. If the carrier name cannot be matched, "Other" is used as a fallback to signal Amazon that they should rely on the `CarrierName` instead. Forward-Port-Of: odoo/enterprise#99026
This fix ensures returned goods are sent to the right place: subcontracted items go to the subcontractor location, while regular supplier returns go back to the supplier. It prevents returns from being routed incorrectly when a receipt includes both subcontracted and non-subcontracted products, reducing fulfillment errors and manual corrections.
Original PR description
Steps to reproduce the bug: - Create a storable product "P1" and "P2" with vendor "azure interior" - for P2 subcontracting BoM referencing "azure interior" as subcontractor and component "C1" -…
Steps to reproduce the bug: - Create a storable product "P1" and "P2" with vendor "azure interior" - for P2 subcontracting BoM referencing "azure interior" as subcontractor and component "C1" - Create a receipt for partner "azure interior" including 1 unit of P1 and 1 unit of P2 - Validate the receipt - Create a return for both P1 and P2 Problem: A picking is created with destination location set to the subcontracting location for both products, instead of setting the partner location only for subcontracted products. Solution: Ensure only the move line for subcontracted products uses the subcontracting destination location, while other returned products go back to the supplier location. When the `picking_id.partner_id`` is changed, it triggers a write on the picking, which in turn triggers a write on its moves, but only on the ones that are not scrapped. However, since the `scrapped`` field is a stored computed field, and as it hasn't been accessed before, it needs to be computed. And because its computation depends on `location_dest_id`, that field also needs to be recomputed. as a result, the `location_dest_id`` of the moves that we manually set may be changed unexpectedly. Therefore, in the `_create_return`` function, we check that the picking’s `partner_id` is different from the moves’ partner_id before updating it, to avoid unnecessary writes and the chain of recomputations that could alter our values. Resetting the picking’s partner_id based on the move’s partner_id could actually be removed in master, as it serves no real purpose, the move.partner_id itself is already derived from the picking’s partner_id. We just keep it in stable versions to avoid any unexpected behavior changes. opw-5208289 Forward-Port-Of: odoo/odoo#234521
Users with Recruitment access can now send referral campaigns without hitting an access error, even if they do not have employee permissions. This fixes a blocking issue in the recruitment flow so eligible users can complete the campaign action normally.
Original PR description
STEP TO REPRODUCE:
------------------
1- Give to Marc Demo the right : Recruitment / Administrator (be sure he doesn't have any right on Employees)
2- Log as Marc Demo
3- Go to Recruitment
4- Click on the three dots in kanban card
5- Click on Referral Campaign
6- Click on Send
You will have an access error
This user (with these groups) should be able to send a referral campaign
task-5082344
Forward-Port-Of: odoo/enterprise#98712
Forward-Port-Of: odoo/enterprise#96746Products with a non-variant attribute and only one available option will now be matched correctly in the cart instead of being added as a new line every time. This prevents duplicate lines for the same item and makes shopping cart behavior more consistent for customers.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have a product attribute with variant creation set to never; 2. have product using only this attribute, with only a single value; 3. open website editor on…
Versions -------- - 18.0+ Steps ----- 1. Have a product attribute with variant creation set to never; 2. have product using only this attribute, with only a single value; 3. open website editor on /shop; 4. enable add-to-cart button & save; 5. use button on the aforementioned product at least twice. Issue ----- Each time the product gets added, a new line is created. Cause ----- Because there's only a single value, the product configurator doesn't pop up by default when adding the product to the cart. Without the configurator pop-up, the `_cart_update` method doesn't receive any `no_variant_attribute_value_ids`, which are used find a matching line if the product template has any `no_variant` attribute. Solution -------- Instead of checking `product.product_tmpl._has_no_variant_attributes()`, to see if we should attempt to match `no_variant_attribute_value_ids`, check if the added product has any `no_variant` attributes that have more than one value or are optional (multi-checkbox). If not, a `no_variant` product behaves the same as a single-variant product. opw-5093175 opw-5137351 Forward-Port-Of: odoo/odoo#234958 Forward-Port-Of: odoo/odoo#233452
This change updates how page assets are included in the appointment and rental website snippets. It helps keep these pages working with the latest Odoo asset structure and reduces the risk of display or loading issues after upgrades.
Original PR description
See https://github.com/odoo/odoo/pull/104836 task-2963840 Forward-Port-Of: odoo/enterprise#98250 Forward-Port-Of: odoo/enterprise#35153
This change stops website assets from being accidentally turned off when modules are updated. It helps keep older page elements working correctly, while unused assets are still cleaned up later by the system's regular maintenance process.
Original PR description
Before this commit when a module was updated all ir.asset records were reset to their defined `active` state, if defined. This causes assets related to old snippet versions to be made inactive even…
Before this commit when a module was updated all ir.asset records were
reset to their defined `active` state, if defined.
This causes assets related to old snippet versions to be made inactive
even if those old snippet versions are used inside existing pages.
It used to work when the activation of assets was made through view
inheritance because when views are defined through a `<template>` tag,
the `active` attribute is in fact ignored during updates since [1],
except for new records since [2].
This commit introduces an `<asset>` tag in the XML import format.
It is an alias of `<record ... model="ir.asset">` with the additional
feature that it avoids taking the `active` field into account during
updates for existing `ir_asset` records, just like `<template>` if the
`active` field is mentioned as attribute of the tag.
We then rely on the `website_disable_unused_snippets_assets` cron to
properly disable any unused asset at a later stage (note that the bug
being fixed here was mitigated by the fact that cron also re-enabled
assets which were disabled by mistake... but that might happen only a
few days later).
Another approach was to overload `_load_records_write` in `base`'s
`ir_asset.py` to avoid taking the `active` field into account when
updating records:
```py
def _load_records_write(self, values):
values.pop('active', None)
super()._load_records_write(values)
```
But this is not as stable because it changes the way `ir.asset` records
are imported when the `<record>` tag is used. In the end we chose to be
consistent and do exactly the same as `<template>`, as this also allows
more and should be entirely stable.
[1]: https://github.com/odoo/odoo/commit/2d296cb77922d33be2dc45b900191fac34bda429#diff-175c28787c272a219b9275f79262a48af9aa029e718f45077fd609737559e84eR803-R804
[2]: https://github.com/odoo/odoo/commit/f1c70d4cc943ac4eb81a85a9dc005de34cd2060a#diff-175c28787c272a219b9275f79262a48af9aa029e718f45077fd609737559e84eR801-R804
task-2963840
(Follow-up of https://github.com/odoo/upgrade/pull/3829)
Forward-Port-Of: odoo/odoo#233402
Forward-Port-Of: odoo/odoo#104836When users click a channel in the Discuss kanban view, Odoo now opens the channel’s form view instead of doing nothing. This makes it easier to review and manage channel details directly from the channel list.
Original PR description
**Steps to reproduce:** Open 'Discuss' Click on 'Channel' in the menu to display channels in kanban view Click on any channel **Cause**: The action 'mail.discuss_channel_action' did not include form view in view_mode. **Effect**: Clicking on a kanban card does not display the form view. **Fix**: Open the form view of a channel when clicking on a kanban card. Task-5076555 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change prevents Spreadsheet from crashing when users freeze and share a sheet that includes a boolean global filter. It ensures Excel export works reliably even when a filter has no selected value, avoiding interruptions for users.
Original PR description
The method `getFilterDisplayValue` would not handled `undefined` values for boolean global filters, causing crashes when exporting to Excel. Task: [5188932](https://www.odoo.com/web#id=5188932&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form) 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
This change updates Odoo’s email server handling so it works correctly on newer Debian Trixie environments. It prevents mail-related warnings and failures caused by changes in how system libraries handle secure connections and local address resolution.
Original PR description
Forward-Port-Of: odoo/odoo#234020 Forward-Port-Of: odoo/odoo#232699
This change stops Hoot tests from creating unnecessary IndexedDB databases during full test runs. It helps keep automated testing cleaner and more reliable, while IndexedDB coverage remains in dedicated tests.
Original PR description
Disable IndexedDB in Hoot tests to avoid creating to much IndexedDB databases when running the full test suite. IndexedDB is still tested in dedicated tours.
This fix ensures Odoo only uses one matching default record when saving a default value. It prevents a rare crash caused by duplicate records, so users can set defaults without interruption.
Original PR description
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found,…
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found, accessing `default.json_value` raises a singleton error.
This fix makes sure the search only picks one record, avoiding that crash.
Before fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(9,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
Traceback (most recent call last):
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5630, in ensure_one
_id, = self._ids
^^^^
ValueError: too many values to unpack (expected 1)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/odoo/odoo/odoo/odoo/addons/base/models/ir_default.py", line 107, in set
if default.json_value != json_value:
^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/odoo/odoo/orm/fields.py", line 1670, in __get__
record.ensure_one()
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5633, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: ir.default(4, 9)
```
After fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(10,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
True
```
opw-5228419
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#234944
Forward-Port-Of: odoo/odoo#234893This update prevents the Mail module from failing during uninstallation when related database fields have already been removed. It helps ensure the module can be cleanly removed and later reinstalled without database errors.
Original PR description
When uninstalling module mail, an override of `unlink()` deletes the activities of the records being deleted. However, this override crashes whenever columns of `mail.activity` have been dropped already. As a consequence, it may prevent the deletion of the field `mail_message_id` of model `mail.tracking.value`, and its table, too. And this causes the reinstallation of module mail to log error: ``` column "mail_message_id" of relation "mail_tracking_value" contains null values ``` See https://runbot.odoo.com/odoo/runbot.build.error/233618 for the cases where it failed. The fix consists in checking whether the columns of `mail.activity` still exist before searching for activities.
3 changes
Resolved issues and error corrections
This update corrects two issues that could prevent DHL shipments and return labels from being created successfully. It fixes a misspelled customer reference field and adjusts the shipping date format to match DHL’s required format, reducing failed deliveries and manual rework.
Original PR description
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes…
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes validation errors when communicating with the DHL API. In addition, the datetime format used for the planned shipping date and time does not conform to the expected format specified by DHL. Steps to reproduce spelling issue: 1. Create a Sales Order with a customer reference and a deliverable product. 2. Validate the SO. 3. Go to the delivery, select DHL as carrier, and confirm. → Error: Validation error #/content/exportDeclaration: extraneous key [recepientReference] is not permitted. Steps to reproduce datetime issue: 1. Create a delivery using the DHL carrier. 2. Confirm the delivery. 3. Return the delivery. 4. Click "Print Return Label". → Error: Bad request #/plannedShippingDateAndTime is not well formatted (expected format: '2010-02-11T17:10:09 GMT+01:00'). Official DHL documentation: https://developer.dhl.com/sites/default/files/2025-11/dpdhl-express-api-3.1.1_swagger.yaml opw-5024363 Forward-Port-Of: odoo/enterprise#98981
Amazon order delivery updates now include the carrier code when Odoo sends fulfillment information. This helps ensure shipments are accepted correctly in countries where that field is required, reducing the risk of delivery sync issues.
Original PR description
The `POST_ORDER_FULFILLMENT_DATA` feed that is used to push order delivery info to Amazon should follow the `OrderFulfillment` schema (see https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderFulfillment.xsd), but it was missing the `CarrierCode` element, which is required in some countries. This commit adds the missing element to the payload, with the formatted carrier name as a value. If the carrier name cannot be matched, "Other" is used as a fallback to signal Amazon that they should rely on the `CarrierName` instead. Forward-Port-Of: odoo/enterprise#99026
When a pivot table is sorted by a date or date-time field in the web view, inserting it into a spreadsheet now keeps the same sort order. This fixes an issue where the date values were not normalized correctly, which could make the spreadsheet version appear unsorted.
Original PR description
If on the web pivot view we create a pivot with a date/dateTime field in the columns, and sort on one of these columns, the resulting pivot when inserted in a spreadsheet isn't sorted. This was because we didn't normalize the date values in the pivot `sortedColumn`, and we had UTC timestamps `2023-01-01 00:00:00` instead of normalized values `01/2023`. Task: [3575465](https://www.odoo.com/web#id=3575465&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form)
12 changes
Resolved issues and error corrections
Fixes an issue where editing a website checkout page after adding a rental-related product could trigger an error due to repeated tooltip cleanup. The change limits cleanup to the intended rental information messages, making the checkout and website editing flow more reliable.
Original PR description
Following commits odoo/odoo@d37d908 and odoo/enterprise@901b8ea, the tooltip cleanup logic disposes elements in `website_sale_renting`, and when the same logic runs again in `payment`, it tries to…
Following commits odoo/odoo@d37d908 and odoo/enterprise@901b8ea, the tooltip cleanup logic disposes elements in `website_sale_renting`, and when the same logic runs again in `payment`, it tries to dispose them a second time, causing a null element error.
Steps to reproduce:
1. Install `website_sale_renting`
2. Install a demo payment method
3. Go to the shop, add any product to the cart, proceed to payment
4. Click the "Edit" button on the website → observe the error
```js
web.assets_frontend_lazy.min.js:3912 TypeError: Cannot read properties of null
(reading 'closest') at Tooltip.dispose (web.assets_frontend_lazy.min.js:2710:70)
at PaymentForm.<anonymous> (web.assets_frontend_…zy.min.js:8282:1450)
at Colibri.destroyInteraction (web.assets_frontend_lazy.min.js:6472:68)
at Colibri.destroy (web.assets_frontend_lazy.min.js:6524:55)
at InteractionService.stopInteractions (web.assets_frontend_lazy.min.js:6584:162)
at InteractionService.stopInteractions (web.assets_frontend_lazy.min.js:6625:907)
at stop (website.assets_insid…rame.min.js:137:290)
at HTMLDocument.<anonymous> (website.assets_insid…rame.min.js:153:450)
at WebsiteBuilderClientAction.onEditPage (web.assets_web.min.js:22215:55)
```
- Restrict tooltip handling to elements with the .o_rental_info_message class to ensure only the intended elements are selected.
- This fix ensures tooltip cleanup is performed safely without re-disposing already disposed elements.
Forward-Port-Of: odoo/enterprise#98748Amazon order fulfillment updates now include the carrier code required in some countries. This helps delivery confirmations match Amazon's expected format and reduces the risk of rejected or incomplete shipment updates.
Original PR description
The `POST_ORDER_FULFILLMENT_DATA` feed that is used to push order delivery info to Amazon should follow the `OrderFulfillment` schema (see https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderFulfillment.xsd), but it was missing the `CarrierCode` element, which is required in some countries. This commit adds the missing element to the payload, with the formatted carrier name as a value. If the carrier name cannot be matched, "Other" is used as a fallback to signal Amazon that they should rely on the `CarrierName` instead. Forward-Port-Of: odoo/enterprise#99026
The Sign app now handles unsupported file uploads properly when debug mode is enabled. Instead of showing a technical crash, users see a clear message explaining that the file type is not supported.
Original PR description
Version: - saas-18.3 Steps to reproduce: - Enable debug mode. - Try uploading a non-PDF file in the Sign app. Before: - Uploading a non-PDF file in debug mode caused a traceback error. - The TemplateAlertDialog component tried to use a message prop that wasn’t defined. After: - Replaced the use of the undefined message prop with the correct body prop to display the error message. Impact: - Fixes the traceback error in debug mode. - Shows a clear and user-friendly error message when uploading unsupported file types. task-4828439 Forward-Port-Of: odoo/enterprise#89081
This fix makes Shiprocket delivery tax processing more robust when India GST tax data is not available. It also stabilizes related tests by using a consistent tax rate, reducing false failures and improving reliability.
Original PR description
Some other test adds a fiscal position with tax mapping. This creates 2 problems 1. The new taxes have a tag, which means we evaluate the right hand of…
Some other test adds a fiscal position with tax mapping. This creates 2 problems
1. The new taxes have a tag, which means we evaluate the right hand of
https://github.com/odoo/enterprise/blob/8d3fe30c627eada1186c15480876fb2e8f7ddb59/delivery_shiprocket/models/shiprocket_request.py#L239
However, since l10n_in is not installed,
`tax.env.ref(f"l10n_in.tax_tag_{gst}gst", False)`
does not return anything (False is not a fallback)
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/api.py#L588
So we end up looking for `None` in `tax_tag_ids`, which leads us to compare the `_name` properties, see
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/models.py#L6545-L6558
2. The test added in 4d5df93 was assuming the default company 15% tax, which was not always true
Solution
-----
1. Provide a fallback for the `ref` lookup
2. Force a 15% tax in the test
-----
runbot-232692
Forward-Port-Of: odoo/enterprise#99027
Forward-Port-Of: odoo/enterprise#97998Fixed an issue where converting very large Excel files with many sheets into Odoo spreadsheets could fail with an error. This improves reliability for users working with complex uploaded spreadsheets in Documents.
Original PR description
Steps to reproduce: - upload a large xlsx file (e.g. with >1000 sheets) - open it and convert it to o-spreadsheet => traceback Task: 5222481 Forward-Port-Of: odoo/enterprise#99087 Forward-Port-Of: odoo/enterprise#98443
Fixes Swedish POS fiscal reporting so sales orders are correctly validated through the required blackbox process again. It also restores reliable receipt reprint tracking and corrects the organisation number format, helping businesses stay compliant with Swedish point-of-sale requirements.
Original PR description
Before this commit, the Swedish blackbox was completely broken in 18.0 because the `push_single_order` function is no longer used. To fix this, the same approach as `pos_blackbox_be` was used, where the `preSyncAllOrders` function was overridden instead. In addition, the old receipt reprinting logic was no longer working, and so it now uses the `nb_print` field to keep track of the number of reprints. Finally, we also forward port a fix from 17.0 (ddbc1fc) to correct the format of the organisation number, which for some reason was not forward ported originally. task-5077448 Forward-Port-Of: odoo/enterprise#98437 Forward-Port-Of: odoo/enterprise#98139
This fix ensures payroll work entries stay accurate when employee attendance records are created, edited, or deleted. It prevents duplicate, missing, or wrongly removed work entries so payroll calculations better reflect actual attendance time.
Original PR description
[FIX] hr_work_entry: fix work entries not being regenerated on attendance modification Steps to reproduce: - In Attendance, create, modify or delete an attendance - In Payroll, go to the work entries…
[FIX] hr_work_entry: fix work entries not being regenerated on attendance modification Steps to reproduce: - In Attendance, create, modify or delete an attendance - In Payroll, go to the work entries tab - If creating an attendance, work entries with the previous and current attendance duration will be displayed - If modifying an attendance, changing the duration would not create a new work entry nor modify the existing one(s) - If deleting an attendance, the work entry would be deleted even if there were other attendances on the same day Reason: - For creation, the method creating work entries from attendances had a strict inequality, which caused the check to never trigger. - For modification, nothing was done to regenerate the work entry after editing the duration. - For deletion, the method archived work entries regardless of whether or not there were other attendances in the day. How it was fixed: - For creation, changed the strict inequalities to inequalities to allow the check for work entries to be made - For modification, if the check in or check out dates are changed, triggers the regeneration of linked worked entries - For deletion, the work entry is only deleted when no attendances are left, and then regenerate work entries to match the new total attendance duration Task ID: 5116353 Forward-Port-Of: odoo/enterprise#96635
The Accounting Reports control panel now handles narrow mobile screens correctly. Users can scroll horizontally within the report controls while the header remains stable, making reports easier to use on phones.
Original PR description
Before this commit, the control panel had an overflow in mobile view. The classes `mx-auto` and `fit-content` were causing the issue, so they got taken out. The class `overflow-x-auto` got put in to manage the horizontal overflow and get a horizontal scroll on the content so the header could stay fixed. task-4768525
Quality checks created during receipt confirmation now use the company from the related stock move line instead of the currently active company. This prevents errors when users confirm Company B receipts while working from Company A, improving reliability for multi-company operations.
Original PR description
When creating quality checks per quantity, a multi-company error occurs if the active company differs from the one defined on the control point. Steps to reproduce: - Create a Quality Control Point for Company B and Product Table for the receipt operation with a per-quantity control. - Create a receipt in Company B for this product but leave it in draft. - Switch to Company A and try to confirm → error. Root cause: The company_id was not set when creating the quality check, causing it to default to `env.company` (A) instead of the stock move line’s company (B). opw-86993 Forward-Port-Of: odoo/enterprise#99076 Forward-Port-Of: odoo/enterprise#98655
This fixes a display issue in the Gantt view where the empty-state helper’s blur effect could appear over other page elements. Users should see cleaner screens when no Gantt content is available, without visual obstruction of nearby controls or components.
Original PR description
This commit resets the `position` and `top` attributes in `gantt_view.scss` causing the previously implemented opacity blur effect of the nocontent helper to wrongly appear on top of some components. task-5245728 Forward-Port-Of: odoo/enterprise#98997
The sitemap now only lists the Helpdesk page for websites where Helpdesk is actually enabled. This prevents visitors and search engines from seeing links to Helpdesk pages on websites that do not offer that service.
Original PR description
Steps to reproduce: 1) Create two websites(Website A, Website B) in one company 2) Configure domains in both websites, for example, http://localhost:8069 for Website A, http://127.0.0.1:8069 for Website B 3) In Helpdesk team settings, enable Website Form and select Website A as the website for the helpdesk 4) Now go to browser, and open http://127.0.0.1:8069/sitemap.xml Current Behaviour: Website B will show <loc>http://127.0.0.1:8069/helpdesk</loc> in sitemap even though Website B has no Helpdesk Team! Solution: This commit will add a sitemap method, that will only show the helpdesk in sitemap if it's enabled Forward-Port-Of: odoo/enterprise#96912
This fix updates an automated test so it runs under the same project user permissions expected in normal use. It prevents misleading test failures caused by administrator-level access, helping keep project budgeting quality checks reliable.
Original PR description
In commit [1], a new test was added, but it fails because the result of `template_values` does not match the expected outcome. The failure occurs at line [2], where the method `_get_profitability_values` is called with the project's environment. This environment includes the superuser, which causes the discrepancy in the result. This commit resolves the issue by calling the project (self.project_goats) with the user set to `self.user_projectuser`. [1]: https://github.com/odoo/enterprise/commit/29c6e1d648218219c718a0448fffb8b8444af5df [2]: https://github.com/odoo/odoo/blob/fad692777e90f3c91f91d2a91e706f8bdb64a08a/addons/project/models/project_update.py#L116 runbot-233851 Forward-Port-Of: odoo/enterprise#98897
31 changes
Resolved issues and error corrections
This change prevents the breadcrumb title from briefly changing to an incorrect label when users switch between livechat sessions. It improves the browsing experience by keeping the session name stable and accurate while navigating.
Original PR description
Before this PR, The breadcrumbs flickered when navigating between livechat sessions. This occurred because the `FormController`…
Before this PR,
The breadcrumbs flickered when navigating between livechat sessions.
This occurred because the `FormController` ([@web/views/form/form_controller](https://github.com/odoo/odoo/blob/saas-18.3/addons/mail/static/src/core/web/discuss_patch.js#L16-L23))
updated the breadcrumb title inside the `onRendered` hook and set it to
`this.model.root.data.display_name` which is `undefined`, the `Discuss` component
also updated the breadcrumb title in a `useEffect` hook. ([@mail/code/web/discuss_patch.js](https://github.com/odoo/odoo/blob/saas-18.3/addons/mail/static/src/core/web/discuss_patch.js#L16-L23))
The two updates conflicted: the onRendered hook first set the title to
“Unnamed,” and then the useEffect hook replaced it with the correct title,
causing a brief flicker. Additionally, when navigating to another session with
the same thread.displayName, the useEffect hook did not trigger (since its
dependency did not change), but onRendered still ran, causing the breadcrumb
to remain “Unnamed”.
This PR fixes the issue by introducing a `LivechatFormController` which
updates the breadcrumbs when channel is fetched in store.
task-4671251
Before:

After:

task-4671251
Forward-Port-Of: odoo/odoo#233167This change prevents the Helpdesk page from appearing in a website’s sitemap unless Helpdesk is actually enabled for that site. It avoids exposing links on websites that do not have a Helpdesk team configured, which keeps site maps accurate for visitors and search engines.
Original PR description
Steps to reproduce: 1) Create two websites(Website A, Website B) in one company 2) Configure domains in both websites, for example, http://localhost:8069 for Website A, http://127.0.0.1:8069 for Website B 3) In Helpdesk team settings, enable Website Form and select Website A as the website for the helpdesk 4) Now go to browser, and open http://127.0.0.1:8069/sitemap.xml Current Behaviour: Website B will show <loc>http://127.0.0.1:8069/helpdesk</loc> in sitemap even though Website B has no Helpdesk Team! Solution: This commit will add a sitemap method, that will only show the helpdesk in sitemap if it's enabled
This update corrects a DHL field name used for customer references, preventing shipment validation errors when sending export declarations. It also adjusts the planned shipping date/time format to match DHL’s required standard, so return labels and related shipping actions complete successfully.
Original PR description
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes…
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes validation errors when communicating with the DHL API. In addition, the datetime format used for the planned shipping date and time does not conform to the expected format specified by DHL. Steps to reproduce spelling issue: 1. Create a Sales Order with a customer reference and a deliverable product. 2. Validate the SO. 3. Go to the delivery, select DHL as carrier, and confirm. → Error: Validation error #/content/exportDeclaration: extraneous key [recepientReference] is not permitted. Steps to reproduce datetime issue: 1. Create a delivery using the DHL carrier. 2. Confirm the delivery. 3. Return the delivery. 4. Click "Print Return Label". → Error: Bad request #/plannedShippingDateAndTime is not well formatted (expected format: '2010-02-11T17:10:09 GMT+01:00'). Official DHL documentation: https://developer.dhl.com/sites/default/files/2025-11/dpdhl-express-api-3.1.1_swagger.yaml opw-5024363 Forward-Port-Of: odoo/enterprise#98981
This fix ensures pricelist rules entered on a product variant are properly saved after you click Save. It prevents users from losing pricing changes, improving reliability when managing product prices in Sales.
Original PR description
steps to reproduce: ------------------- 1. Install sales 2. Enable Product Variants and Pricelists under Sales > Configuration 3. Open a product variant and create a pricelist rule 4. Save it issue:…
steps to reproduce: ------------------- 1. Install sales 2. Enable Product Variants and Pricelists under Sales > Configuration 3. Open a product variant and create a pricelist rule 4. Save it issue: ----- The pricelist rules are not saved. cause: ------ The field `pricelist_rule_ids` on `product.product` is a non-stored One2many. https://github.com/odoo/odoo/blob/b1041951d436b4b6adc90d8b8dd7b8c88cc69a46/addons/product/models/product_product.py#L62-L68 In the ORM, such fields are handled in the else part of [write_real()](https://github.com/odoo/odoo/blob/b1041951d436b4b6adc90d8b8dd7b8c88cc69a46/odoo/orm/fields_relational.py#L1033-L1049), Since this field is non-stored, it has no corresponding column in the database to persist changes. As a result, any updates made to it are lost after saving. solution: --------- Add an inverse method to make the field writable. opw-5097909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229521
When creating a new employee, the system now pulls the work address from the active company instead of the current user’s company. This ensures employees created in a different company start with the right address automatically.
Original PR description
Steps to reproduce: - Open the Employee app. - Create a new employee in a company different from the current user's company. Issue: - The default address is taken from the current user's company instead of the active company's address. Fix: - Default address now uses the active company's address instead of the user's company. task-5138714 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230049
The invoice synchronization process was using the wrong company in some cases. This update ensures invoices are grouped by company and synced separately, reducing the risk of incorrect synchronization results.
Original PR description
The sync process previously used the wrong company when synchronizing invoices. This fix groups invoices by their respective companies and performs the sync for each company individually. task-5207338 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233148
This change prevents an error from appearing when someone uploads a non-PDF file in the Sign app while debug mode is enabled. Instead of a traceback, users now see a clear and friendly message explaining that the file type is not supported.
Original PR description
Version: - saas-18.3 Steps to reproduce: - Enable debug mode. - Try uploading a non-PDF file in the Sign app. Before: - Uploading a non-PDF file in debug mode caused a traceback error. - The TemplateAlertDialog component tried to use a message prop that wasn’t defined. After: - Replaced the use of the undefined message prop with the correct body prop to display the error message. Impact: - Fixes the traceback error in debug mode. - Shows a clear and user-friendly error message when uploading unsupported file types. task-4828439 Forward-Port-Of: odoo/enterprise#89081
This update makes Shiprocket work reliably when local GST tax labels are not available, preventing shipping-related errors in affected setups. It also corrects the test scenario so it uses a consistent tax rate, avoiding flaky test behavior.
Original PR description
Some other test adds a fiscal position with tax mapping. This creates 2 problems 1. The new taxes have a tag, which means we evaluate the right hand of…
Some other test adds a fiscal position with tax mapping. This creates 2 problems
1. The new taxes have a tag, which means we evaluate the right hand of
https://github.com/odoo/enterprise/blob/8d3fe30c627eada1186c15480876fb2e8f7ddb59/delivery_shiprocket/models/shiprocket_request.py#L239
However, since l10n_in is not installed,
`tax.env.ref(f"l10n_in.tax_tag_{gst}gst", False)`
does not return anything (False is not a fallback)
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/api.py#L588
So we end up looking for `None` in `tax_tag_ids`, which leads us to compare the `_name` properties, see
https://github.com/odoo/odoo/blob/1e96a3d127e8f521d3027f7110026ae84e11ed5e/odoo/models.py#L6545-L6558
2. The test added in 4d5df93 was assuming the default company 15% tax, which was not always true
Solution
-----
1. Provide a fallback for the `ref` lookup
2. Force a 15% tax in the test
-----
runbot-232692
Forward-Port-Of: odoo/enterprise#99027
Forward-Port-Of: odoo/enterprise#97998This change corrects a test that was failing when a project was added because it was using the wrong user context. By running the project with the expected project user instead of superuser access, the test now matches the intended business behavior.
Original PR description
In commit [1], a new test was added, but it fails because the result of `template_values` does not match the expected outcome. The failure occurs at line [2], where the method `_get_profitability_values` is called with the project's environment. This environment includes the superuser, which causes the discrepancy in the result. This commit resolves the issue by calling the project (self.project_goats) with the user set to `self.user_projectuser`. [1]: https://github.com/odoo/enterprise/commit/29c6e1d648218219c718a0448fffb8b8444af5df [2]: https://github.com/odoo/odoo/blob/fad692777e90f3c91f91d2a91e706f8bdb64a08a/addons/project/models/project_update.py#L116 runbot-233851
When a product with only one non-variant option was added to the cart from the website, it could create a new line every time instead of updating the existing one. This fix makes those products behave like standard single-variant items, so repeat additions are handled correctly and the cart stays accurate.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have a product attribute with variant creation set to never; 2. have product using only this attribute, with only a single value; 3. open website editor on…
Versions -------- - 18.0+ Steps ----- 1. Have a product attribute with variant creation set to never; 2. have product using only this attribute, with only a single value; 3. open website editor on /shop; 4. enable add-to-cart button & save; 5. use button on the aforementioned product at least twice. Issue ----- Each time the product gets added, a new line is created. Cause ----- Because there's only a single value, the product configurator doesn't pop up by default when adding the product to the cart. Without the configurator pop-up, the `_cart_update` method doesn't receive any `no_variant_attribute_value_ids`, which are used find a matching line if the product template has any `no_variant` attribute. Solution -------- Instead of checking `product.product_tmpl._has_no_variant_attributes()`, to see if we should attempt to match `no_variant_attribute_value_ids`, check if the added product has any `no_variant` attributes that have more than one value or are optional (multi-checkbox). If not, a `no_variant` product behaves the same as a single-variant product. opw-5093175 opw-5137351 Forward-Port-Of: odoo/odoo#234958 Forward-Port-Of: odoo/odoo#233452
This change fixes an error that could prevent users from saving an overtime rule when it is based on timing. The system now provides a default timing value, avoiding the crash and making rule setup work as expected.
Original PR description
This error occurs when no `timing_type` is set for the timing in the rule.
Steps to reproduce:
---
- Install `hr_attendance` module(without demo)
- Attendance > Configurations > Overtime Rulesets
- Create New Rule > Add an overtime rule in this ruleset with:
- Rule is based on: `Timing`
- Save & Close
- Now Save Rule
Traceback:
---
`KeyError: False`
At [1], this error occurs because the rule has no `timing_type` set, as no default value for field is defined.
[1]- https://github.com/odoo/odoo/blob/6e5146113adbdce3cbe317a7b3ef16be0a244b6a/addons/hr_attendance/models/hr_attendance_overtime_rule.py#L453
sentry-6986530016
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThe app creator in Studio now uses a border color that stands out against the background. This makes checkboxes and other boundary elements easier to see while building an app, improving usability and reducing confusion.
Original PR description
Before this commit : when creating an app using the studio, none of the borders were visible, including the checkboxes in the app creator, because the background color of the app creator and the border color were the same. After this commit: the border color for the app creator has been changed to make it visible. task-5138669
The Amazon order fulfillment data now includes the carrier code required by some countries. If the carrier cannot be identified, the system uses a safe fallback so Amazon can still process the shipment correctly.
Original PR description
The `POST_ORDER_FULFILLMENT_DATA` feed that is used to push order delivery info to Amazon should follow the `OrderFulfillment` schema (see https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderFulfillment.xsd), but it was missing the `CarrierCode` element, which is required in some countries. This commit adds the missing element to the payload, with the formatted carrier name as a value. If the carrier name cannot be matched, "Other" is used as a fallback to signal Amazon that they should rely on the `CarrierName` instead. Forward-Port-Of: odoo/enterprise#99026
This update corrects how the empty-state helper is displayed in the Gantt view. It prevents the helper’s faded overlay effect from appearing on top of other interface elements, improving readability and avoiding visual overlap issues.
Original PR description
This commit resets the `position` and `top` attributes in `gantt_view.scss` causing the previously implemented opacity blur effect of the nocontent helper to wrongly appear on top of some components. task-5245728
This update corrects how package-in-package handling is detected in barcode operations so the system keeps selecting the right package without changing the user experience. It also updates an automated test to match the revised order in which package lines are processed, helping prevent incorrect follow-up actions.
Original PR description
Some adaptations based on the community side: - Adapt the compute of `outermost_result_package_id` so nothing changes functionality-wise in barcode. - Adapt a test as the priority of move lines from 'Put in Pack' have changed. Task-5116567
This update fixes several issues around moving and splitting packed goods in stock operations. It makes pack actions more reliable, improves how package choices and labels are shown, and updates printed picking documents so warehouse users see the right package information.
Original PR description
Summary of the fixes for the Put/Pack in pack: - Avoid an error when trying to click on 'Move a Pack' on an unsaved picking. - Apply putaway rules at with multi-level packages, considering…
Summary of the fixes for the Put/Pack in pack: - Avoid an error when trying to click on 'Move a Pack' on an unsaved picking. - Apply putaway rules at with multi-level packages, considering higher-level packages first. - Consider higher-level packages when checking package routes. - Updates the picking operation pdf. - For pickings, no longer display the 'Packages' stat button if no package are set as destination. We keep it for batches however, as it's currently the only way to add entire packs into a batch. - Be more lenient with the 'Remove' button for packages in a picking. - Allow to select the right packages as destination in a picking. - Change priority of move line when using 'Put in Pack', always prioritizing `picked` lines. - Avoid `Unnamed` packages when creating a new package without a name from a list view. - Display the parent packages in the 'Pick from' auto-complete. For more detail about each fix, read the related commit. Task-5116567 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Quality checks created per quantity now keep the correct company instead of using the currently active one. This prevents errors in multi-company environments when confirming receipts that were created under a different company.
Original PR description
When creating quality checks per quantity, a multi-company error occurs if the active company differs from the one defined on the control point. Steps to reproduce: - Create a Quality Control Point for Company B and Product Table for the receipt operation with a per-quantity control. - Create a receipt in Company B for this product but leave it in draft. - Switch to Company A and try to confirm → error. Root cause: The company_id was not set when creating the quality check, causing it to default to `env.company` (A) instead of the stock move line’s company (B). opw-86993 Forward-Port-Of: odoo/enterprise#99076 Forward-Port-Of: odoo/enterprise#98655
This update adds a test to make sure channel mentions are preserved when a user edits a message using the ArrowUp shortcut in the composer. It helps prevent message edits from dropping important channel references, which keeps conversations accurate and easier to follow.
Original PR description
Follow-up of https://github.com/odoo/odoo/pull/229546 Add a test to verify that mentioned channels are correctly restored when editing a message using the ArrowUp shortcut in the composer.
This update prevents a crash that could happen when a user was redirected after their session had been refreshed. It ensures session data is saved while the needed request context is still available, so users are less likely to hit errors during normal navigation.
Original PR description
Steps to reproduce ------------------ Login to runbot, wait `odoo.http.SESSION_ROTATION_INTERVAL`s (3h) then access any page, then access any bundle using its id (not its `f'{name}-{id}') e.g.…
Steps to reproduce
------------------
Login to runbot, wait `odoo.http.SESSION_ROTATION_INTERVAL`s (3h) then access any page, then access any bundle using its id (not its `f'{name}-{id}') e.g. `/runbot/bundle/123`. Traceback: cannot use a closed cursor. It occurs when the system tries to save the session.
Traceback, explained
--------------------
1. The previous request session underwent a "soft rotation", its sid changed and it was marked "gc_previous_sessions".
2. The following request matches a route that is website & multilang, it is the case of the runbot bundle route.
3. The session was marked "gc_previous_sessions", it removes *now* the other sessions and removes the mark from the current one, this sets the current session dirty.
4. The request URL is not canonical, `_pre_dispatch` in `http_routing` abords with a redirection to `/runbot/bundle/18.0-123`.
5. The abortion (`werkzeug.exceptions.abort`) is an exception that bubbles up all the way up in the http stack, notably above `_serve_db` where `request.env.cr` is closed.
6. `odoo.http.root.__call__` ultimatelly processes the response received from `_pre_dispatch`: it calls `post_process` which call `_save_session` which sees that the current session is dirty: it attempts to save it.
7. Because there is a `session.uid`, we need to refresh the session token, for that we need an environment and a cursor.
8. Kaboom, the cursor was closed by `_serve_db`.
Problem
-------
When we set/delete items from the session, the changes are only saved in the session object in memory. The modified session is only written once, at the end of the request, if no error occured.
When we save the session, we gotta update the `session_token` value, this token is a SHA over the user's login information: active, email, password, ... and is verified upon loading the session in a future request. Should the user changes its password, a new token would be computed and all the sessions with the old token would become invalid. Should the user uses an old session, he would get redirected to /web/login.
Computing the `session_token` is mandatory when there's a `uid` inside the session, otherwise the session would be invalid. Computing it requires a valid cursor to fetch the user's active, email, password, ...
In our case, the (valid) response contained in `wekzeug.exception.abort` did bubble-up above `_serve_db`: `request.env.cr` is closed.
Solution
--------
Move the exception handling for `werkzeug.exceptions.abort` in both `_serve_nodb` and `_serve_db`. That it is in `_serve_db` makes it possible to call `_post_dispatch` with a cursor and environment that are still alive. This fixes the problem at hand.
With the above fix, comes two sanity things:
The `if session.uid and env` conditional is wrong, it must be only `if session.uid`. When there is a uid stored in the session, updating the `session_token` is mandatory. It MUST crash if `save()` is called for a session with a uid but with no environment.
The `_serve_db` method manages both the request's cursor and the `request.env` attribute. Everytime the cursor is updated (e.g. when changing from a read-only to a read+write one)This change reduces unnecessary database overhead when recalculating salary simulations for job offers. By using one database savepoint for the whole calculation instead of one per offer, it improves performance and responsiveness.
Original PR description
Savepoints are used in multiple computes related to salary simulation for an offer, because it creates and updates existing records, but those should not be committed to the database. Those are currently made for each offer that needs to be recomputed. Frequent savepoint, without commit/rollback of the whole transaction, are a performance issue at the database level. To partially alleviate this issue, this commit creates 1 savepoint for the whole compute, instead of per record to compute.
This update adjusts Odoo’s mail server handling so it works correctly on newer Debian releases and with updated Python SSL libraries. It helps prevent warning messages and connection issues when sending mail in those environments.
Original PR description
Forward-Port-Of: odoo/odoo#234020 Forward-Port-Of: odoo/odoo#232699
This update prevents a crash that could happen when multiple default records matched the same setting. The system now picks a single matching record, so users can save defaults reliably even if duplicate entries exist.
Original PR description
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found,…
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found, accessing `default.json_value` raises a singleton error.
This fix makes sure the search only picks one record, avoiding that crash.
Before fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(9,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
Traceback (most recent call last):
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5630, in ensure_one
_id, = self._ids
^^^^
ValueError: too many values to unpack (expected 1)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/odoo/odoo/odoo/odoo/addons/base/models/ir_default.py", line 107, in set
if default.json_value != json_value:
^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/odoo/odoo/orm/fields.py", line 1670, in __get__
record.ensure_one()
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5633, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: ir.default(4, 9)
```
After fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(10,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
True
```
opw-5228419
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#234944
Forward-Port-Of: odoo/odoo#234893Branch companies can now see and use payment providers set up for their parent company when customers pay online. This fixes a problem that previously blocked checkout with a “No compatible payment providers found” message.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have a published payment provider; 2. create a branch company; 3. create a sales order in branch company; 4. enable online payment for sales order; 5. open sales order in portal view; 6. attempt to pay. Issue ----- No compatible payment providers found. Cause ----- The `payment.provider._check_company_domain` is set to the default exact match, so when it's used in `_get_compatible_payment_providers`, it's unable to find any providers for the branch company. Solution -------- Set `_check_company_domain` to `check_company_domain_parent_of`. opw-5214269 Forward-Port-Of: odoo/odoo#234821 Forward-Port-Of: odoo/odoo#234763
This update prevents a website access error when a product variant has a ribbon assigned. It ensures visitors can view product pages normally, avoiding a broken shopping experience for public users.
Original PR description
### Issue: An access error is shown on the website if ribbon is added to a product variant. #### To reproduce: 1- Create a db with `website_sale` installed. 2- Activate product variant. 3- Create a product variant and publish it. 4- Add a ribbon to the variant. 5- Using public user, navigate to the website product page. #### Cause: This is caused due to not having proper access rights. On stable we can use both the csv modification and adding sudo env to have an easier view update without need to upgrade the module. In master, we can keep the fix only in the csv file. opw-5224552
The Discuss command palette now uses smaller avatars on desktop so it matches the rest of the Discuss interface. This makes the list look more consistent and allows more results to be visible at once, while keeping the larger mobile layout unchanged.
Original PR description
Discuss command avatar were much bigger than rest of discuss UI, such as discuss sidebar. Discuss sidebar avatar size was reduced in 19.0, but discuss command palette still had big size like before this change. This commit fixes the issue with reduced size. To compensate with reduced size, more items are shown at once. This change only applies to desktop: in mobile the avatar need to be bigger, so this commit doesn't affect small UI. Part of Task-5227387 Before <img width="1280" height="946" alt="Screenshot 2025-11-10 at 12 59 56" src="https://github.com/user-attachments/assets/532c7d7f-a381-43f4-8a65-b0e3db7d6809" /> After <img width="1281" height="946" alt="Screenshot 2025-11-10 at 12 59 43" src="https://github.com/user-attachments/assets/9e018c92-a862-4aee-a2ad-dadd880b21f3" />
This change updates a manufacturing accounting test so it matches the latest way production duration is calculated. It ensures the test reflects the current logic and prevents false failures in automated checks.
Original PR description
### Issue: This is caused by changing the duration inverse in #233777. ### Cause: Before #233777, in duration inverse, only sum of `time_ids` was taken into account to calculate the `duration`. After that PR, `time_ids` with `get_working_duration` are also taken into account which cause this test fail. runbot-233742 Forward-Port-Of: odoo/odoo#234305
This change adds a regression test to make sure work entry generation still succeeds when an employee has overlapping leave periods, such as sick leave and a public holiday. It helps prevent a specific runtime error for fully flexible employees using attendance-based work entries, improving reliability in payroll-related processing.
Original PR description
**Purpose:** Add regression test to verify that overlapping leave scenarios (sick leave + public holiday) do not cause singleton errors for fully flexible employees using attendance-based work entries. **Test Coverage:** - Fully flexible employee with no calendar assignment - Attendance-based work entry source configuration - Overlapping sick leave and public holiday scenario - Work entry generation and validation without singleton errors Related : [PR](https://github.com/odoo/odoo/pull/223448) opw-4979974 Forward-Port-Of: odoo/enterprise#96664 Forward-Port-Of: odoo/enterprise#93902
This change prevents payroll from failing when an employee with fully flexible working hours has overlapping leave records, such as sick leave and a public holiday. It makes work entry processing more reliable and avoids blocking payroll runs for affected employees.
Original PR description
**Issue:** Multiple errors occur when processing payroll for "Fully Flexible" employees and overlapping leave scenarios: 1. ValueError "Expected singleton: hr.work.entry.type(7, 8)" during work entry…
**Issue:** Multiple errors occur when processing payroll for "Fully Flexible" employees and overlapping leave scenarios: 1. ValueError "Expected singleton: hr.work.entry.type(7, 8)" during work entry generation when sick leave overlaps with public holiday **Steps to Reproduce:** 1. Go to the **Employees** app and create a new employee. * Set the working hours to **empty (fully flexible)**. 2. Go to **Contracts** and create a new contract. * Set the **Work Entry Source** to *Attendance*. * Save and make the contract **Running**. 3. Go to **Time Off** → **New**, and create a sick time off for the employee. * Example: from **25th to 29th**. * Approve the time off. 4. Go to **Configuration** → **Public Holidays**, and create a new public holiday. * Example: **27th**, which overlaps with the sick time off. * Work Entry Type = **Paid Time Off**. 5. Go to **Payroll** → **Work Entries**. * A **traceback** occurs. **Root Causes:** - In `_get_interval_leave_work_entry_type()`: Direct access to `interval[2].work_entry_type_id.code` causes singleton violation when overlapping leaves create intervals containing multiple work entry types. **Fix:** - Replace direct access to `interval[2].work_entry_type_id.code` with safe recordset slicing `interval[2].work_entry_type_id[:1].code` to prevent singleton violation when interval contains multiple work entry types This resolves payroll blocking issue for deployments using the Fully Flexible employee feature, where employees may have overlapping leave types and no assigned working calendar. Test : [PR](https://github.com/odoo/enterprise/pull/93902) opw-4979974 Forward-Port-Of: odoo/odoo#230659 Forward-Port-Of: odoo/odoo#223448
When users click a channel from the Kanban view in Discuss, the channel now opens in the form view as expected. This makes it easier to review and manage channel details without extra steps.
Original PR description
**Steps to reproduce:** Open 'Discuss' Click on 'Channel' in the menu to display channels in kanban view Click on any channel **Cause**: The action 'mail.discuss_channel_action' did not include form view in view_mode. **Effect**: Clicking on a kanban card does not display the form view. **Fix**: Open the form view of a channel when clicking on a kanban card. Task-5076555 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227668
This change prevents the employee version timeline from trying to use payroll-related data when a user does not have access to it. As a result, HR users can open employee forms reliably, and the timeline simply omits the extra contract grouping line when the needed information is unavailable.
Original PR description
Before this commit, the version timeline component needs to read contract_type_id and contract dates fields to be able to add an extra line below the versions to mention the versions inside the same contract. The problem is `contract_type_id` and the contract dates fields are not available when the user cannot see the payroll tab in the employee form. This commit makes sure the fields needed to display the extra line inside the version timeline are only used if the user has access to them otherwise no extra line will be displayed since some information is missing to be able to display it. task-5253864 X-original-commit: 0b1d4b006908b1ad993177f024d65a484d477078
This update fixes when Avatax-related fields and address validation appear on customer and product screens. It ensures the system reads fiscal country codes correctly, so users see the right options at the right time and Avatax data is handled more reliably.
Original PR description
**Changes:** - Updated the logic for showing address validation in `res_partner.py` to handle fiscal country codes more robustly. - Modified visibility conditions for `is_avatax`, `avatax_category_id`, `avatax_unique_code`, `avalara_partner_code`, and `avalara_exemption_id` fields in XML views to correctly parse and check fiscal country codes. **Purpose:** These changes ensure that the application correctly identifies when to display certain fields based on the fiscal country codes, enhancing the accuracy of the Avatax integration. This is made necessary because of changes to the _compute_fiscal_country_codes method introduced in commit https://github.com/odoo/odoo/commit/c518589716ebde6fb418d907ee01799dd7b889e9.
11 changes
Resolved issues and error corrections
This update fixes two issues that could prevent DHL shipments from being created successfully. It corrects a misspelled field name and adjusts the date/time format to match DHL's requirements, reducing failed shipping and return label requests.
Original PR description
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes…
Currently, when creating a DHL shipment with an export declaration that includes a customer reference, there is a misspelling of the field 'recipientReference' as 'recepientReference'. This causes validation errors when communicating with the DHL API. In addition, the datetime format used for the planned shipping date and time does not conform to the expected format specified by DHL. Steps to reproduce spelling issue: 1. Create a Sales Order with a customer reference and a deliverable product. 2. Validate the SO. 3. Go to the delivery, select DHL as carrier, and confirm. → Error: Validation error #/content/exportDeclaration: extraneous key [recepientReference] is not permitted. Steps to reproduce datetime issue: 1. Create a delivery using the DHL carrier. 2. Confirm the delivery. 3. Return the delivery. 4. Click "Print Return Label". → Error: Bad request #/plannedShippingDateAndTime is not well formatted (expected format: '2010-02-11T17:10:09 GMT+01:00'). Official DHL documentation: https://developer.dhl.com/sites/default/files/2025-11/dpdhl-express-api-3.1.1_swagger.yaml opw-5024363 Forward-Port-Of: odoo/enterprise#98981
This change fixes a problem where setting a default value could fail if duplicate default records already existed in the system. The update makes the lookup select only one matching record, so users can save defaults reliably without encountering an error.
Original PR description
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found,…
There’s no constraint preventing duplicate `ir.default` records. When setting a default using `self.env['ir.default'].set()`, it searches for an existing one, but if more than one match is found, accessing `default.json_value` raises a singleton error.
This fix makes sure the search only picks one record, avoiding that crash.
Before fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(9,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
Traceback (most recent call last):
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5630, in ensure_one
_id, = self._ids
^^^^
ValueError: too many values to unpack (expected 1)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/odoo/odoo/odoo/odoo/addons/base/models/ir_default.py", line 107, in set
if default.json_value != json_value:
^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/odoo/odoo/orm/fields.py", line 1670, in __get__
record.ensure_one()
File "/home/odoo/odoo/odoo/odoo/orm/models.py", line 5633, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: ir.default(4, 9)
```
After fix:
```py
self: res.users(1,)
>>> company = self.company_id
>>> company
res.company(1,)
>>> self.env['ir.default'].create({'field_id': 4540, 'company_id': company.id, 'json_value': 7})
ir.default(10,)
>>> self.env['ir.default'].set('res.partner', 'property_account_receivable_id', 7, company_id=company.id)
True
```
opw-5228419
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#234893This update fixes a spelling mistake in the Website Sale module, changing an incorrect word to the intended one. It improves the clarity and professionalism of the customer-facing text without affecting how the feature works.
Original PR description
Description of the issue/feature this PR addresses: This PR fixes a typo that was found in website_sale module. There is a mistake in writing "you" --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Amazon delivery update now includes the carrier code expected by Amazon in the shipment data. This helps prevent shipment updates from failing in countries where that field is required, improving order tracking reliability.
Original PR description
The `POST_ORDER_FULFILLMENT_DATA` feed that is used to push order delivery info to Amazon should follow the `OrderFulfillment` schema (see https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderFulfillment.xsd), but it was missing the `CarrierCode` element, which is required in some countries. This commit adds the missing element to the payload, with the formatted carrier name as a value. If the carrier name cannot be matched, "Other" is used as a fallback to signal Amazon that they should rely on the `CarrierName` instead. Forward-Port-Of: odoo/enterprise#99026
This update adds automated tests for a sales margin scenario to make sure purchase price is recalculated correctly when a canceled order is reset, then the pricelist currency is changed. It helps prevent pricing errors for products with automated costing methods and improves confidence in future changes.
Original PR description
Description of the issue/feature this PR addresses: Test-only PR to verify `purchase_price` recomputation behavior when changing pricelist currency after order cancellation (per reviewer feedback on https://github.com/odoo/odoo/pull/232553). Current behavior before PR: No test coverage for this scenario. Desired behavior after PR is merged: Test validates correct currency conversion of `purchase_price` for AVCO/FIFO products after cancel → draft → pricelist change workflow. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures the purchase price on sales order lines is recalculated correctly when a cancelled order is returned to quotation and the pricelist currency is changed. It prevents outdated cost values from being kept, which helps maintain accurate margin calculations and reporting.
Original PR description
**Description of the issue/feature this PR addresses:** Issue: The purchase_price field in sale order lines is not recomputed when changing the pricelist to a different currency after a sales order…
**Description of the issue/feature this PR addresses:** Issue: The purchase_price field in sale order lines is not recomputed when changing the pricelist to a different currency after a sales order has been confirmed, cancelled, and set back to quotation state. This causes incorrect cost calculations and margin reporting when users need to modify the currency/pricelist of a previously confirmed order that was later cancelled and reset to draft. Affected modules: sale_stock_margin Versions affected: 16.0, 17.0, 18.0 (confirmed on 18.0) **Current behavior before PR:** When a sales order goes through the following workflow: Create a sales order with a pricelist in USD Add a product line (e.g., purchase_price shows $100.00 USD) Confirm the order (stock moves are created) Cancel the order (stock moves are set to state 'cancel' but remain in move_ids) Set the order back to quotation state Change the pricelist to one with a different currency (e.g., EUR) Result: The purchase_price remains in the original currency (USD) instead of being converted to the new currency (EUR). Root cause: The _compute_purchase_price() method in sale_stock_margin checks if move_ids exist to determine whether to use stock-based costing or fall back to the standard price from sale_margin. However, cancelled moves are still present in move_ids, causing the method to skip the currency conversion that should happen when no valid (non-cancelled) moves exist. **Desired behavior after PR is merged:** After following the same workflow: Create a sales order with a pricelist in USD Add a product line (purchase_price shows $100.00 USD) Confirm the order Cancel the order Set the order back to quotation state Change the pricelist to EUR Expected result: The purchase_price is automatically recomputed and converted to the new currency (e.g., shows €92.00 EUR based on the exchange rate). How it works: The method now filters out cancelled stock moves before checking if valued moves exist. If only cancelled moves are present, the computation is delegated to the parent sale_margin module, which properly handles currency conversion using _convert_to_sol_currency(). Video Demostration From runbot of today (10/21/2025) https://drive.google.com/file/d/1KExSzOYHAmMc10b3u_Xy5B1nWkkYOBqy/view --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When a user deletes a rating message in the portal or related pages, the rating summary now updates right away. This keeps the displayed ratings accurate and avoids showing outdated information after a message is removed.
Original PR description
*: portal, portal_rating, website_slides PR #221050, makes it possible to properly remove a message in the portal and PR #216044 retrieves the rating cards feature. There is an overlap between what these two PRs do. When a user removes a rating message and there is a rating cards feature on the page, it should be updated. Most of the remove method changes are indeed what we did in forward port of #221050 (#222517). task-5106543
When a candidate’s name is changed, any existing follow-up activities now automatically reflect the updated name. This keeps records consistent and avoids confusion for recruiters viewing older tasks.
Original PR description
Issue: When updating an hr recruitement candidate name (stored in hr_applicant after 18.2) the name change is not updated in the name of previously created activities. Cause: The field res_name in mail.activity is computed and stored only at creation of an activity. Solution: Retrigger the compute of an activity when updating a candidates name. Task-4988342
This update adjusts an automated purchase test so it works correctly with PostgreSQL 18. It keeps the test focused on the real business behavior while avoiding a database-specific error name change that caused unnecessary test failures.
Original PR description
Apparently in pg18 a standard-compliance
fix (postgres/postgres@086c84b23d99c2ad268f97508cd840efc1fdfd79) has led to `RESTRICT_VIOLATION` being emitted in cases which formerly emitted `FOREIGN_KEY_VIOLATION`. One such case is specifically being tested for by `test_purchase_order_line_without_uom`, leading to this test failing systematically when running pg18:
psycopg2.errors.RestrictViolation: update or delete on table "uom_uom" violates RESTRICT setting of foreign key constraint "purchase_order_line_product_uom_id_fkey" on table "purchase_order_line"
DETAIL: Key (id)=(29) is referenced from table "purchase_order_line".
Update the test to use the more generic `IntegrityError` as it's probably more than sufficient for our purposes. Technically we could pass a tuple of `(ForeignKeyViolation, RestrictViolation)` but it doesn't really seem necessary. And it would require fixing the `_raisesContext` override as currently it is very much *not* compatible with that.This fix makes drag-and-drop work more reliably on touch devices in the Documents app. It helps users move files or items on mobile devices, where the browser was previously losing the needed drag information before the drop action completed.
Original PR description
For now, touch devices do not work with native drag and drop in browsers. When a datatransfer is set on a dragstart event, it is lost before reaching the drop event, but only when using a touch device. Unfortunately, I still haven't found any sources that clearly explain whether this is a known bug or a limitation. The fact that on mobile (really mobile, not devtools, you need a touch device) drag fails on Chrome but succeeds on Firefox. To fix this issue, this commit manages datatransfers in an external variable, without using the method in the Event. I keep the original behavior as default, I just add a fallback to my global datatransfer variable. opw-5139435
This change makes interval calculations consistently normalize their data before combining results. It helps prevent incorrect overlaps and errors when different interval types are used together, especially in planning-related operations.
Original PR description
## The issue Prior to this commit, the `other` parameter in the `_merge` method could belong to a different class, not necessarily an instance of `Intervals`.…
## The issue Prior to this commit, the `other` parameter in the `_merge` method could belong to a different class, not necessarily an instance of `Intervals`. https://github.com/odoo/odoo/blob/8c737601327acec1d83e1e5e3c6e66c9fd226339/addons/resource/models/utils.py#L158-L165 The comment indicates that normalization should be enforced; however, there is no corresponding reference to it within the `_boundaries` method. https://github.com/odoo/odoo/blob/8c737601327acec1d83e1e5e3c6e66c9fd226339/addons/resource/models/utils.py#L48-L53 That normalization just happens in the `__init__`. https://github.com/odoo/odoo/blob/8c737601327acec1d83e1e5e3c6e66c9fd226339/addons/resource/models/utils.py#L117-L132 ## Example For example, in Planning module, we perform operations between `Intervals` and `WorkIntervals`. The `WorkIntervals` class behaves differently from `Intervals`: while `Intervals` uses disjoint closed intervals, `WorkIntervals` uses disjoint semi-closed intervals. ## Side effects During these operations, the `_merge` method was not normalizing the `_items`, which caused inconsistencies and errors (when we are merging two unormalized intervals `([0, 10], [10, 20])` with an empty `others`). ## The fix This commit ensures that the `other` parameter is normalized before processing the `_merge` operation. The fix ensures that normalized intervals are always produced after `_merge`, even when unnormalized intervals are provided as input. ## Real case That issue has been found in that ticket: 5184291 Forward-Port-Of: odoo/odoo#234352
6 changes
Resolved issues and error corrections
When users upload an image in the Website Editor for the first time, Odoo now avoids creating duplicate attachments for the same file. This reduces unnecessary storage use and keeps page media cleaner, while still applying image optimization such as resizing and web format conversion.
Original PR description
This PR aims to prevent the creation of duplicate image attachments when uploading an image for the first time in Website Editor. --- ### Steps to Reproduce 1. Open Website → Edit mode. 2. Drag and drop any snippet that contains an image (e.g., cover, banner, image block). 3. Upload an image using the image upload option. 4. Check the attachments. → You will notice multiple attachments of the same image being created(by odooBot). --- ### Impact * Prevents unnecessary saves and duplicate attachments. task-4812410
Payments now correctly generate their journal items even when the journal lines field is added to the form with Studio. This prevents draft payments from being saved without the accounting entries they need, while still preserving any custom journal lines users provide.
Original PR description
**Steps to reproduce:** 1. Install the Accounting and Studio modules. 2. Create a payment in draft state. 3. Add the `line_ids` field to the payment form view using Studio. 4. Save the payment. **Observed behavior:** * A journal entry was created, but its journal items (`line_ids`) were not computed. * The payment stayed in draft with empty journal items. * The normal flow (without the field added) worked correctly. **Cause:** * The create method only checked whether `line_ids` was missing from `vals`. When Studio adds the field to the form, it appears in `vals` even when empty. As a result, the condition failed and journal items were not generated. **Fix:** * Check both if `line_ids` is missing and if it is empty. * Always compute journal items when none are explicitly provided. * Keep existing behavior for custom journal item creation. opw-5030072
The upload button in the accounting dashboard can no longer be dragged around by mistake. This keeps the interface stable and avoids confusing shifts in the upload area while users work.
Original PR description
Issue: - In the dashboard, the upload button (purchase journal and others) could be dragged. - This caused unintended movement of the upload UI element. Fix: - Added `draggable=false` to the upload button element. - Ensures the button remains fixed and cannot be dragged around. TaskID-5114617
This change corrects how time intervals are combined so they are always cleaned up before being processed. It prevents inconsistent results and errors when different interval types are used together, improving reliability in planning-related operations.
Original PR description
## The issue Prior to this commit, the `other` parameter in the `_merge` method could belong to a different class, not necessarily an instance of `Intervals`.…
## The issue Prior to this commit, the `other` parameter in the `_merge` method could belong to a different class, not necessarily an instance of `Intervals`. https://github.com/odoo/odoo/blob/8c737601327acec1d83e1e5e3c6e66c9fd226339/addons/resource/models/utils.py#L158-L165 The comment indicates that normalization should be enforced; however, there is no corresponding reference to it within the `_boundaries` method. https://github.com/odoo/odoo/blob/8c737601327acec1d83e1e5e3c6e66c9fd226339/addons/resource/models/utils.py#L48-L53 That normalization just happens in the `__init__`. https://github.com/odoo/odoo/blob/8c737601327acec1d83e1e5e3c6e66c9fd226339/addons/resource/models/utils.py#L117-L132 ## Example For example, in Planning module, we perform operations between `Intervals` and `WorkIntervals`. The `WorkIntervals` class behaves differently from `Intervals`: while `Intervals` uses disjoint closed intervals, `WorkIntervals` uses disjoint semi-closed intervals. ## Side effects During these operations, the `_merge` method was not normalizing the `_items`, which caused inconsistencies and errors (when we are merging two unormalized intervals `([0, 10], [10, 20])` with an empty `others`). ## The fix This commit ensures that the `other` parameter is normalized before processing the `_merge` operation. The fix ensures that normalized intervals are always produced after `_merge`, even when unnormalized intervals are provided as input. ## Real case That issue has been found in that ticket: 5184291
Sales order line costs now keep updating correctly even after an order was confirmed, canceled, and then reset to draft. This prevents outdated margin and pricing information from appearing when users revise quotations.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have a product with a purchase cost; 2. have sale margins enabled; 3. add a the product to a quotation; 4. change pricelist to one with a different currency; 5. note that the line's cost gets updated; 6. change order state to confirmed, then canceled, then back to draft; 7. change pricelist again. Issue ----- The purchase cost no longer update. Cause ----- The `_compute_purchase_price` override in `sale_stock_margin` doesn't pass the line to `super` if it `has_valued_move_ids`. This hook only checks for the existence of linked `move_ids` on the record with no regard for their state. Solution -------- 1. Move the `has_valued_move_ids` hook from `sale` to `sale_stock`. 2. Only return `True` if any of the moves aren't in draft or canceled. opw-5147321
Mobile visitors using live chat will no longer see the message field auto-zoom when they tap to type. This keeps the send button visible and makes the chat experience smoother on phones and tablets.
Original PR description
Before this commit, when using livechat for visitors on mobile devices, click on input would zoom on input of about 115%. This zoom would hide send button at the very end of composer input, and would…
Before this commit, when using livechat for visitors on mobile devices, click on input would zoom on input of about 115%. This zoom would hide send button at the very end of composer input, and would force users to pinch-to-unzoom, making the UX quite poor. This problem happens because mobile devices have an auto-zoom feature that is triggered when font-size is below 16px. The discuss UI is designed with 14px font size (web client font size), and since 14px < 16px, it zooms on input focus to about 115%. This commit fixes the issue by using a font-size of 16px specifically for livechat visitor on mobile devices, so that this doesn't auto-zoom. Note that this problem doesn't happen on the web client even though this uses a font-size of 14px because it specifically disable the autozoom feature: https://github.com/odoo/odoo/blob/17.0/addons/web/views/webclient_templates.xml#L250 This solution is not practical for livechat, for which it has to work on any external website. opw-5229076 Before <img width="199" height="431" alt="after" src="https://github.com/user-attachments/assets/cc2f8e04-bde7-4eeb-84d5-b2efa2763490" /> After <img width="199" height="431" alt="before" src="https://github.com/user-attachments/assets/6c6679fc-9c16-40e7-ab6f-21540d20d59d" />