Skip to content

Merge from upstream 19 20260615 01#1229

Open
royle-vietnam wants to merge 530 commits into
Viindoo:19.0from
royle-vietnam:merge_from_upstream_19_20260615_01
Open

Merge from upstream 19 20260615 01#1229
royle-vietnam wants to merge 530 commits into
Viindoo:19.0from
royle-vietnam:merge_from_upstream_19_20260615_01

Conversation

@royle-vietnam

Copy link
Copy Markdown
Collaborator

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

Syozik and others added 30 commits June 2, 2026 08:12
*: website.
The color filter applied to a video background would disappear after
selecting the block. Commit [1] fixed this problem, but only when the
color filter is a gradient, but it didn't take into account just a plain
color. This commit fixes it.

Steps to reproduce:
1. Enter Edit mode on the website.
2. Drag and drop a snippet (e.g., "Intro").
3. Set a video background for the block and apply a color filter with a
   custom color.
4. Click on another block then click back on the block with the video.
-> The color filter is removed.

[1]: bd105a1

task-6102345

closes odoo#267513

X-original-commit: f36d4d5
Signed-off-by: Francois Georis (fge) <fge@odoo.com>
Signed-off-by: Serhii Rubanskyi (seru) <seru@odoo.com>
Steps to reproduce:
------------------------------------
1. Install `base_automation` and the Sales module
2. Create an automation rule for a sale order as follows:
     * Trigger: State set to Sale order
     * Add a Create Activity action
     * Change User Type to Dynamic
     * Set User Field to Customer > Users
3. Create and confirm a sale order with Admin as the customer

Observation:
------------------------------------
The activity is created in Chatter, but it was not assigned to any user

Issue:
------------------------------------
The condition `self.activity_user_field_name in record` uses the `__contains__`
check which only looks for direct fields on the record's model. A dotted path
like 'partner_id.user_id' is not a field name on the record itself, so the check
evaluated to `False`, skipping the user assignment entirely
https://github.com/odoo/odoo/blob/2bafcebfaba01e46856d6eb2a440ede95b9c0a4a/addons/mail/models/ir_actions_server.py#L378-L379

Solution:
------------------------------------
Use `record.mapped()` as a fallback when the field name is not directly present
on the record. `mapped()` natively supports dotted paths by traversing the
relational chain (e.g. record -> partner_id -> user_id)

opw-6191715

closes odoo#263530

Related: odoo/enterprise#118921
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Why this commit:
toLocaleString() relies on the device's local format instead of the
Odoo-configured format.

Since Odoo already defines a standard date format,the toLocaleString() usages
should be replaced to ensure consistency.

After this commit:
date references consistently use the Odoo-configured date format.

closes odoo#259651

Opw: 6087341
Signed-off-by: Steve Van Essche <svs@odoo.com>
Issue:
- In website forums, the toolbar was either not visible or did not reposition
  correctly after scrolling.

Cause:
- This issue occurred only in forums when an iframe was present. In that case,
  scroll events were not triggered on the window visual viewport, preventing
  toolbar repositioning.

Solution:
- Attached scroll events to the iframe’s visual viewport instead of the window
  visual viewport when an iframe is present.

task-6201171

closes odoo#265221

Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
task-None

closes odoo#267650

Signed-off-by: Wala Gauthier (gawa) <gawa@odoo.com>
…reate

When creating a calendar event by dragging on the calendar view, modifying the end time in the quick-create popover, and then clicking "More Options", the duration shown in the full form is the original drag value instead of the value implied by the user's updated stop.

calendar's makeContextDefaults seeds default_start, default_stop, default_duration, and default_allday from the drag extent. In the quick-create popover, changing stop triggers _compute_duration on that record so its duration becomes correct. On "More Options", goToFullEvent extracts a whitelist of fields from the quick-create record as default_X and merges them with the original drag context.

https://github.com/odoo/odoo/blob/c82341c503ac/addons/calendar/static/src/views/calendar_form/calendar_quick_create.js#L9-L19

duration is missing from that whitelist, so the merged context still carries the stale default_duration from the drag. In the full form, that default is applied to the duration field and _compute_duration does not run because a default was provided for a stored, writable field.

Adding duration to the whitelist forwards the quick-create's recomputed value as default_duration so the full form opens with the correct duration.

Steps to reproduce:
1. Open Calendar, drag to create a 2-hour event (e.g. 10:00-12:00)
2. In the quick-create popover, change the end time to 14:00
3. Click "More Options"
4. Check the Duration field in the full form

=> Duration shows the original drag value (02:00) instead of 04:00

opw-6087449

closes odoo#267628

X-original-commit: dabf0d4
Signed-off-by: Jérémy Hennecart (jeh) <jeh@odoo.com>
Signed-off-by: Mohamed Jemai (mojem) <mojem@odoo.com>
Before this commit:
- Chatter activity display used `summary` to get the display name.
- If `summary` was empty, it fell back to `display_name`.
- However, `_to_store` only stored `summary`.
- As a result, nothing was shown when `summary` was empty, even
though `display_name` was set.

