Wednesday, November 19, 2025
49 changes · 19.0
Enhancements to existing features
The mail plugin can now detect which Odoo version is in use. This lets it display a clear message when the version is not supported, helping users understand why the add-in may not work.
Original PR description
Purpose ======= The new addin has been refactored and doesn't work with older Odoo version, and so we add an endpoint to be able to show a message if we don't support that Odoo version. Task-4727609 Forward-Port-Of: odoo/odoo#236286 Forward-Port-Of: odoo/odoo#236047
The Point of Sale sales report now includes a clearer breakdown of payments by method, making it easier to see how customers paid. This helps businesses review sales patterns and reconcile reports more quickly.
Original PR description
In this commit: ----------- - Enhances the PoS sales report by adding detailed breakdowns of payments grouped by payment method. task-5184319 Forward-Port-Of: odoo/odoo#234486
Resolved issues and error corrections
The message action menu now reliably shows “Copy to Clipboard” for regular conversations, even when the AI module is installed. This fixes a missing option that could prevent users from copying message text in chat and discuss views.
Original PR description
Before this commit, "Copy to Clipboard" was sometimes not visible in the message action list when message had some text content. This happens because message actions can condition overridden by some…
Before this commit, "Copy to Clipboard" was sometimes not visible in the message action list when message had some text content. This happens because message actions can condition overridden by some other modules, and the way overrides of action condition work is to have boolean value taking precedence over the local condition of action. This architecture is meant to provide exhaustive list of actions to allow, which is quite useful to control what livechat visitors can have. However this architecture requires overrides to properly return `undefined` when the local condition should apply, which was not the case for an override by `ai` module. So when `ai` module is installed, the "copy to clipboard" feature as not available. This commit fixes the issue by adapting the condition in `ai` module to return `undefined` on non-AI conversations, and add test coverage for both `@mail` discuss suite and all overrides of discuss in `@test_discuss_full_enterprise`. opw-5240768 https://github.com/odoo/enterprise/pull/99794
This update changes how Odoo finds Peppol service providers so it stays compatible with upcoming DNS changes. It helps avoid failed lookups and keeps electronic document exchange working reliably as the old method is phased out.
Original PR description
From November 1st, CNAME DNS will be deprecated for Peppol lookups. From February 1st CNAME lookups will no longer be supported. The replacement are NAPTR DNS records. Multiple solutions were available, such as using DoH (e.g. with cloudflare DNS), but we ended up choosing to proxy DNS requests through IAP to centralize the lookups and make such specs upgrades easier to handle in the future. IAP is now responsible of doing the DNS lookup and fetching the service groups of the found SMP. IAP-side: https://github.com/odoo/iap-apps/pull/1227 task-5179969 Forward-Port-Of: odoo/odoo#233766 Forward-Port-Of: odoo/odoo#232483
The Copy to Clipboard action now appears correctly again for regular conversations, even when the AI module is installed. This fixes a missing option in the message menu and improves consistency for users and support teams.
Original PR description
Before this commit, "Copy to Clipboard" was sometimes not visible in the message action list when message had some text content. This happens because message actions can condition overridden by some…
Before this commit, "Copy to Clipboard" was sometimes not visible in the message action list when message had some text content. This happens because message actions can condition overridden by some other modules, and the way overrides of action condition work is to have boolean value taking precedence over the local condition of action. This architecture is meant to provide exhaustive list of actions to allow, which is quite useful to control what livechat visitors can have. However this architecture requires overrides to properly return `undefined` when the local condition should apply, which was not the case for an override by `ai` module. So when `ai` module is installed, the "copy to clipboard" feature as not available. This commit fixes the issue by adapting the condition in `ai` module to return `undefined` on non-AI conversations, and add test coverage for both `@mail` discuss suite and all overrides of discuss in `@test_discuss_full_enterprise`. opw-5240768 https://github.com/odoo/odoo/pull/236295
Odoo now adds a timestamp suffix to Flutterwave payment references so each transaction sent to the provider stays unique. This prevents duplicate reference issues when databases are reset during testing or in similar edge cases, improving payment reliability.
Original PR description
The `/payments` endpoint of the Flutterwave v3.0.0 API expects unique `tx_ref` parameters (matching Odoo's payment transaction `reference` field) to be passed. This is guaranteed by a UNIQUE() SQL constraint in Odoo, but testing sometimes involves dropping the database, leading to transaction references being repeated at the provider level for a given merchant account. This commit singularizes all transaction references by suffixing them with the current timestamp, ensuring that the `tx_ref` API parameter remains unique across transaction reference sequences. Forward-Port-Of: odoo/odoo#235799
Users can now export records even when the list is grouped by a property field. This fixes a crash that happened during export, improving reliability for grouped views and avoiding interruption of normal work.
Original PR description
Step to reproduce
- open a task
- add a property field , say test
- add values for this field in few records
- go to list view and group by test
- select a record from result and export it (from Action btn)
Observation:
- traceback
```
File "/home/odoo/17.0/addons/web/controllers/export.py", line 486, in base
groupby_type = [Model._fields[x.split(':')[0]].type for x in groupby]
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
KeyError: 'task_properties.b60ee9baefee14a8'
```
Cause:
- The issue is caused by splitting, which didn't considered property field
- it tried to look for `task_properties.b60ee9baefee14a8` in _fields which causes KeyError
FIx:
- split the field name properly to bring out actual field name while considering granularity as well as the property fields
opw-5159155
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#235979
Forward-Port-Of: odoo/odoo#235209Vendor batch payments now use the correct numbering sequence when they are created and validated. This prevents vendor batches from being labeled with the wrong type of sequence, which could cause confusion in accounting records.
Original PR description
Currently when creating a vendor batch payment, the system may incorrectly use the inbound batch payment sequence to generate the batch name Steps to reproduce: - Create a Vendor payment. - Create a Vendor batch payment, add the payment, validate it. Issue: Name has been set using the incoming batch payment sequence This occurs because `batch_type` is set to readonly when a payment is added to the list. As result, the current batch type is never sent to the backend that will use the default 'inbound'. opw-5128426 Forward-Port-Of: odoo/enterprise#99570
This update corrects how returned subcontracted products are routed so they go back to the appropriate location instead of all being sent to the subcontracting area. It prevents the system from accidentally changing delivery locations during the return process, which helps avoid stock errors and makes returns more reliable.
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#234850 Forward-Port-Of: odoo/odoo#234521
Fixed an issue where the “Update extra prices” action could disappear too early after a form save, even when not all variant prices had been synchronized. This helps ensure all affected product variants can be updated consistently before being used in sales orders.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Have a product with multiple variants; 2. go to one of its attributes; 3. in the form, change the default extra price on multiple lines; 4. click on "Update…
Versions -------- - 18.0+ Steps ----- 1. Have a product with multiple variants; 2. go to one of its attributes; 3. in the form, change the default extra price on multiple lines; 4. click on "Update extra prices"; 5. add the updated variants to a sale order. Issue ----- Only the line on which "Update extra prices" was clicked has been updated, even though the button disappeared on all lines after clicking it. Cause ----- The `_compute_default_extra_price_changed` method only compares the `default_extra_price` of the current record to its `_origin` value. Consequently, after saving the form, it will return `False`, even though only one attribute has been updated. Solution -------- Aside from checking whether the value changed on the form, also check whether any product template attribute value has a `price_extra` that's different from the product attribute value's `default_extra_price`. This way, clicking on "Update extra prices" once won't make the other update buttons disappear. opw-5240236 Forward-Port-Of: odoo/odoo#235088
This update ensures payment references keep the intended prefix when generating a unique reference. It helps avoid confusion and reduces the risk of duplicate-looking transaction names for payments processed through Paymob.
Original PR description
Forward-Port-Of: odoo/odoo#236015
The Activities menu now keeps pagination working even when some activities are filtered out by access rules. This prevents users from getting stuck on the first page and makes it possible to browse all activities they are allowed to see.
Original PR description
**Steps to reproduce:** - Create some activities which should not be accessible to a specific user (according to the `_search` filtering of `mail.activity`) - Go to Activity Menu > View all…
**Steps to reproduce:** - Create some activities which should not be accessible to a specific user (according to the `_search` filtering of `mail.activity`) - Go to Activity Menu > View all activities as the given user - Ensure that the limit (default: 80) is lower than the total number of activities which should be returned and that the new activities are in the returned elements - On `web_search_read` some records are removed by the `_search` override - The pagination navigation buttons are disabled as the returned number of records is lower than the limit - This means that some activities are not accessible to the user (everything above the given limit) **Issue:** The issue comes from the `_search` override which checks the records available to the user. As it's done after fetching with the limit, the resulting number of records can be lower than expected and this breaks the `_format_web_search_read_results` which considers that we have all the possible records and doesn't try to fetch the total count of records. **Fix:** The main issue can't be directly fixed without modifying the way the access are checked in the `_search` override. This could be mitigated by changing the search limit, making the search as superuser, or adding specific filtering but each has its own limitations. Adding `force_search_count` should allow the user to navigate between pages anyway and see all the available activities. But the number displayed in the pagination will often be incorrect for the current and total count. (e.g. we can have 75 records but 1-80/150 is displayed out of 140 actually readable records) opw-5046389 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233585
This update prevents an error that could happen when a user adds a product from the sales catalog and immediately removes it. Instead of failing, the system now correctly uses the product’s sale price, so the sales order remains usable and the user can continue working smoothly.
Original PR description
Currently, an error occurs when the user immediately removes a catalog product after adding it. Steps to Reproduce ([Video](https://drive.google.com/file/d/12hOavt1zCa6hbG0EWHsIDGxfgVkxJmLW/view)): -…
Currently, an error occurs when the user immediately removes a catalog product after adding it. Steps to Reproduce ([Video](https://drive.google.com/file/d/12hOavt1zCa6hbG0EWHsIDGxfgVkxJmLW/view)): - Install the `sale_management` module. - Go to `Sales Orders` and create a new `sale order`. - In the order line, click on the `Catalog` button. - `Add` a product and then immediately `remove` it. `ValueError: Expected singleton: sale.order.line()` After [this commit], when the user clicks the Remove button immediately after clicking the Add button (within 500 ms). In this case, the system proceeds with the last request due to the useDebounced delay [1], which removes the product. However, since there is no order line yet for that product [2] and the quantity is 0, the order line [3] is not created. When it attempts to retrieve the discounted price, it raises the error [4]. This commit ensures that if no order line exists, the product's price is returned according to the sale order's pricelist. [this commit]: https://github.com/odoo/odoo/pull/233098/commits/697c559791fdf00b5602b9459bbdf21f392757d8 [1]- https://github.com/odoo/odoo/blob/ec212f38e50520edf612522717952855c8c09a80/addons/product/static/src/product_catalog/kanban_record.js#L17-L19 [2]- https://github.com/odoo/odoo/blob/ec212f38e50520edf612522717952855c8c09a80/addons/sale/models/sale_order.py#L2202 [3]- https://github.com/odoo/odoo/blob/ec212f38e50520edf612522717952855c8c09a80/addons/sale/models/sale_order.py#L2218-L2219 [4]- https://github.com/odoo/odoo/blob/ec212f38e50520edf612522717952855c8c09a80/addons/sale/models/sale_order_line.py#L1602-L1603 sentry-7019831319 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#235470
We fixed an issue that could cause the QAP & SAWT report to crash when users switched to it from another report. The report now waits for its related filter information to be ready before showing the page, so it opens reliably and smoothly.
Original PR description
Before: - When switching from another report to the SAWT & QAP report, it gave traceback. - The traceback happened because the system tried to read missing data in the comparison filter. After: - Added a proper check so the report only loads the comparison filter when it exists. - Switching between reports now works smoothly without errors. Impact: - QAP & SAWT report opens reliably without unexpected crashes. Task: 5085985
The appointment page in the website editor could crash when users clicked Edit, preventing them from making changes. The template was adjusted so the page keeps the same look while avoiding a layout structure that confused the editor, restoring normal editing.
Original PR description
#### Steps to Reproduce 1- Create a fresh database on Odoo 19.0. 2 - Install both the Appointments and Website modules. 3 - Go to the website appointment page generated by the module. 4 - Click Edit…
#### Steps to Reproduce
1- Create a fresh database on Odoo 19.0.
2 - Install both the Appointments and Website modules.
3 - Go to the website appointment page generated by the module.
4 - Click Edit in the website builder.
5 - The website editor crashes with the SelectionPlaceholderPlugin error.
#### Issue
After Odoo 19 introduced the new [SelectionPlaceholderPlugin](https://github.com/odoo/odoo/blob/19.0/addons/html_editor/static/src/main/selection_placeholder_plugin.js) in the HTML editor, the appointment progress bar view began to crash, specifically when clicking the “Edit” button of the website editor on the appointment page.
This issue did not occur in earlier versions because the plugin did not exist. And the old editor never scanned or validated raw text nodes.
The appointment progress bar template contained a `li` node using d-flex directly on the `li` element.
In Odoo 19, the HTML Editor’s selectionPlaceholder plugin inspects the DOM after every render to determine where the selection placeholder blocks must be inserted.
Because d-flex changes the internal layout of the `li`, Owl and the HTML editor produces intermediate text nodes / inline nodes inside the flex container. During placeholder evaluation, the editor scans siblings before/after each block using:
```python
selection_blocker_predicates(blocker)
```
This logic expects HTML elements, as it calls:
```python
blocker.hasAttribute(...)
```
However, the flex layout caused the plugin to receive a non-element node (e.g. a TextNode) as blocker.
Since TextNodes do not implement .hasAttribute(), the editor raised:
```python
TypeError: blocker.hasAttribute is not a function
```
This error propagated into:
```python
OwlError: An error occurred in the Owl lifecycle
```
which broke the entire website editor.
#### Traceback
```python
UncaughtPromiseError > OwlError
Uncaught Promise > An error occurred in the Owl lifecycle (see this Error's "cause" property)
Occurred on localhost:8069 on 2025-11-11 13:57:55 GMT
OwlError: An error occurred in the Owl lifecycle (see this Error's "cause" property)
Error: An error occurred in the Owl lifecycle (see this Error's "cause" property)
at handleError (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:762:101)
at App.handleError (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:1420:29)
at ComponentNode.initiateRender (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:854:19)
Caused by: TypeError: blocker.hasAttribute is not a function
at selection_blocker_predicates (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:14305:1708)
at http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:14306:115
at Array.map (<anonymous>)
at checkPredicate (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:14306:106)
at isSelectionBlocker (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:14306:243)
at SelectionPlaceholderPlugin.updatePlaceholders (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:14307:272)
at http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:12434:52
at Array.forEach (<anonymous>)
at Editor.startPlugins (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:12434:38)
at Editor.attachTo (http://localhost:8069/web/assets/1/d4f733d/web.assets_web.min.js:12425:6)
```
#### Fix
To avoid creating confusing DOM structures for the editor, the template was updated to:
- Wrap the inner content to keep the same UI layout without affecting the parent `li` block semantics.
##### This insure
- The items stay a clean block-level element.
- The HTML editor correctly identifies block boundaries.
- The selection placeholder plugin no longer receives invalid nodes.
OPW - [5226904](https://www.odoo.com/odoo/project/70/tasks/5226904)This fix prevents an error that could occur when a purchased product receipt is edited and its quantity is changed to zero. Instead of crashing, the product’s value remains unchanged, allowing the user to save the receipt normally.
Original PR description
Currently an error occurs when user change the move line quantity. Steps to Reproduce [video](https://drive.google.com/file/d/12r0DxsKZkvuVjoCsRgXlHJ23NpaqciV7/view?usp=drive_link): - Install the…
Currently an error occurs when user change the move line quantity. Steps to Reproduce [video](https://drive.google.com/file/d/12r0DxsKZkvuVjoCsRgXlHJ23NpaqciV7/view?usp=drive_link): - Install the `purchase_stock` module. - Create a `product` with category: `Costing Method: FIFO`. - Create a `purchase order` and add the newly created product to it. - Click `Confirm Order`, then click on `Receipt` and `validate` it. - Click on `Moves`, open the record, set the `Quantity to zero`, and `save`. `ZeroDivisionError: float division by zero` This error occurs when a user confirms a purchase order, validates its picking, and changes the move line quantity to zero. It then tries to update the move line value and the product's standard price due to the FIFO costing method, but the valued quantity becomes zero from [1], which raises an error at [2]. This commit ensures that if the move line has a zero quantity, the product's standard price remains unchanged. [1]- https://github.com/odoo/odoo/blob/f8f72b15598576f5870e49879e96fc5c127a6100/addons/stock_account/models/stock_move.py#L333-L343 [2]- https://github.com/odoo/odoo/blob/f8f72b15598576f5870e49879e96fc5c127a6100/addons/stock_account/models/product.py#L218 sentry-6993648057 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents a server error when using the “eCommerce Categories” option in the website mega menu. The menu now correctly detects the relevant mega menu element even when the first item inside it is not the expected one, making the website editor more reliable.
Original PR description
A server traceback would occur when clicking the "eCommerce Categories" toggle in the mega menu's style options. Steps to reproduce: 1. Go to the Website editor. 2. Add a mega menu to the page header. 3. Edit and Click on the mega menu's 4. In the sidebar, click the "eCommerce Categories" toggle. -> Traceback. Cause: When loading it was trying to find a specific class name (starting with `s_mega_menu_`) to identify the snippet. It was hardcoded to only look at the `firstElementChild` of the snippet's container. This assumption was too rigid. If the first element was a `<p>` tag or another element without the required class, the code would fail to find it. This resulted in an `undefined` value being sent to the server, causing the traceback. Solution: Use `querySelector` to search for any element with a class name containing `s_mega_menu_`. opw-5245777 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
We fixed an issue where offers created from the offer list could generate an invalid link. Now every offer gets a proper access token, so the link works reliably, including when opened outside the logged-in session. This prevents broken offer pages for candidates and employees.
Original PR description
- Go to Recruitment > Applications > All Applications. - Open an applicant form and click "Generate Offer". - Repeat a few times so that the "Offers" smart button shows a list view. - From the list…
- Go to Recruitment > Applications > All Applications. - Open an applicant form and click "Generate Offer". - Repeat a few times so that the "Offers" smart button shows a list view. - From the list view, click "New" to create an offer. - Compare both flows: * With "Generate Offer" button: the generated offer link has a valid token and works even in an incognito window. * With "New" button: the generated offer link has `token=False`, which leads to an invalid link. #### Issue In the first scenario, `action_generate_offer()` generates an `access_token` for the offer's link in `hr.applicant`. In the second scenario, no token was generated in `hr.contract.salary.offer`, so offers created via the "New" button end up with `access_token=False` in their links. #### Fix Add a compute to `access_token` in `hr.contract.salary.offer` to generate a token if there is no employee or if the employee on the offer has no linked user. #### Additional - Mark the field `access_token` as readonly. task-5051394 Forward-Port-Of: odoo/enterprise#93561
This fix ensures landed costs are only applied to the quantity that is still in stock, instead of increasing the value of goods that have already been delivered. It keeps inventory valuation accurate and prevents reports from showing inflated values for products no longer on hand.
Original PR description
## Issue: When adding landed costs to stock moves, the resulting move value was increased regardless of the quantity remaining in stock As a result, moves with no remaining quantity could still…
## Issue: When adding landed costs to stock moves, the resulting move value was increased regardless of the quantity remaining in stock As a result, moves with no remaining quantity could still receive additional value, incorrectly affecting products that are no longer in stock ## Cause: The valuation is determine using the `move._get_value()` function, which uses the standard price when there is no linked PO, Bill, or Credit Note However, it distributed the landed cost share based on the move itself, without considering whether the move’s quantity was still available in stock ## Steps to reproduce: - Create a product (Tracking: Quantity, category: AVCO) - Receive 2 units of the product. - Deliver 1 unit - Create a Landed Cost for the receipt with an additional cost of 100 $ - Open Inventory > Reporting > Move Analysis - Add Value in Measures - Look for the current month (add a product filter if needed) - You should have Quantity: 2 and Value: 50$ after the fix opw-5128570 Forward-Port-Of: odoo/odoo#232857 Forward-Port-Of: odoo/odoo#231936
This fix lets managers refuse a validated time-off allocation even if leave records already exist in that period. Previously, the system could wrongly block the refusal by linking those existing leaves to the newer allocation, making it harder to correct the record.
Original PR description
## Issue: When you have an allocation and set a leave for that period, if you add a new allocation for that period and you validate it, it will be impossible to Refuse this allocation later A…
## Issue: When you have an allocation and set a leave for that period, if you add a new allocation for that period and you validate it, it will be impossible to Refuse this allocation later A UserError was raised asking to remove the leave even if it should be linked to the first allocation created ## Cause: The `action_refuse()` method for `hr.leave.allocation` uses the `virtual_leaves_taken` value inside the `_get_consumed_leaves()` function's result That parameter is calculated for the allocation as far as it state is `validate`, for all the leaves in that time interval, including previously created leaves The leaves will be allocated to the last allocation created, so the last one can't be removed later As a result, the allocation is considered as already used by these pre-existing leaves, even if the leave can still be modified to return to the state prior to the allocation's validation ## Steps to reproduce: - Create an initial Allocation (that should end after the next created Allocation) - Create a Leave from 22/12/2025 to 31/12/2025 - Create an Allocation including the leave period (01/12/2025 to 31/12/2025) - Validate, then Refuse opw-4900686 Forward-Port-Of: odoo/odoo#235711 Forward-Port-Of: odoo/odoo#222171
This update fixes the Philippine Summary Lists of Sales and Purchases report so company customers now appear with their registered name again. It also ensures exported files show the correct name format for both companies and individuals, improving report accuracy and compliance.
Original PR description
**Steps to reproduce:** 1. Install the `Accounting` and `l10n_ph_reports` modules. 2. Create a contact with the company flag enabled. 3. Create an invoice using that contact. 4. Go to `Reporting →…
**Steps to reproduce:**
1. Install the `Accounting` and `l10n_ph_reports` modules.
2. Create a contact with the company flag enabled.
3. Create an invoice using that contact.
4. Go to `Reporting → Summary Lists of Sales and Purchases → Sales`.
**Observed behavior:**
* The `Registered Name` column in the report is blank for companies.
**Cause:**
* The query logic was incorrectly showing the registered name only when a last name was present. This issue arose due to the change in how company/individual differentiation is handled.
**Fix:**
* Update the query logic for the Odoo report:
- **Always display the registered name in the Odoo report**:
- If individual: show `First Name`, `Middle Name`, `Last Name`.
- If company: show `commercial_partner_id.name`.
- **For the export file**:
- If company: only show the registered name.
- If individual: show `First Name`, `Middle Name`, `Last Name`.
The fix ensures that **Registered Name** is always displayed in the report, and the export behaves as expected for both individuals and companies.
Note: spec provided by po ->
<img width="1662" height="431" alt="image" src="https://github.com/user-attachments/assets/a7a58a9e-b769-4815-ad0a-cef9c8e2eff7" />
opw-5143677This update fixes an issue where some Sendcloud delivery services could not show drop-off point selection during checkout. Customers can now choose a locker or service point on the map when the delivery method supports it, improving the delivery experience and preventing missing options at checkout.
Original PR description
Steps to reproduce ----- - Create a Sendcloud delivery method - Select a delivery service with "Locker or service point" as "Last mile" (eg "bpost @ bpack") > "Use Sendcloud locations" is set to…
Steps to reproduce ----- - Create a Sendcloud delivery method - Select a delivery service with "Locker or service point" as "Last mile" (eg "bpost @ bpack") > "Use Sendcloud locations" is set to false Cause ----- There is a problem with the values retrieved from the Sendcloud API call, more specifically the `available_functionalities` > `last_mile` value. The Sendcloud API (of both previous and current beta version) specifies the possible values to only be the following - `home_delivery` - `mailbox` - `pobox` - `service_point` - null https://api.sendcloud.dev/docs/sendcloud-public-api/shipping-options/operations/create-a-shipping-option https://api.sendcloud.dev/docs/sendcloud-public-api/branches/v2/shipping-products/operations/list-shipping-products However, it seems like they have added some new undocumented values `locker` and `locker_or_service_point`. To detect whether to use drop-off locations, we do https://github.com/odoo/enterprise/blob/5b64c63301bc814c7c9d99146af6a86d37563762/website_delivery_sendcloud/models/delivery_sendcloud.py#L51-L53 Where we compare the retrieved value with the string 'Service point' https://github.com/odoo/enterprise/blob/5b64c63301bc814c7c9d99146af6a86d37563762/website_delivery_sendcloud/models/delivery_sendcloud.py#L13 In our "Locker or service point" case, this does not work because the `in` operator makes a case sensitive comparison. Solution ----- Functionally, both lockers and service points work the same. The user should be prompted a map on which they choose where the delivery should be dropped off. So we can add `Locker` and `Locker or service point` as accepted values and enable the use of sendcloud locations for both. ----- Ticket: opw-5217796 Forward-Port-Of: odoo/enterprise#98875
This update corrects a missing reference in the Point of Sale cash move popup so new orders include the right configuration information. It helps avoid receipt printing problems when handling cash moves.
Original PR description
Before this commit, the cash move popup created an order that missing the config_id field, leading to potential issues in receipt printing. opw-5251257 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#236203
This change fixes WebSocket timeout handling so stalled connections are detected and closed correctly. It improves reliability by making sure the system does not leave connections hanging when the other side stops responding.
Original PR description
This PR fixes several issues with WebSocket timeouts: - Waiting for more than one response was not handled properly, resulting in missed timeouts. - The closing handshake did not strictly follow the RFC when initiated on the server side (it closed without waiting for the other peer). - Close timeouts were not enforced (the connection was not terminated when the other peer did not respond to the close frame). Forward-Port-Of: odoo/odoo#236016 Forward-Port-Of: odoo/odoo#234881
This update prevents the website editor from crashing when a saved AI live chat snippet is added again from the custom blocks list. It improves the editing experience by making saved snippets reusable without error.
Original PR description
Steps to reproduce: ------------------------- 1. Install Website and AI modules. 2. Open the website editor. 3. From the Intro block, search for the AI snippet and add the snippet contains 'Need…
Steps to reproduce:
-------------------------
1. Install Website and AI modules.
2. Open the website editor.
3. From the Intro block, search for the AI snippet and add the snippet contains 'Need Help?'.
4. Click on the added block, then click the Save icon from the Style tab.
5. Save the snippet
6. Go to Blocks → Custom Blocks and add the saved snippet.
Observation:
-------------------------
A traceback is raised:
```
TypeError: Cannot read properties of null (reading 'remove')
at AILivechatOptionPlugin.onSnippetDropped
```
Issue:
-------------------------
The `onSnippetDropped` method
https://github.com/odoo/enterprise/blob/bb3699cc112acb3ec545d3aa5f3d8f7263a5dac6/ai_website_livechat/static/src/website/plugins/ai_livechat_option_plugin.js#L39-L51 executes every time a snippet is dropped into the layout. When the snippet is first added, the method removes the `<div>` with class `s_ai_livechat_preview`. Upon saving, the snippet is stored without that `div`. When re-adding the saved snippet from custom tab, the method runs again but fails since the `s_ai_livechat_preview` element no longer exists, resulting in the traceback.
Solution:
-------------------------
Added the optional chaining operator to safely remove the `s_ai_livechat_preview` div only when it exists.
opw-5227072