Skip to content

Merged from upstream 19 260130 01#1182

Open
davidtranhp wants to merge 333 commits intoViindoo:19.0from
davidtranhp:merged_from_upstream_260130_01
Open

Merged from upstream 19 260130 01#1182
davidtranhp wants to merge 333 commits intoViindoo:19.0from
davidtranhp:merged_from_upstream_260130_01

Conversation

@davidtranhp
Copy link

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

hisi-odoo and others added 30 commits January 21, 2026 16:39
…n SInvoice

Before:
SInvoice was stripping newlines from the `itemName` field. Since we were directly
using `line.name` (which contains a `\n` between product name and description),
the content ended up concatenated without any separation.

After:
Now we replace the newline with a space before sending the value, so the name
and description remain readable once processed by SInvoice and set
limit to 500 characters as per API specs.

task-5498120

closes odoo#244794

X-original-commit: 55d6e27
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Signed-off-by: Himilsinh Sindha (hisi) <hisi@odoo.com>
Steps to reproduce:
1. Set network speed to 3G
2. Create website Page from the systry new menu
3. click on edit button
You'll face the traceback.

The website editor could try to open before the iframe finished
loading, leading to non-deterministic behavior. This commit ensures
the editor initializes only after the iframe load event, making the
edit action consistent and reliable.

Erlier fixed was not covering the all the cases. PR: odoo#238054

runbot-233039

closes odoo#244808

X-original-commit: 7f38f8e
Signed-off-by: Francois Georis (fge) <fge@odoo.com>
Signed-off-by: Divyesh Vyas (divy) <divy@odoo.com>
Steps to Reproduce : 

- Open To-Do and type some text.
- Place the cursor at the start of the block.
- Insert a table. (e.g.: /table)
- The table appears after the text instead of before it.

Purpose of this commit:

- Table insertion logic was previously duplicated inside TablePlugin,
where it tried to manually split text and inline nodes before inserting
the table. However, this responsibility is now correctly handled by
DomPlugin.insert(), which already:
 - deletes the current selection if needed,
 - splits text and inline nodes safely,
 - handles block boundaries and unsplittable elements,
 - normalizes the DOM after insertion, and
 - places the cursor at a valid position.

task-5480759

closes odoo#244689

X-original-commit: cb5cf99
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Adnan Chaudhary (adch) <adch@odoo.com>
For export invoices, the total invoice value in the eWaybill JSON did not
include reverse charge amounts for GST, leading to a mismatch with the value
shown in Odoo and the eWaybill generated by the Indian government system.

This commit adjusts the JSON computation to include reverse charge amounts
in the total invoice value for exports, aligning it with the government
generated eWaybill, while preserving the existing reverse charge flow.

task-5068199

closes odoo#244839

X-original-commit: a2fb5ef
Signed-off-by: Josse Colpaert (jco) <jco@odoo.com>
Signed-off-by: Harsh Shah (hash) <hash@odoo.com>
This commit adds a new client action that will be used to display an exception
on the WebClient.

Part-of: odoo#243623
Signed-off-by: Krzysztof Magusiak (krma) <krma@odoo.com>
It is possible to run a cron via the "Run Manually" button of the
ir.cron form view. In 18.4 and before, in case the cron failed due to an
exception, that exception would appear in the web client. Since 19.0 and
commit 78c00d2, the exception no longer bubbles-up to the web client. It
is only logged in the server logs.

Many system admins and also the Odoo support use on the "Run Manually"
to quickly test a cron and make sure it works. The change done in 19.0
is considered as a nasty surprise. They want their exceptions back!

When running a cron manually, we now track the logs that are emitted on
the cron logger and search for an error with an exception. May we find
one, we send a client action that display an error modal in the web
client.

closes odoo#243623

Signed-off-by: Krzysztof Magusiak (krma) <krma@odoo.com>
…N16931)

The list is there but not exhaustive.

Make the exhaustive list of VAT exemption reason codes (VATEX) available.

task-5443294

closes odoo#244555

Signed-off-by: Laurent Smet (las) <las@odoo.com>
### Contains the following commits:

odoo/o-spreadsheet@bd44f59a66 [REL] 19.0.18 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
odoo/o-spreadsheet@7b6469f3de [PERF] evaluation: fast predicate path for empty strings [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
odoo/o-spreadsheet@49a8ade732 [FIX] range: add result changeType [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@c1d5ddafc9 [FIX] range: adapt string XC on sheet rename [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@b148744709 [FIX] range: rename parameter [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@dcd419a83e [FIX] range: add range to NONE [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@a2e329cfb3 [FIX] Actions: ensure the sequence is applied on action children [Task: 5452669](https://www.odoo.com/odoo/2328/tasks/5452669)
odoo/o-spreadsheet@edc5f21755 [FIX] composer: prevent autocomplete from closing on grid icon drag [Task: 5392156](https://www.odoo.com/odoo/2328/tasks/5392156)
odoo/o-spreadsheet@8446e90c25 [PERF] evaluation: don't spread single element matrix [Task: 5491138](https://www.odoo.com/odoo/2328/tasks/5491138)
odoo/o-spreadsheet@63c002a1ee [FIX] evaluation: remove spread relation [Task: 5491138](https://www.odoo.com/odoo/2328/tasks/5491138)
odoo/o-spreadsheet@1642f79973 [FIX] vectorization: fix error message on size mismatch [Task: 5331324](https://www.odoo.com/odoo/2328/tasks/5331324)
odoo/o-spreadsheet@c7c2baabfb [FIX] chart: ignore NoChanges in gauge/scorecard side panel errors [Task: 5478288](https://www.odoo.com/odoo/2328/tasks/5478288)
odoo/o-spreadsheet@4589afc1fd [IMP] xlsx: export clip [Task: 5368130](https://www.odoo.com/odoo/2328/tasks/5368130)
odoo/o-spreadsheet@9f4416e6f1 [IMP] export: export align left when the cell content is a number; [Task: 5368130](https://www.odoo.com/odoo/2328/tasks/5368130)
odoo/o-spreadsheet@c8c01a1fe1 [FIX] header_size: wrong row size from wrapped number [Task: 4878338](https://www.odoo.com/odoo/2328/tasks/4878338)

Part-of: odoo#244981
Related: odoo/enterprise#105056
Signed-off-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Co-authored-by: Florian Damhaut (flda) <flda@odoo.com>
Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com>
Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com>
Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com>
Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com>
Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com>
Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com>
Co-authored-by: Rémi Rahir (rar) <rar@odoo.com>
Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com>
Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
See odoo/o-spreadsheet@6533266efa

Task: 5095364
Part-of: odoo#244981
Related: odoo/enterprise#105056
Signed-off-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
### Contains the following commits:

odoo/o-spreadsheet@bd44f59a66 [REL] 19.0.18 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
odoo/o-spreadsheet@7b6469f3de [PERF] evaluation: fast predicate path for empty strings [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
odoo/o-spreadsheet@49a8ade732 [FIX] range: add result changeType [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@c1d5ddafc9 [FIX] range: adapt string XC on sheet rename [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@b148744709 [FIX] range: rename parameter [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@dcd419a83e [FIX] range: add range to NONE [Task: 5095364](https://www.odoo.com/odoo/2328/tasks/5095364)
odoo/o-spreadsheet@a2e329cfb3 [FIX] Actions: ensure the sequence is applied on action children [Task: 5452669](https://www.odoo.com/odoo/2328/tasks/5452669)
odoo/o-spreadsheet@edc5f21755 [FIX] composer: prevent autocomplete from closing on grid icon drag [Task: 5392156](https://www.odoo.com/odoo/2328/tasks/5392156)
odoo/o-spreadsheet@8446e90c25 [PERF] evaluation: don't spread single element matrix [Task: 5491138](https://www.odoo.com/odoo/2328/tasks/5491138)
odoo/o-spreadsheet@63c002a1ee [FIX] evaluation: remove spread relation [Task: 5491138](https://www.odoo.com/odoo/2328/tasks/5491138)
odoo/o-spreadsheet@1642f79973 [FIX] vectorization: fix error message on size mismatch [Task: 5331324](https://www.odoo.com/odoo/2328/tasks/5331324)
odoo/o-spreadsheet@c7c2baabfb [FIX] chart: ignore NoChanges in gauge/scorecard side panel errors [Task: 5478288](https://www.odoo.com/odoo/2328/tasks/5478288)
odoo/o-spreadsheet@4589afc1fd [IMP] xlsx: export clip [Task: 5368130](https://www.odoo.com/odoo/2328/tasks/5368130)
odoo/o-spreadsheet@9f4416e6f1 [IMP] export: export align left when the cell content is a number; [Task: 5368130](https://www.odoo.com/odoo/2328/tasks/5368130)
odoo/o-spreadsheet@c8c01a1fe1 [FIX] header_size: wrong row size from wrapped number [Task: 4878338](https://www.odoo.com/odoo/2328/tasks/4878338)

closes odoo#244981

Related: odoo/enterprise#105056
Signed-off-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Co-authored-by: Florian Damhaut (flda) <flda@odoo.com>
Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com>
Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com>
Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com>
Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com>
Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com>
Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com>
Co-authored-by: Rémi Rahir (rar) <rar@odoo.com>
Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com>
Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
closes odoo#244845

X-original-commit: a6d562f
Signed-off-by: Claire Bretton (clbr) <clbr@odoo.com>
**Issue**:

When the module `l10n_ro_edi_stock` is installed and Romanian is the selected language,
accessing the settings app causes a traceback.

**Steps to reproduce**:

- Install the module `l10n_ro_edi_stock`
- Select a Romanian company
- In Profile > My Preferences > select Romanian language
- Try to access the settings

-> A traceback occurs

**Cause**:

The error is caused by this XPath:

https://github.com/odoo/odoo/blob/2309fb56553e6ae9f89b6dd0947aba2f54408960/addons/l10n_ro_edi_stock/views/res_config_settings_views.xml#L9C13-L11C21

Specifically, the `'select the option'` part. The XPath tries to replace this line in the parent view:

https://github.com/odoo/odoo/blob/2309fb56553e6ae9f89b6dd0947aba2f54408960/addons/l10n_ro_edi/views/res_config_settings_views.xml#L39

but fails to find it because the source text has already been translated at that point, so `'select the option'` no longer matches:

https://github.com/odoo/odoo/blob/2309fb56553e6ae9f89b6dd0947aba2f54408960/odoo/tools/template_inheritance.py#L154

opw-5490346

closes odoo#244898

X-original-commit: 7595df3
Signed-off-by: Antoine Boonen (aboo) <aboo@odoo.com>
…ges setting

Before this commit:
===================
- When the `Show product images` setting was disabled, the optional products UI
still displayed product images.
- If an optional product did not have an image, the UI displayed the image's alt
text
- Also when the product don't have image, the combo popup and product card just
display the product name.

After this commit:
==================
- Optional product images are displayed only when the `Show product images`
configuration is enabled.
- If the optional product doesn't have an image, we will display an image
placeholder instead of alt text.
- If there is no product image, the combo popup and product card will
display the image placeholder.

closes odoo#244809

Task: 5480181
X-original-commit: 888e181
Signed-off-by: David Monnom (moda) <moda@odoo.com>
Signed-off-by: Vedant Pandey (vpan) <vpan@odoo.com>
Odoo controllers often don't use coherent API they respond with either json, jsonrpc or html.
On the client side, we have no reliable way to know this, and sometimes it is not possible to make a guess
(rpc.js makes the guess that controllers are of json type -- actually meaning jsonrpc)

The file upload service suffered from this and did not handle those error cases well.

After this commit, the file upload service handles much of the errors.

closes odoo#244904

X-original-commit: 2fd456e
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
When printing several picking operation at once, they are all in the same page.

Steps to reproduce:
-------------------
* Inventory>Operations>Deliveries
* Create several Deliveries
* Open list view to see all the deliveries
* Select several deliveries
* Print > Picking Operations
-> All the picking operation report are on the same page.

Observation:
-------------
Since the change on the picking report layout
https://github.com/odoo/odoo/pull/152280/changes#diff-7542c191def78bd64f54f1c33fde2c73e19e4d27f92b195c464d1d84e55b682fL6-R8
the report now uses a single article container for all records, this don't trigger automatic page break.

opw-5481034

closes odoo#244849

X-original-commit: a0d8b7f
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Joseph Vankelegom (josv) <josv@odoo.com>
**Steps to reproduce:**
- Go to Event module
- Go to an open event
- Register for the event
- Go to the Attendees of the event
- On the attendee record, click `Send by Email`
- The received email shows twice the header and footer

**Issue:**
Encapsulating notification layout was applied with
`default_email_layout_xmlid` but the main template used
is `event_registration_mail_template_badge` which
already has its own header and footer.

**Fix:**
Removed the `default_email_layout_xmlid`

opw-5032767

closes odoo#244840

X-original-commit: 5b80307
Signed-off-by: Noé Antoine (nan) <nan@odoo.com>
…ith pos_hr

When the POS is locked by an employee (pos_hr module active and no cashier logged in), users could bypass the login screen by using the browser back button.

Steps to reproduce:
-------------------
* Install pos_hr module
* Open a POS session and log in as an employee
* Lock the POS
* Use browser back button to navigate back
> Observation:
The POS reopens without requiring employee login, allowing unauthorized access to protected pages.

Why the fix:
------------
The handleUrlParams method now checks if pos_hr is active and if no cashier is logged in before processing URL parameters. If an unauthenticated user tries to access a protected page (other than LoginScreen), they are automatically redirected to the LoginScreen. This ensures that the POS security is maintained even when using browser navigation.

opw-5400719

closes odoo#244757

X-original-commit: 0d0d9ce
Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Signed-off-by: Guillaume Vardakis (gvar) <gvar@odoo.com>
When a preparation printer is configured to print only specific product categories
(e.g., drinks only), adding items from other categories (e.g., food) would cause
the printer to reprint the previous order with a "NEW (DUPLICATE!)" label.

Steps to reproduce:
-------------------
* Configure a restaurant/bar POS with a preparation printer set to print only drinks
* On a table, order a drink item → printer correctly prints "NEW" ticket with the drink
* On the same table, add a food item (not in printer categories)
* Trigger sending to preparation (e.g., validate order or send to kitchen)

> Observation: The printer prints a duplicate of the previous drink order showing "NEW (DUPLICATE!)" instead of staying silent.

Why the fix:
------------
The `sendOrderInPreparation` method was automatically reusing `order.uiState.lastPrint`
when no preparation category changes were detected, causing an implicit reprint.
This behavior is incorrect when the order only contains items outside preparation
printer categories - the printer should simply not print anything.

The fix:
- Prevents automatic reprint when there are no prep category changes
- Still calls `updateLastOrderChange()` to mark the order as "sent" and prevent
  the restaurant popup warning about unsent orders
- Only allows explicit reprints via `opts.explicitReprint` flag for future use cases

opw-5358075

closes odoo#244756

X-original-commit: 6581c15
Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Signed-off-by: Guillaume Vardakis (gvar) <gvar@odoo.com>
When printing many receipts quickly using a USB printer, this error was
occasinally occuring:

```
WARNING ? odoo.addons.iot_drivers.iot_handlers.drivers.printer_driver_base: Failed to query ESC/POS status
ERROR   ? root: Could not set configuration: [Errno 16] Resource busy
```

This would cause `python-escpos` to be disabled and fallback to just
CUPS printing.

The issue was caused by two threads trying to access the printer at the
same time, which could happen in two ways:
- IoT thread with `python-escpos` and CUPS try to access the printer at
  the same time.
- Two IoT threads with `python-escpos` try to access the printer at the
  same time (this can happen if two receipt actions are received at the
  same time).

Both of these scenarios should now prevented:
- Now, if we are using `python-escpos`, we also use it to print the
  receipt as well as checking the status. CUPS is never used so there
  should be no interference from it.
- We now have an `escpos_lock` (per printer, not global) that is
  acquired when accessing the printer via `python-escpos`. This ensures
  that different threads cannot both try to access the printer at the
  same time.

task-5490942

closes odoo#244370

X-original-commit: 07ca8a4
Signed-off-by: Louis Travaux (lotr) <lotr@odoo.com>
Signed-off-by: Max Whale (mawh) <mawh@odoo.com>
…ith bank statement lines

closes odoo#244896

X-original-commit: ffafaf5
Related: odoo/enterprise#104996
Signed-off-by: Hugo Poncelet (hupo) <hupo@odoo.com>
Signed-off-by: Olivier Colson (oco) <oco@odoo.com>
**Steps to reproduce:**
* Install the **l10n_ch** module for a Swiss company.
* Create a vendor bill for a **foreign vendor**.
* Apply a reverse charge tax:
  * **8.1% R C** (figure **383a**), or
  * **7.7% R C** (figure **382a**).
* Confirm the vendor bill.
* Go to **Accounting → Reporting → Tax Report**.
* Generate the VAT report for the relevant period.

**Observed behavior:**
* Figure **383a** (8.1% reverse charge) is reported as **negative**.
* Figure **382a** (7.7% reverse charge) is reported as **negative**.
* This results in incorrect VAT reporting.

**Cause:**
* Reverse charge taxes use **negative tax rates** to model the reverse
  mechanism.
* The base amounts were tagged with **positive** signs, leading to
  negative values in the report.

**Fix:**
* Invert the base formula signs for 383a and 382a:
  * **382a**: change base formula from `-382a` to `382a`.
  * **383a**: change base formula from `-383a` to `383a`.
* Reverse charge base amounts now appear as **positive** values in the
  VAT report.

opw-5257445

closes odoo#244934

X-original-commit: f5d5783
Signed-off-by: Olivier Colson (oco) <oco@odoo.com>
Signed-off-by: Raj Bhuva (bhra) <bhra@odoo.com>
Issue Before This Commit:
================================
Previously, the delivery carrier was only propagated between pickings when it
was set from the sale order. If the carrier was manually set on a picking
(e.g., during the packing step in a multi-step delivery flow), it was not
propagated to the consequent pickings, even when the stock rules had
`Propagation of carrier` enabled.

Steps to reproduce:
================================
1. Activate Multi-Step Routes and Delivery Methods.
2. Configure a 3-step delivery route in the warehouse and enable Propagate
   Carrier on all rules.
3. Create a sale order with a product but without setting a delivery carrier.
4. Confirm the sale order to generate picking.
5. On the first picking (i.e., pick), manually set a delivery carrier
   (e.g., Local Delivery) and validate.
6. On the next transfer (i.e., pack), observe that the delivery carrier is not
   propagated.

After this commit:
================================
The delivery carrier set on any picking is propagated to subsequent transfers
when the corresponding stock rule has Propagation of carrier enabled and no
carrier is already configured on the next picking.

This ensures consistent carrier propagation across all routing configurations
(all pull rules, all push rules, and mixed push/pull flows), even when the
carrier is configured at the picking level rather than on the sale order.
This behavior is required because, in many business scenarios, carrier selection
is managed by the logistics team rather than the sales team.

task-4454313

closes odoo#243597

X-original-commit: 0fa1a98
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
When sending an invoice to SInvoice (Viettel), the API raises an
`INVALID_DECIMAL_POINT_TAX_MONEY` error if the tax amount contains
excessive decimal places (e.g., 100.02999999999997).

This occurs because the tax amount is currently calculated using simple
subtraction (`total - subtotal`). Due to standard floating-point
precision issues, this can result in unrounded values that
the API rejects.

The tax amount calculation is now updated to explicitly use the
currency's rounding method, ensuring the value is accepted by SInvoice.

task-5484845

closes odoo#244929

X-original-commit: 08ae1c0
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Steps to reproduce:
===================
1. Enable the Cookies Bar in website settings.
2. Go to the website and enter Edit mode.
3. Select the Cookie Bar and change the button "I agree" style shape to
"Default"  (this applies the `.btn-primary` class). & Save
4. Accept the cookies & refresh

-> The cookie bar appears again because the consent was not saved.

Cause:
======
The `CookiesBar` widget inherits from the generic `Popup` widget.
The `Popup` class defines a default behavior for elements with the
`.btn-primary` class: clicking them triggers `onBtnPrimaryClick`,
which closes the popup.

By default, the cookie bar button uses `.btn-outline-primary`, avoiding
this behavior. However, when the user changes the style to "Default",
the button receives the `.btn-primary` class. Consequently, the
parent `Popup` handler is triggered. It closes the modal prematurely,
interrupting the `CookiesBar`'s specific logic (specifically
`onAcceptClick`),So onHideModal won't be called inside the function,
and as a result, the user's consent cookie is never written.

Solution:
=========
Override the event to avoid side effects on hide.

opw-5484578

closes odoo#244875

X-original-commit: dde9485
Signed-off-by: Robin Lejeune (role) <role@odoo.com>
Signed-off-by: Saif Allah Ben Khalil (sben) <sben@odoo.com>
Summary:
Refactor `preserveSelection()` to use a stack-based approach
(`preservedCursors` array) instead of a single cursor reference.
This allows nested calls to `preserveSelection()` to operate
independently while keeping cursor updates synchronized across active
contexts.

Problem:
Using a single stored cursor caused issues in nested calls to
`preserveSelection()`:

1. **State overwrite:** Inner calls could overwrite or clear the
   outer cursor.
2. **Stale references:** If an inner function replaced a DOM node,
   the outer cursor could still point to a removed node and fail
   on restore.

Solution:
Use an array of cursor subscribers

- **Shared updates:** When calling `remapNode` on a cursor, it
  iterates over all active subscribers in the stack. This ensures
  node replacements performed in inner contexts also update outer
  cursor references.
- **Scoped cleanup:** `restore()` now removes only the corresponding
  cursor instance from the stack, ensuring proper lifecycle
  management.

Example:
The key improvement is that outer scopes receive updates performed
by inner scopes.

```javascript
// Function A (outer)
function wrapperFunction() {
    const cursor = this.preserveSelection();
    replaceTextWithSpan();
    cursor.restore();
}

// Function B (inner)
function replaceTextWithSpan() {
    const innerCursor = this.preserveSelection();
    const oldNode = document.querySelector('text');
    const newNode = document.createElement('span');
    oldNode.replaceWith(newNode);
    innerCursor.remapNode(oldNode, newNode);
    innerCursor.restore();
}
```
opw-5386862

X-original-commit: 63ccff8
Part-of: odoo#244758
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit improves `splitElement` by avoiding deletion of the
original element being split. Instead, it only creates the `after`
element that receives the moved nodes, preserving the original
element and reducing unnecessary DOM mutations.

task-5386862

Part-of: odoo#244758
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Problem:
Links with no content that are not selected are kept when calling
`updateFeffs`, leaving empty anchor elements in the DOM.

Solution:
Only make links eligible for `Zwnbsp` insertion when they are selected
or when they contain actual content. Otherwise, empty and unselected
links are removed during `updateFeffs`.

task-5386862

Part-of: odoo#244758
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Problem:
Some tests fail when using `makeSavePoint` because preserved cursors
are not updated after steps are restored.

Additionally, the selection is staged too early during paste. It is
currently restored using the state from before
`before_paste_handlers`, while those handlers can adapt the selection
specifically for the paste operation.

Solution:
- Update preserved cursors after steps restoration so they stay in
  sync with the restored DOM state only when there is no draft mutations
  otherwise we restore the initial preserved selection.
- Stage the selection in the clipboard plugin after
  `before_paste_handlers`, ensuring the selection reflects the final
  adjusted state before pasting.
- Fix `selectFullText` to trigger `pointerup` to have a correct staged
selection.

opw-5386862

closes odoo#244758

Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
As runbot faketimes test fail because the usage of dynamic dates

now the test uses freeze_time

Task#5717031

closes odoo#245000

X-original-commit: b8e89e7
Signed-off-by: Abdelrahman Mahmoud (amah) <amah@odoo.com>
If an action takes a long time to execute (>6s), then we don't add
the unique id during this time as the action didn't finish.
As it exceeds 6 seconds, we also send one through websocket,
that isn't filtered as duplicate as the action id isn't set yet
in the `_recent_action_ids` cache.

To avoid this, we add the action id to the cache, then execute the
action and remove the id from the cache if there is an exception.

closes odoo#245026

X-original-commit: 4c3c231
Signed-off-by: Max Whale (mawh) <mawh@odoo.com>
Signed-off-by: Louis Travaux (lotr) <lotr@odoo.com>
Armin-FalDiS and others added 13 commits January 29, 2026 19:40
On MRP production kanban, if the name of the
product is too long, `product_qty` and
`product_uom_id` fields on the card shrink and
become unreadable.

This adds proper classes to keep those fields from
shrinking no matter how long product's name is.

closes odoo#246104

X-original-commit: 836b329
Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
Inconsistent data in the localDB or local storage can cause the POS to
fail before it can get initialized. When this happens the page just
stays showing the loading screen forever.

Now when an error happens while initializing the POS the loader will
disappear and the app will give the user the option to clear all local
data and refresh the page. This should be especially useful for users on
mobile where it's a pain to refresh the local data manually.

Task-[5420544](https://www.odoo.com/odoo/project/1737/tasks/5420544)

closes odoo#246217

X-original-commit: 9775b44
Signed-off-by: David Monnom (moda) <moda@odoo.com>
When product images are hidden (image_width='none' or missing), switching
between product variants caused a traceback.

Steps to reproduce:
===================
- Go to a product page with variants
- Edit mode & change the image to hidden
- Change variant

-> Traceback

Cause:
======
- The server doesn't send `carousel` data when images are hidden
  (product_page_image_width='none')
- However, `_getProductImageContainerSelector()` still returned a valid
  selector ("#o-carousel-product" or "#o-grid-product")
- `querySelector` found the existing (but empty) image container in the DOM
- `_updateProductImage()` was called with `undefined` as newImages parameter
- the re-queried images element crashed

In old versions we remove the carousel, but now when we hide the image
we add the class `o_wsale_product_page_opt_image_width_none` which hides
the image via CSS, But the carousel still exists

Solution:
=========
In old version it was jquery and it was only checking for the existance
of the Old images.
Now it will check both old and new images.
(we can check the existance of the class
`o_wsale_product_page_opt_image_width_none` and avoid the update too)

[1]: https://github.com/odoo/odoo/blob/77bfe416d08eefc720f12899490d3d39efacb74a/addons/website_sale/static/src/js/website_sale.js#L294

opw-5499004

closes odoo#246081

Signed-off-by: Valeriya Chuprina (vchu) <vchu@odoo.com>
Steps to reproduce:

1. Go to Website (Edit mode) and drop a title block.

2. Select the title, set a highlight effect, and save the page.

3. Load the page in a reduced viewport in a way that makes the
highlighted text split into multiple lines.

4. The highlight won't be applied correctly (only the last line will be
detected).

The current line detection mechanism relies on the horizontal comparison
of rects (see `rectToBatch()`), which returns wrong results when applied
to centered text content.

The goal of this commit is to add a y-coordinate (vertical) check to
detect new lines more reliably in `rectToBatch()`. This improves
robustness for multi-line selections with unusual layouts.

related to opw-4865891

closes odoo#245142

X-original-commit: c54a82d
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Signed-off-by: Outagant Mehdi (mou) <mou@odoo.com>
Before this commit, loading the list view of the website pages invoked
a method called `_get_most_specific_pages`. This method caused a memory
error due to loading the field called `key` for the pages being fetched.
This field was related to a field called `key` in the model
`ir.ui.view`, so a cache miss in the recordset causes a `SELECT *` query
for the ir.ui.view potentially causing a memory error if the size of
these views are big.

A solution for this is to force the ORM to load only the `key` field by
invoking **search_fetch** on the `ir.ui.view` model instead.

In order to improve the retrieval of a given page key count, we now use
a Counter map (=> constant time instead of linear search).

closes odoo#245600

X-original-commit: 15b65a8
Signed-off-by: Soukéina Bojabza (sobo) <sobo@odoo.com>
Steps to Reproduce:
1. Drag and drop the dynamic products snippet.
2. Select it and change the content width to “max”.

Issue:
When the content width is set to “max”, an unnecessary horizontal scroll
appears.

Reason:
The issue occurs because the "previous" and "next" navigation buttons
were not properly positioned.

Fix:
For devices larger than "mobile", the "previous" and "next" buttons are
repositioned, horizontally inward by "50%" of their own width with the
help of "transform" property. This keeps the controls within the visible
area and prevents horizontal scrolling.

task-5090468

closes odoo#246288

X-original-commit: 9d99b53
Signed-off-by: Alay Patel (alap) <alap@odoo.com>
Before:
the scrollbar of the kanban view in timeoff was not showing coz of which users
were not able to see their timeoffs easily

After:
Fixed the scrollbar of the kanban view so that the user can be able to see their
timeoffs which they were not able to do that easily

Fix:
Added the overflow-x as auto so that the scrollbar is visible.

Task:5502863

closes odoo#246323

X-original-commit: edbe600
Signed-off-by: Abdelrahman Mahmoud (amah) <amah@odoo.com>
Signed-off-by: Devendra Jaikishan Ladhani (djal) <djal@odoo.com>
Steps to Reproduce:
1. Go to Accounting > Configuration > Journals
2. Archive a Journal with outgoing payment method
3. Go to Expenses > Create an Expense paid by company
4. Note that payment methods from archived journal are still visible and can be
selected.

Issue:
- Archived journals with outbound payment methods were still selectable
 when creating company-paid expenses.
- Due to this [commit](odoo@c4f2108)
The journals can be archived without system prevention as the action_archived
method has been removed.

Solution:
- This occurred because selectable_payment_method_line_ids did not filter
out inactive journals when falling back to a generic search.
-Aligning the search domain with
[company_expense_allowed_payment_method_line_ids]
(https://github.com/odoo/odoo/blob/19.0/addons/hr_expense/models/res_company.py#L20)
by excluding payment method lines linked to inactive journals.

Before Fix:
```py
In [1]: expense = self.env['hr.expense'].browse(1639)

In [2]: expense.selectable_payment_method_line_ids
Out[2]: account.payment.method.line(2, 4, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 166, 170, 172, 512, 516)

In [3]: archived_journal_ids = []

In [4]: payment_method_lines = self.env['account.payment.method.line'].search([
   ...:                     *self.env['account.journal']._check_company_domain(expense.company_id),
   ...:                     ('payment_type', '=', 'outbound'),
   ...:                 ])

In [5]: payment_method_lines
Out[5]: account.payment.method.line(2, 4, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 166, 170, 172, 512, 516)

In [6]: for payment_method_line in payment_method_lines:
   ...:     if not payment_method_line.journal_id.active:
   ...:         archived_journal_ids.append(payment_method_line.journal_id.id)
   ...:

In [7]: archived_journal_ids
Out[7]: [7, 8]
```

After Fix:
```py
In [8]: payment_method_lines_with_fix = self.env['account.payment.method.line'].search([
   ...:                     # The journal is the source of the payment method line company
   ...:                     *self.env['account.journal']._check_company_domain(expense.company_id),
   ...:                     ('payment_type', '=', 'outbound'),
   ...:                     ('journal_id.active', '=', True),
   ...:                 ])
In [9]: payment_method_lines_with_fix
Out[9]: account.payment.method.line(153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 166, 170, 172, 512, 516)

In [10]: archived_journal_ids_with_fix = []
In [11]: for payment_method_line in payment_method_lines_with_fix:
    ...:     if not payment_method_line.journal_id.active:
    ...:         archived_journal_ids_with_fix.append(payment_method_line.journal_id.id)

In [12]: archived_journal_ids_with_fix
Out[12]: []
```

OPW-5461359

closes odoo#245092

X-original-commit: 12e5194
Signed-off-by: Olivier Colson (oco) <oco@odoo.com>
Signed-off-by: Raj Patani (rapa) <rapa@odoo.com>
This commit fixes an indeterministic sign tour that could run either inside an
iframe or directly in the main page. Since the execution context was
unpredictable, both selectors were added to handle both cases reliably.

runbot error-238443

closes odoo#246393

X-original-commit: 20fc6c6
Signed-off-by: Nisarg Patel (nipl) <nipl@odoo.com>
Since this commit https://github.com/odoo/odoo/pull/242248/changes
flushing inside `test_cant_unlink_message1`, `test_cant_unown_message`
is now required.

runbot/error-237803

closes odoo#246428

X-original-commit: 1b62170
Signed-off-by: Krzysztof Magusiak (krma) <krma@odoo.com>
Signed-off-by: Achraf Ben Azzouz (abz) <abz@odoo.com>
Steps to reproduce:

- Open the website builder and drop a "Cover" snippet on the page.
- In "Background > Image", choose "Position: Repeat pattern" to reveal
the "Width/Height" sub-options.
- Issue: the vertical connector line between the "Filter" and "Position"
options is broken.

After this commit, the gap is removed. Options at the same level are now
properly connected, even when one of them contains sub-options.

task-5155955

closes odoo#246090

X-original-commit: b85689b
Signed-off-by: Romaric Moyeuvre (romo) <romo@odoo.com>
Signed-off-by: Benjamin Vray (bvr) <bvr@odoo.com>
In website_sale product price computation,
https://github.com/odoo/odoo/blob/saas-18.2/addons/website_sale/models/product_product.py#L163
https://github.com/odoo/odoo/blob/saas-18.2/addons/website_sale/models/product_template.py#L490
the target_currency is passed but it is unused parameter.

The product_pricelist price computation logic relies on the currency
https://github.com/odoo/odoo/blob/saas-18.2/addons/product/models/product_pricelist.py#L162
and target_currency is not used anywhere in the pricing flow.

As a result, passing target_currency adds confusion without affecting
the outcome.

This commit replaces target_currency with currency to avoid unused / misleading
parameter.

closes odoo#246291

X-original-commit: 9490854
Signed-off-by: Nikhil Kajavadra (nika) <nika@odoo.com>
@davidtranhp davidtranhp added this to the 19.0 milestone Jan 30, 2026
@davidtranhp davidtranhp changed the title Merged from upstream 260130 01 Merged from upstream 19 260130 01 Jan 30, 2026
@viinbot
Copy link

viinbot commented Jan 30, 2026

@davidtranhp Viindoo Test Suite has failed!

@trungtuan88
Copy link

@viinbot rebuild

@viinbot
Copy link

viinbot commented Jan 31, 2026

@trungtuan88 PR in the queue to wait for rebuild!

@viinbot
Copy link

viinbot commented Jan 31, 2026

@davidtranhp Viindoo Test Suite has failed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.