After this commit:
- Added `display_name` to `_to_store` along with `summary`.
- Chatter activity now correctly falls back to `display_name`.
- Users can now see the correct activity label in chatter.

Steps to reproduce:
- Create an activity in chatter
- Remove the default summary if set.
- Observer the title.

closes odoo#267529

X-original-commit: 3dc6cf3
Signed-off-by: Kalpan P Desai (kdes) <kdes@odoo.com>
Steps to reproduce
1. Create a company with Egypt localization, currency EGP
2. On a bank journal, set Outstanding Receipt and Outstanding Payment accounts
3. Register a customer payment so the journal dashboard shows the
   Payments row with a negative amount
4. Switch the user language to Arabic
5. Open the Accounting dashboard

Issue
The Payments amount renders as "LE 5,000.00-" instead of "-5,000.00 LE".
formatCurrency returns the string "-5,000.00 LE". In an Arabic page the
leading "-" has no intrinsic direction, so the browser attaches it to
the surrounding right-to-left Arabic text and visually moves it past
the symbol. Sibling rows on the same dashboard render correctly because
they already wrap the amount in dir="ltr", see
https://github.com/odoo/odoo/blob/d0424f2ffcf99ee59befe288150f1643b3fa0112/addons/account/views/account_journal_dashboard_view.xml#L252

opw-6183749

closes odoo#267582

X-original-commit: c1e61f7
Signed-off-by: Guillaume Vanleynseele (guva) <guva@odoo.com>
Signed-off-by: Amr Ahmed (amahm) <amahm@odoo.com>
… invoice cogs lines

Steps to reproduce:
- Activate Anglo-Saxon accounting
- Create a product with track inventory and an automated inventory valuation product category
- Define MTO on the product
- Add this product to an Analytic Distribution Model (i.e. Legal)

- Create a SO for this product
- Create and confirm the PO related to it, the Analytic account is set on the PO.
- Confirm the reception of the product
- This creates a Stock valuation layer with the Analytic account
- Confirm the SO
- Confirm the delivery of the product
- This creates a Stock valuation layer with the Analytic account too
- Create the Invoice

Issue:
Missing analytic account on the 110300 Stock Interim (Delivered) creating unabalanced analytic accounting

Other:
test_report_invoice_items_anglo_saxon_automatic_valuation
introduced in this PR odoo#205777
checks that in a project's analytic report, the values based
on cogs lines are displayed in the cost section.
With this fix, both cogs lines will have an analytic account
so their impact on the project analytic report will even out.
This made the test fail.
To keep the benefit of this test, we simulate that the user manually
removes the analytic account on some of the cogs lines
(those targetting stock valuation).

opw-6060567

closes odoo#266617

X-original-commit: 89622cb
Signed-off-by: Pierre-Louis Hance (plha) <plha@odoo.com>
If a list view contains a field (column) with binary widget, on click it
will download the content of the field. This is the intended behavior
but at the same time it will, by default, open the record of which it is
part, which is strange since the user only wants to download the
content.

With this PR we make use of .stop on the t-on-click to detach the
execution of the function from the opening of the record.

We also add unit tests for this.

closes odoo#267197

Task: 6260266
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Steps to reproduce:
1- Install the Attendance app
2- Enable PIN Identification in setting
3- Go to Admin user (who is also an employee) and remove their admin access on the Employees field and save.

Issue:
`AccessError: You do not have enough rights to access the field "pin" on Employee (hr.employee).`

Expected behavior:
User can change their access rights without getting AccessError

Why this happens:
The addition of the Employee PIN to the Preferences tab in v19.0 (commit edc6562) causes this error. During web_save,
a read is triggered for all fields in the view. Since the user just removed their own HR rights, they no longer have
access to the PIN field. While the PIN was moved in v19.1 (commit a2e785b), it remains in v19.0.

Fix:
- Removing the field from the xml file was not enough as it introducted another error:
`AccessError: You do not have enough rights to access the field "version_id" on Employee (hr.employee).`
- Commit 5024fc7 changes field `work_location_id` to be editable. This field is related to an `hr.employee` field which
depends on `version_id`. Saving now causes this field to be read through this chain, which causes an an implicit access.
- Set `related_sudo=True` to allow the user to read their own employee data during the save

Note:
This `version_id` error doesn't exist from v19.1 upwards due to the refactor made in  commit 9605045.

opw-6112646

closes odoo#262053

Signed-off-by: Waleed Elgamal (waelg) <waelg@odoo.com>
The reverse charge group taxes "Reverse Charge - SRRC + TXRC-TS" and
"... + TXRC-ESS" returned a wrong GST amount on bills: a S$10,000 line
showed -S$900 GST instead of S$0.

A reverse charge group pairs the -9% SRRC child with a +9% TXRC child,
so the GST nets to zero. The TXRC-TS and TXRC-ESS children shipped
inactive, while their siblings TXRC-N33 and TXRC-RE shipped active.
Since children_tax_ids is a many2many onto account.tax (which has an
active field), the inactive children are filtered out of the group, so
only the -9% SRRC remained and the GST no longer netted to zero.

Activate the two children in the tax template so the groups aggregate
both legs. A migration reactivates them on existing SG databases, since
the template data is not re-applied to taxes already loaded.

opw-6199248

closes odoo#267670

Signed-off-by: Josse Colpaert (jco) <jco@odoo.com>
When we import a UBL file, we call the `_import_retrieve_tax`
method to fetch taxes to indicate on lines.

During the process, we use cache to avoid performing the search
a second time if a new line is the same as a previous one.

https://github.com/odoo/odoo/blame/d0424f2ffcf99ee59befe288150f1643b3fa0112/addons/account/models/account_tax.py#L4459-L4462

The cache_key used is defined as follows: {line's invoice,
line's name, line's partner}.
This implies that if two lines from the same invoice share the
same name and partner, the same tax will automatically be
used even if different taxes were indicated in the file.

This is not desirable as we should match what is indicated
in the XML file imported.

opw-6226166

closes odoo#267559

X-original-commit: f726393
Signed-off-by: Laurent Smet (las) <las@odoo.com>
Why this commit:

There are two instances in version 17.0 where dates use
toLocaleString(), which relies on the device's local format instead of
the Odoo-configured format.

Since Odoo already defines a standard date format, all
toLocaleString() usages should be replaced to ensure consistency.

Starting from version 17.0, cash in/out receipts and the sales report
use the local device time format.

This commit updates those references and aligns them with the
Odoo-configured date format. Other references will be updated during
forward-porting.

After this commit:

All date references consistently use the Odoo-configured date format.

closes odoo#266770

X-original-commit: 697aba3
Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Signed-off-by: Kalpan P Desai (kdes) <kdes@odoo.com>
Visitors in livechat can currently trigger partner mention suggestions
using the @ delimiter. However, visitors can only mention themselves
or odoobot, which does not provide any meaningful functionality and
adds unnecessary noise to the composer suggestions.

This change disables the @ delimiter for visitors in livechat threads,
preventing partner mention suggestions from appearing while keeping the
feature available for internal users.

Task-5119068

closes odoo#267566

X-original-commit: 8320ea93eecdc4319c96638f089d0c83199f2d37
Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
Signed-off-by: Ayush Kumar Singh (akus) <akus@odoo.com>
1. Remove the possibility to create link tracker with an empty code.
Empty code tracker do not work, but still appear in the tracker list.
Only accept alphanumerical chars in the tracker code.

2. Set the target link input as disabled after generating the tracker,
since editing the target link at this point would have no impact.

task-4531974

closes odoo#266987

X-original-commit: 3fb72af
Signed-off-by: Francois Georis (fge) <fge@odoo.com>
Signed-off-by: Romaric Moyeuvre (romo) <romo@odoo.com>
In mobile view, the payment link wizard shows a copy button with a long
label.

Since the button keeps its intrinsic width, it may overflow its container
and appear cut off.

Make this payment wizard copy button take the available width to avoid the
overflow.

TT58871

closes odoo#267452

X-original-commit: 0a71768
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Description of the issue:
- MoveNode restores the selection at the container end position
- After moving a table, the cursor ends outside the table body

After this commit:
- Preserve the selection if it was inside the moved node
- Otherwise place the cursor at the start of the moved node

Steps to reproduce:
- Create a table in the editor
- Move the table using Movenode
- Drop the table and check the cursor position
- The cursor ends outside the moved table body
- Select some text in a paragraph
- Move that paragraph using Movenode
- The selection is placed at the end of the moved node

task-6215743

closes odoo#267549

X-original-commit: 8744200
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Samit Bharatbhai Bhadiyadra (sbbh) <sbbh@odoo.com>
This commit will affect all certification modules for the POS
(pos_blackbox_be, l10n_se_pos, l10n_de_pos_res_cert)

Inside the base `handleDecreaseLine` we match all the lines which
have the same product_id and compute the new quantity based on those.
At the end we create a new line with the decreased quantity. This
method is called when `disallowLineQuantityChange()` returns `false`,
so when either of `pos_blackbox_be`, `l10n_se_pos` or
`l10_de_pos_res_cert` are installed.

The problem is that different combos will still have the same
product_id and total_excluded_currency, so the
`current_saved_quantity` adds the other unrelated combos together and
tries to remove from the total of all the combos with the same
parent.

This commit will keep the decrease line for an order in the uiState. So
instead of iterating over all the lines in the order and matching lines
which have the same product_id we always keep track of the original line
and the matching decrease line for that line.

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

closes odoo#262744

Signed-off-by: Manu Vaillant (manv) <manv@odoo.com>
Steps to Reproduce:

1. Configure the website default language different from the user’s current
language.
2. Go to Website → Site → Pages.
3. Duplicate an existing page.
4. Edit the duplicated page and save the changes.
5. Duplicate the edited page again.
6. Observe that the newly duplicated page is generated from the original page
content instead of the updated duplicated page.

Issue:

When duplicating a website page, the website default language was not passed in
the context. As a result, the duplication was performed using the active user
language.

The root cause is that `copy()` does not simply duplicate the existing `arch_db`
translation dictionary. Instead, it copies the field value in the current
language and then rebuilds all translations through `copy_translations()`.

This behavior becomes problematic when `delayed translations` are involved.
After a page is modified in a non-default language, the latest changes may
be stored in a delayed translation entry (`_{lang}`) while the regular translation
value remains unchanged. During the copy process, these delayed translation
entries are intentionally discarded because they are considered temporary data
and are not treated as valid language translations.

As a result, when the page is duplicated from a non-default language, `copy()`
rebuilds the translations using an outdated translation value instead of the
most recent content stored in the delayed translation. The newly
duplicated page therefore does not accurately reflect the current state of
the source page.

Solution:

The fix enables `check_translation=True` during page duplication so that
the copy operation uses the latest translation state, including delayed
translations when available. This ensures duplicated pages are generated
from the most recent version of the source page and keeps translated
content consistent across languages.

OPW-5914281

closes odoo#264656

Signed-off-by: Sébastien Blondiau (blse) <blse@odoo.com>
A message's author is identified by one of two fields depending on its
model: `author_id` (for partners) or `author_guest_id` (for guests).
Previously in `changeThread`, the value of `thread.effectiveSelf` (which
can be either a Partner or a Guest) was provided as the `author_id`
regardless of its actual model.

This commit explicitly uses `store.self_partner` as the `author_id` and
`store.self_guest` as the `author_guest_id` to resolve the occasional
mismatch.

closes odoo#267464

Signed-off-by: Louis Wicket (wil) <wil@odoo.com>
Steps to reproduce
==================

- Install l10n_din5008,l10n_de
- Use a german company
- Go to settings
- Enable "Show Position Column in Reports"
- Go to Invoicing > Sales > New
- Add a new section
- Click on the three dots
- Check "Hide composition"
- Add a new line with a product
- Confirm the Journal Entry
- Print the Invoice PDF

=> Every column after the description is offset by one

opw-5427590

closes odoo#261527

Signed-off-by: Hubert Van De Walle <huvw@odoo.com>
Scenario:

- insert Instagram Page snippet
- using iOS chrome browser (reproduced in iOS 26.3, google chrome 146)
  visit that page logged in as a internal user or in ?debug=assets (so
  traceback are shown)

Result: 3 tracebacks errors are shown with error "Uncaught Promise >
JSON Parse error: Unexpeced identifier "object".

Cause: probably since this change:

https://chromium.googlesource.com/chromium/src/+/9629a16a7ab0b91c59ecaa9fc8934db3d6c83ba3%5E%21/

chrome on iOS is sending message with this object as data:

{ "command": "registerAsChildFrameAck", "remoteFrameId": "d905013d…" }

but the instagram code is expecting a stringified JSON.

Fix: ignore message data that are object.

opw-5930717

closes odoo#267093

X-original-commit: 28972ea
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
When a mass mailing block uses a `bg-o-color-N` theme color class, the mailing's `body_arch` stores the class and `convert_inline` correctly inlines the resolved color into `body_html`, matching the website palette at save time. The class also stays on the element in `body_html`. The stylesheet rule that gives `bg-o-color-N` its color is declared with `!important`. When the website palette is later rebuilt (any change to the primary colors), the new `bg-o-color-N` rule wins over the inline color whenever `body_html` is rendered. So an already-sent mailing reopened in the backend shows the new palette's color instead of the one that was picked, and resaving the mailing bakes that new color into `body_html`.

`classToStyle` already does the right thing for the property value. What was missing is dropping the class itself from `body_html` once its style has been inlined, so no future `!important` palette rule can override the inline color. `body_arch` keeps the class, so the editor preview stays theme-aware while editing, but `body_html` is now stable across palette rebuilds.

Steps to reproduce:
1. Open Email Marketing and create a new mailing using the Welcome Message template
2. Select a content block, open Customize, set the background to the 5th theme color
3. Save the mailing
4. Open the Website editor and change the 5th primary color to a different value
5. Reopen the saved mailing in the backend

=> the block's rendered background follows the new website color instead of the one picked at design time

Ticket [link](https://www.odoo.com/odoo/project.task/5892350)
opw-5892350

closes odoo#267570

X-original-commit: 2cb42f7
Signed-off-by: Damien Abeloos (abd) <abd@odoo.com>
Signed-off-by: Mohamed Jemai (mojem) <mojem@odoo.com>
The purchase_order_id column in invoice lines was hidden for vendor credit notes (in_refund), while it was visible for vendor invoices (in_invoice). This prevented users from identifying which purchase order each line belonged to when a credit note was linked to one or more POs.

Include 'in_refund' in the column_invisible condition so the purchase order column is also available on vendor credit note lines.

closes odoo#267316

Signed-off-by: William Henrotin (whe) <whe@odoo.com>
When a PL supplier has no VAT and a PL company tries to pay him a
bill above 15.000 PLN, there is a traceback.
The reason is that there was no check for partner with no VAT, a
verification was created every time the field was compute.

closes odoo#267834

X-original-commit: 441d1d9
Signed-off-by: William André (wan) <wan@odoo.com>
Step to reproduce:
1. Install `website_link`
2. Open Website > Site > Link Tracker
3. Type in text into any pre-defined field (Campaign, Medium, Source)
4. Observe that the input is not showing all the typed characters

Issue:
- It's randomly removing characters, for example, type "1234567890" and observe

Cause:
- SelectMenu updates its internal searchValue only inside the debounced
  onInput handler `debouncedOnInput`. When an autocomplete callback reloads
  choices before that debounce fires, the component rerenders with a stale searchValue
  and writes that outdated value back into the controlled input, overwriting newer
  characters already typed by the user.

Solution:
- Update searchValue immediately on every raw input event and keep only the
  search callback debounced.
- Also reset searchValue to null when a required single-select is blurred
  while empty, so the input falls back to the selected choice label instead
  of staying visually cleared.

opw-6000540

closes odoo#255819

Signed-off-by: Piyush Sharma (pish) <pish@odoo.com>
Currently, it is possible to confirm a manufacturing order linked
to a project without an analytic distribution, even when a plan is
set as mandatory for Manufacturing Orders.

Fix:

On action_confirm, check whether the related project has mandatory
plans set and, if so, ensure they are filled — raising a
ValidationError otherwise.

task-id 6250034

closes odoo#266943

Signed-off-by: William André (wan) <wan@odoo.com>
Lines 29 to 34 in the tax report should be negated

opw-5985774

closes odoo#259147

Signed-off-by: de Wouters de Bouchout Jean-Benoît (jbw) <jbw@odoo.com>
MaximeNoirhomme229 and others added 24 commits June 12, 2026 13:00
…lti-step receipts

**Issue**
Reducing the PO quantity after performing a partial receipt, in multi-step receipts warehouse
can incorrectly update the remaining receipt quantity.

**Steps to reproduce**
- Setup 2-route receipt warehouse (Inventory > Configuration > Warehouse Management > Warehouses)
- Create a PO for 35 units and confirm it
- Click on receive products, set received quantity to 10 and create a backorder
- Validate the next transfer
- Go back to the PO and change the quantity to 20
- Check the receipt demand
-> The backorder picking demand become 35 instead of 10

**Cause**
Updating the quantity of a purchase order line, also updates the related picking:
https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L120
It updates the picking associated to the backorder since the other one is done:
https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L185-L187
https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L197
This ultimately calls:
https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L228
To compute the new demand for the picking, it retrieves the `move_dest`:
https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L240
To compute `qty_to_push`:
https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L247-L249
However, since we are in a 2-route receipt setup, `move_dest` is the move from Input to stock for the done picking.
Thus, `qty_to_push` is `20 - 10 = 10` instead of `20 - 35 = -15`

**Solution**
The previous logic assumes a pull flow, where downstream (move_dest_ids) quantities are always up-to-date and can be used as the source of truth to recompute demand.
In push flows (e.g., multi-step receipts), this assumption does not hold.
To fix this, we instead base the computation on the quantity of the current moves (qty) if nothing has to be attached.

**Additional information**
Known limitation: this does not address inconsistencies in return flows. When there're returns, units
define in the pol and the one define in the sum of the picking can diverge, thus this pr won't fix that.

opw-5512172

closes odoo#269514

X-original-commit: b84b62d
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Steps to reproduce:

- Configure user A to receive inbox notifications.
- As user B, invite user A to follow a record with Notify recipients enabled.
- Open the inbox of user A.

The Invitation to follow notification is not displayed in the inbox when no
additional comment is provided. This happens because the notification body is
empty unless extra comments are added.

This commit fixes the issue by displaying only the subject when the body is
empty.

Task-5485727

closes odoo#269511

X-original-commit: 0238e0e
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Signed-off-by: Akshay Thakur (akth) <akth@odoo.com>
When importing a Peppol/UBL vendor bill containing a line with a 100%
discount, the line was created in Odoo with quantity=1 and
discount of 100*original_qty, instead of the
expected quantity=qty_original and discount=100%.

This happened because the line-level branching in
`_import_ubl_invoice_line_add_price_unit_quantity_discount` relied on
the truthiness of `line_extension_amount` to detect whether the
`LineExtensionAmount` node was present in the XML. a line with
a genuine `<cbc:LineExtensionAmount>0</...>` was indistinguishable
from a line where the node was missing, and fell
through to the fallback branch intended for incomplete XML. That
fallback reconstructs the quantity from `<cbc:BaseQuantity>`,
ignoring `<cbc:InvoicedQuantity>`, and then computes the
discount percentage against the wrong denominator.

a `LineExtensionAmount` of 0 is the only legal way to
express a fully-discounted line, so this case must be distinguished
from the node being absent.

the fix is simply checking if the line exist not if its True

opw-6176349

closes odoo#269148

X-original-commit: 9ab1873
Signed-off-by: Ricardo Gomes Rodrigues (rigr) <rigr@odoo.com>
Signed-off-by: Laurent Smet (las) <las@odoo.com>
When we download the ETA invoice PDF, a JSONDecoderError
can happen when calling the json() method on the request.
This error is properly caught by Odoo :

https://github.com/odoo/odoo/blame/7a9a340e0dbac470c4bea3f8ce8a32e55f3e82e6/addons/l10n_eg_edi_eta/models/account_edi_format.py#L58-L60

However, the following commit introduced a monkeypatch
to handle errors when the simplejson library is
installed : 2435fe7

If we meet the conditions, the original error is replaced
by a json.JSONDecodeError which is not caught during the
previous process.

We propose to add this error to the catch block.

This modification was inspired by the commit
d483dac.

opw-6266862

closes odoo#269629

X-original-commit: 28ee5d3
Signed-off-by: Maximilien La Barre (malb) <malb@odoo.com>
**Steps to reproduce**
- Use a french company with `l10n_fr_hr_holidays` installed
- Change the duration type of the time off type set as the "Company
Paid Time Off Type" in the French Time Off Localization settings
to "Half-Day"
- Company Working Schedule:
	- Attendance on a day from 10 to 19, Day Period: Full Day
- Part-time employee Working Schedule:
	- Attendance on the same day from 11 to 12, Day Period: Morning
	- Attendance on the same day from 13 to 19, Day Period: Afternoon
- Create a full day time off for the part time employee on that day, using
the time off type set as the "Company Paid Time Off Type" (start am, end pm)

-> Excepted: time off duration is 1 day
-> Actual: time off duration is 0.89 day

**Change**
Now that `request_unit_half` of a leave is a simple related to the `request_unit`
of the leave type, it becomes important to not rely on a call to `_get_durations`
using the company's calendar to compute the leave's duration, as it may not be
fully accurate when the company's working hours and employee's working hours are
not aligned.
Continuation of 05e71eb

`_get_fr_date_from_to` is also adapted to take into account multi-day leaves
ending in the morning while the employee works in the afternoon (in which case
it should not be extended in case the employee doesn't work the next day).

opw-6000011

closes odoo#253059

Signed-off-by: Bertrand Dossogne (bedo) <bedo@odoo.com>
Before this commit, user needed to manually refresh de kyc status,
with this commit, the status will be changed when receiving the
notification from IAP

task-6271596

closes odoo#269732

X-original-commit: 4f1cf66
Signed-off-by: Florian Gilbert (flg) <flg@odoo.com>
…ransactions

Steps to reproduce
1. Configure a Polish company with KSeF enabled.
2. Create a customer invoice using a tax tagged with K_21 (0% EU G,
   intra-Community supply of goods), K_12 (0% EU S, services taxed in the
   buyer's EU country) or Triangular Sale.
3. Send the invoice to KSeF and download the generated FA(3) XML.

Issue
The Podmiot1 (seller) block in the rendered FA(3) XML omits the
PrefiksPodatnika element, see https://github.com/odoo/odoo/blob/89219a843545d8bb0cad6ea806a1167cee6289da/addons/l10n_pl_edi/data/fa3_template.xml#L34-L42.
According to the official Ministry of Finance documentation
(https://ksef.podatki.gov.pl/media/4u1bmhx4/information-sheet-on-the-fa-3-logical-structure.pdf,
page 11), this conditional field must carry the value "PL" when the
invoice documents:
- the intra-Community supply of goods,
- the provision of services referred to in Article 100 sec. 1 item 1 of
  the Act for EU VAT taxpayers,
- the supply carried out under a simplified triangular transaction by
  the second taxpayer (Article 135 sec. 1 item 4 (b) and (c)).
The XSD marks the element as optional (minOccurs="0", fixed="PL") so
KSeF accepts the XML, but the seller's tax reporting is still legally
non-compliant for the three cases above, and the field is missing from
the KSeF PDF viewer rendering.

opw-6213178

closes odoo#269713

X-original-commit: 08f0c14
Signed-off-by: Amr Ahmed (amahm) <amahm@odoo.com>
Steps:
* Create an extra-hours attendance for an employee that has overtime ruleset
OR
* Create an extra-hours attendance for an employee that has no overtime ruleset

Issue:
* The overtime details in the attendance view visibility condition was flipped

Solution:
* Reverse the visibility condition of the XML element

closes odoo#269744

Task: 6295710
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
We now allow formatting and parsing quantity on an
orderline when using the decrease quantity popup.
This allows overriding from other modules to add
contraints (e.g. `pos_blackbox_be` prevents from
setting negative quantities).

see odoo/enterprise#119702
task-5942777

closes odoo#269487

Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Co-authored-by: Stephane Vanmeerhaeghe (stva) <stva@odoo.com>
Replenishing the stock from an orderpoint will look for a purchase order
line having the same orderpoint_id in order to update the quantity
instead of creating a new one. The issue is manual orderpoint are
deleted right after the replenishment.
Replenishing two times the same product will always create a new
purchase order line.

This commit makes the orderpoint_id is pass in the procurement values
only in case of `trigger == auto` orderpoint.

closes odoo#269725

Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
The `tax_ids` field on `pos.order.line` is defined with `readonly=True`.
When editing a POS order from the backend (e.g. during a return/exchange
flow), the `_onchange_product_id` method correctly sets `tax_ids` from
the product, and the computed `tax_ids_after_fiscal_position` displays
the mapped taxes in the UI. However, because `tax_ids` is readonly, the
web client does not include it in the save payload. As a result, the
taxes are silently dropped on save and `tax_ids_after_fiscal_position`
recomputes to empty.

Steps to reproduce:
1. Create and pay a POS order with a product that has taxes
2. Go to the backend (Point of Sale > Orders) and open that order
3. Initiate a return for the order
4. In the return order, add a new product (exchange scenario)
5. Observe that taxes are correctly shown on the new line
6. Click Save
7. The taxes disappear from the order line

The fix adds `force_save="1"` to the `tax_ids` field in both the list
and form views of `pos.order.line`, consistent with how `price_subtotal`
and `price_subtotal_incl` are already handled in the same views.

closes odoo#261672

X-original-commit: 7b37d84
Signed-off-by: Adrien Guilliams (adgu) <adgu@odoo.com>
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
The quantity on hand for a main company with branches is calculated to be the the sum of all its child companies + its own quantities.  `_run_fifo_get_stack()` doesn't include the child companies in the `moves_domain`, so it is unable to create a FIFO stack for moves from a child. This leaves extra quantity unaccounted for, which defaults to the standard_price.
When multiple companies are selected, the displayed quantity on hand for a product is calculated as the sum of all selected companies. However, the moves domain only looks at the main selected company instead of all selected companies, leading to an incorrectly calculated standard price when using FIFO. This is more apparent on lot-valuated products because their standard price is recalculated every time the field is accessed.

PR odoo#258199

Signed-off-by: Stéphane Diez (snd) <snd@odoo.com>
We iniatially though the 2FA was needed by the administration.
But in fact, it was not. So we will remove it.

Commit of the 2FA:
odoo@7535ce7

Commit of the reregister also changed a bit that
odoo@22ba629

no task id

closes odoo#269862

X-original-commit: 58ec761
Signed-off-by: Sven Führ (svfu) <svfu@odoo.com>
**Description of the issue/feature this PR addresses:**
The method _get_ab_testing_siblings_mailings currently scans all mailings in a campaign to apply a simple filter, which becomes expensive on databases with many large mailings.

**Steps to reproduce bug:**
1) Run this script to get [enough sufficiently large mailings](https://gist.github.com/brcut-odoo/bb0d6d334bfe110afe16021d17d1b443)
2) Open one of the mailings and recieve a crash from the _get_ab_testing_siblings_mailings

**Current behavior before PR**
https://drive.google.com/file/d/19xftvzsGSQ9DxB67LNiLkKApzsD192ax/view?usp=drive_link

**Current behavior after PR**
https://drive.google.com/file/d/1apTJ0rWTKaATYa67ZmmN-7bKhrw4KuTx/view?usp=drive_link

opw-6245908

closes odoo#269865

X-original-commit: 4a52702
Signed-off-by: Damien Abeloos (abd) <abd@odoo.com>
Signed-off-by: Brett Cutler (brcut) <brcut@odoo.com>
Steps to reproduce:
- Start from a database where the eCommerce app is not installed.
- Open the website configurator.
- In the first step, choose "I want an eCommerce".
- In the Pages and Features step, select all Pages.
- Select a theme that adds an eCommerce category snippet, for example
  Treehouse.
- Build the website.
=> During the first `configurator_apply`, `website_sale` is installed
   after the theme and the configured menu items are already created.
=> The homepage rendering then needs a `website_sale` configurator
   snippet template requested by the theme, but it was not generated
   during that first call.
=> The client retries `configurator_apply`. It now succeeds because
   `website_sale` is fully installed, but page and menu creation runs
   again and duplicates the menu items.

Before this commit, primary snippet template generation only read the
manifest of the module being generated. When `website_sale` was
installed from the first `configurator_apply`, it did not see addon
snippets declared by the already installed theme. The first call could
therefore fail while rendering the homepage after pages and menus were
created.

After this commit, generation also reads installed theme addon snippets
that target the module being generated. The `website_sale` configurator
templates requested by the selected theme are created before the first
homepage rendering, so `configurator_apply` does not retry after
creating menu items.

task-5973739

closes odoo#261022

Signed-off-by: Soukéina Bojabza (sobo) <sobo@odoo.com>
Accounting users can access POS closing journal entries even when they
do not have Point of Sale access rights.

The PDP POS helper checked POS session/order links directly while
computing e-reporting fields on account moves. This could raise an
access error on `pos.session` for accounting users without POS rights.

closes odoo#269961

X-original-commit: 42bb359
Signed-off-by: de Wouters de Bouchout Jean-Benoît (jbw) <jbw@odoo.com>
Signed-off-by: Jérémy Bazin (baje) <baje@odoo.com>
…ring rule

Version:
----------
- 18.0+

Steps to reproduce:
-----------------------
1- Install the `purchase` and `stock` modules.
2- Create a storable product with tracking enabled.
Set the Cost (standard price) to 50.
3- Open the product form and go to the Purchase tab.
   * Add a vendor with:
   * Quantity: 2
   * Price: 10
4- Create a Reordering Rule for this product:
   * Route: Buy
   * Trigger: Manual
   * To Order Quantity: 2
5- Click on the Order button to generate a purchase order.
6- Open the generated Purchase Order and verify the Unit Price
on the purchase order line.
7- Open the same product and go to the Purchase tab.
In the existing vendor line, add an End Date lower than today so
the vendor pricelist becomes expired.
8- Reopen the same reordering rule.
Change To Order Quantity to 1.
9- Click on the Order button again.

Issue:
-----
The generated purchase order line gets a Unit Price of 0
instead of keeping the product cost or a valid fallback price.

Root Cause:
--------------
- When clicking on `Order`, it triggers `action_replenish`, which calls the
procurement flow:
`_procure_orderpoint_confirm` → `run` → `run` → `_run_buy`.

- Inside `_run_buy`, the system checks whether a `purchase.order.line`
already exists. In this case, the PO line exists, so it calls
 `_update_purchase_order_line`.

https://github.com/odoo/odoo/blob/47ef8b75d0c90001b9989a95f09b962c5b286c53/addons/purchase_stock/models/stock_rule.py#L137

- In `_update_purchase_order_line`, the system tries to fetch a seller using
 `_select_seller`,
- which internally calls `_get_filtered_sellers`.
https://github.com/odoo/odoo/blob/47ef8b75d0c90001b9989a95f09b962c5b286c53/addons/product/models/product_product.py#L759

- However, if the seller's `end_date` is less than `today`,
 `_get_filtered_sellers` skips that seller and returns no valid seller.

https://github.com/odoo/odoo/blob/47ef8b75d0c90001b9989a95f09b962c5b286c53/addons/product/models/product_product.py#L731-L733

- As a result, `_update_purchase_order_line` does not find any seller and falls
back to setting `price_unit` to `0`, causing the purchase order line price to
be updated incorrectly.

https://github.com/odoo/odoo/blob/47ef8b75d0c90001b9989a95f09b962c5b286c53/addons/purchase_stock/models/stock_rule.py#L259

opw-6117461

closes odoo#269971

X-original-commit: c7f5e82
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Pawan Kumar Gupta (pkgu) <pkgu@odoo.com>
…d line description

1) Previously, we were supposing that only one <cbc:Description> tag could
be found on InvoiceLine item.
After checking the UBL XSD, I found we could have multiple Description tags
for one item.

2) The import order of <cbc:Name> and <cbc:Description> on the invoice line
now has been changed to be more accurate and prevent loss of information.
The export has been adapted to this change too. Now, we export the actual description
written by the user.

task-6153895

closes odoo#261949

Signed-off-by: Jugurtha Gaci (jugac) <jugac@odoo.com>
…emo mode

**Steps to reproduce:**
* Install `l10n_fr_pdp` module.
* Activate French eInvoicing in demo mode and enable
  "Participate in the pilot phase".
* Create an invoice for a French client and send it via the French E-Invoicing.

**Observed behavior:**
* A traceback is raised with `KeyError: 'messages'` in
  `_send_peppol_documents`.

**Cause:**
* `DEMO_ENDPOINTS['send_document']` in `l10n_fr_pdp` was returning
  `{'ppf_messages': [...]}`, missing the `messages` key that
  `_send_peppol_documents` in `account_peppol` unconditionally reads for flow 2.
* Additionally, the demo mock was returning `uid` instead of `uuid` inside
  `ppf_messages`, which does not match the real IAP response structure.
* Finally, in `l10n_fr_pdp/models/pdp_flow.py`, after successfully sending a
  flow 10 batch, the system attempted to log `response['uid']` despite the
  `_send_to_proxy()` method returning `uuid`. This caused a crash during the
  chatter logging step.

**Fix:**
* Fix `DEMO_ENDPOINTS['send_document']` to return
  `{'messages': [...]}` with `message_uuid` entries, matching the
  real IAP response structure for flow 2.
* Update `ppf_messages` in the demo mock to return `uuid` instead of `uid`.
* Fix `pdp_flow.py` to correctly access `response['uuid']` instead of
  `response['uid']` when posting the success message.

opw-6289723

closes odoo#269930

X-original-commit: 62f1f4e
Signed-off-by: Wala Gauthier (gawa) <gawa@odoo.com>
Signed-off-by: Raj Bhuva (bhra) <bhra@odoo.com>
This fix removes the condition that moves must be sent to be part of a flow 10 and correct copy-pasted zip by country_id in address check.

closes odoo#269984

X-original-commit: 4a0a438
Signed-off-by: de Wouters de Bouchout Jean-Benoît (jbw) <jbw@odoo.com>
@viinbot

viinbot commented Jun 15, 2026

Copy link
Copy Markdown

@royle-vietnam 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.