Skip to content

Syncing from upstream odoo/odoo (saas-19.2)#39650

Open
bt-admin wants to merge 231 commits intobrain-tec:saas-19.2from
odoo:saas-19.2
Open

Syncing from upstream odoo/odoo (saas-19.2)#39650
bt-admin wants to merge 231 commits intobrain-tec:saas-19.2from
odoo:saas-19.2

Conversation

@bt-admin
Copy link
Copy Markdown
Collaborator

bt_gitbot

chgo-odoo and others added 17 commits March 21, 2026 05:37
This commit removes the `.` added in the classname in order to ensure
the classname used within the selector is the right one.

task-6047633

closes #254953

X-original-commit: aa3d073
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Signed-off-by: Chrysanthe Gomrée (chgo) <chgo@odoo.com>
The bubble layout was changed in commit[1] but the logo size is too big,
the goal is to reduce the vertical space the logo and spacing take by
using the small version of the logo which is significant for vertical
logos.

task-5951770
[1]: 8eb61a2

closes #254960

X-original-commit: d66de21
Related: odoo/enterprise#111383
Signed-off-by: Olivier Colson (oco) <oco@odoo.com>
Signed-off-by: Mathieu Notté (mano) <mano@odoo.com>
Refund orders were reporting incorrect values because the sign was
derived from `is_refund`, which is not reliable. Replace with
`SIGN(qty) * SIGN(price_unit) * ABS(...)` so the sign is computed
directly from the line data in both `pos_order_report` and `sale.report`.

opw-6017438

closes #254782

X-original-commit: cb9bd14
Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
Steps to reproduce:
	- Create a xlsx sheet with some fsm_tasks values with recurrence values
	- Import the sheet to Field Service > Tasks
	- Navigate to the created tasks
	- Notice the recurrence values is the default ones not the ones in the imported sheet

Cause:
If we are importing records without recurrence_id value we will set
the recurrence fields' values to the default values while we might
already have values for those fields

Fix:
Check if we have values for recurrence fields we don't set the
defaults and let the create method create the project.task.recurrence
record and set the recurrence_id

opw-5925546

closes #255036

X-original-commit: 425065d
Signed-off-by: Youssef Bashandy (yoba) <yoba@odoo.com>
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
Currently the initial demand click will open the account.move view
without filter. So you don't know what is related to the initial balance
or not.

This commit updates the action to use a domain on the accounts used by
inventory valuation. Also it shows the account.move.line instead.

It also add a date if needed to be concistent with the reprot.

closes #255010

X-original-commit: 00e41f9
Signed-off-by: Tiffany Chang (tic) <tic@odoo.com>
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Currently, the `l10n_ca_pst` field label and help message implies that
it is only for the PST number; however, in Quebec the proper name for
such a value is the Quebec Sales Tax or (QST) registration number. As
such, by updating the help message we clarify to the users that both PST
and QST should be placed here.

task-5866356

closes #255048

X-original-commit: 083b38c
Signed-off-by: Joren Van Onder (jov) <jov@odoo.com>
Signed-off-by: Andrew Gavgavian (andg) <andg@odoo.com>
Since [1], the warning to inform the user that a snippet is outdated has been removed.

After this commit, if a builder action fail on outdated snippets (mismatched vcss/vxml/vjs
versions), we show a warning notification instead of propagating the error. The notification
informs the user that an error occurred on an outdated snippet, and prompts them to drag
a new version of the snippet.

This is achieved by wrapping try-catch blocks around all builder action lifecycle methods
(apply, clean, load, getValue, isApplied) and implementing an error handling method that
detects if the snippet is outdated.

task-4297808

[1]: #224382

closes #255062

X-original-commit: be8d00f
Signed-off-by: Francois Georis (fge) <fge@odoo.com>
Before this commit, when page loading in the webclient while not
using Discuss (Discuss app closed, no chat window and bubble), the
messaging menu counter could be wrong.

Steps to reproduce:
- Open Discuss app
- Make a new channel
- Post a message in this channel
- Mark conversation as unread
- Open Advanced settings of this channel
- Archive this channel
- Go back to home menu
- (make sure no chat windows and chat bubbles are open)
- Reload the page

=> The counter of messaging menu should be over-estimated by 1.
For example if all conversations are read, counter is 1 instead of 0.
Opening the messaging menu refreshes the counter to correct value 0.

This happens because when using Discuss, the counter is deduced from
all channels that have been fetched and for which current user is a
member of these channels. Implicitly, archived channels are filtered
out.

However when not using discuss, the channels as member have not been
fetched, and instead an estimation of the counter is fetched from
server. This counter was computed on channel members that have
unread messages. When a channel is archived, that doesn't mean the
members are archived too. In the steps listed above, the self member
is still active. As a result, the self member of this archived
channel had contribution to the counter estimation, hence the value
of 1 instead of 0.

This commit fixes the issue by keeping computation on channel members
but it checks also that the channel is active, as the resulting
counter is based on active channels.

This commit also fixed a similar issue where the counter was wrongly
taking muted channels into account on the global counter when not
using Discuss. This lead to a similar problem on non-archived but
muted channels were they contribute in the estimated counter but not
in the actual in-use counter.

Task-6014754

closes #255119

X-original-commit: 87df5fb
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This PR completes the changes introduced in:
2cbb735

Issue:
A <div> was added to prevent click propagation in the FileUploader,
but it introduced unintended extra spacing in several parts of the UI

Cause:
The added <div> affected the layout by taking up space where it should not

Fix:
A specific class is added to neutralize the layout impact of this element
while preserving the click propagation behavior

Steps to reproduce:
- Install `hr'
- Create a new Employee
- Go in Private Information > Work Permit
- Upload a file
Before the fix, the edition's buttons are in another line

opw-5918379

closes #255156

X-original-commit: c001628
Signed-off-by: Hubert Van De Walle <huvw@odoo.com>
Signed-off-by: Corentin Heinix (cohe) <cohe@odoo.com>
Rule information:
https://docs.peppol.eu/poacc/billing/3.0/2025-Q4/rules/ubl-peppol/SE-R-005/

OPW-5881918

closes #255161

X-original-commit: 96460f5
Signed-off-by: Wala Gauthier (gawa) <gawa@odoo.com>
Signed-off-by: Victor Miguel Armenta Carrillo (vmac) <vmac@odoo.com>
The aim of this commit is to ensure the feature doesn't get silently
broken in case some underlying code gets reworked.

closes #255196

Task-id: None
X-original-commit: 77c08ac
Signed-off-by: William André (wan) <wan@odoo.com>
Signed-off-by: Brice Bartoletti (bib) <bib@odoo.com>
some debugging lines were left in the final PR.

Task-0

closes #255176

X-original-commit: 139304b
Signed-off-by: Lucas Lefèvre (lul) <lul@odoo.com>
Signed-off-by: Rémi Rahir (rar) <rar@odoo.com>
We're adding new PO files for the following languages:
uz
hsal-odoo and others added 12 commits March 22, 2026 08:08
This commit fixes the following issues
1) Having more than one payment method on a pos.order led to an error
2) Customer should be required if payment method is receivable, or cash with amount > 10,000 JOD

task-6005832

closes #255225

X-original-commit: 840bcba
Signed-off-by: Josse Colpaert (jco) <jco@odoo.com>
Signed-off-by: Hesham Saleh (hsal) <hsal@odoo.com>
…validation

**Issue**:
Making two stock valuation closings with different accounting dates in the past,
on the same day, leads to an "Invalid Operation" error.

**Steps to reproduce**:
- In settings, set inventory valuation at invoicing
- Create 2 bills of a storable product:
	- `Accounting date` = `bill date` = today - 2 days
	- `Accounting date` = `bill date` = today - 4 days
- Go to Accounting > Review > Inventory > Inventory Valuation
- Set the day to today - 3 days, generate and post the entry
- Go back the Inventory Valuation
- Set the day to today - 1 day, generate the entry
-> Invalid Operation error: the system thinks it exists a closing entry after the selected date.

**Cause**:
The regression was introduced by commit 594654d
Indeed, `_get_last_closing_date` was modified to prioritize the creation date
of the closing instead of its accounting date:
https://github.com/odoo/odoo/blob/594654deb84ba45e9a6a765b89de79e4ce4e4b50/addons/stock_account/models/res_company.py#L336

As a consequence, the second closing with at_date = today - 1 day
was compared against last_closing_date = today (creation date):
https://github.com/odoo/odoo/blob/b3559145febc16271c78ca516af9d7e99bf3452f/addons/stock_account/models/res_company.py#L53-L55

**Solution**
To avoid to revert this commit 594654d fix, both creation and accounting date are used.

opw-5559264

closes #253445

X-original-commit: df586d4
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Maxime Noirhomme (noma) <noma@odoo.com>
Steps to reproduce
------------------
1. Make two fiscal positions, one applying taxes, and the other not.
2. Open pos, select the FP that applies taxes, and add a product
3. Now apply a global discount of 10%
4. Chagne to the FP that does not apply any taxes.

Notice that the discount line amount is still computed based on the the
taxes from the old FP.

Rational and fix
----------------
When changing the fiscal position of an order, we recompute the prices
for all linese, as this new FP might bring new taxes or tax_maps rules.

If a global discount is also apply, we have to reapply it in order to
make sure all the discount lines are up to date with new prices changes
after applying the FP.

We now listen to accounting fields changes also in pos_discount, i.e. to
FP and preset_id, and reapply the discount when they do change.

opw-5443716

X-original-commit: 91e4648
Part-of: #255060
Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Signed-off-by: Hadi El Yakhni (hael) <hael@odoo.com>
When updating an already existing discount line, we were only updating
its `price_unit` field, but we kept using the old `extra_tax_data`,
which created inconsistencies when recomputing the line prices.

closes #255060

X-original-commit: 959dd68
Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Signed-off-by: Hadi El Yakhni (hael) <hael@odoo.com>
There is no unified way to retrieve discount lines across modules. Each
source uses a different mechanism: `display_type == 'discount'` in
account, a company-level `sale_discount_product_id` in sale, and a
config-level `discount_product_id` in point_of_sale.

This commit adds a `_get_discount_lines` helper on `account.move.line`
that consolidates multiple sources. The base implementation filters by
`display_type`, and each module overrides it to also include its own
discount product lines.

task-5875158

X-original-commit: 7a1d765
Part-of: #255001
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Signed-off-by: Jonathan Andika (jand) <jand@odoo.com>
Previously, the invoice logic did not properly handle the following scenarios:

- Global discount: when a global discount was applied, negative values
  were sent to Sinvoice, resulting in a BAD_REQUEST_ITEM_VALUES_NEGATIVE
  error.
- Down payment: when an invoice included a down payment to deduct the
  amount, negative values were sent to Sinvoice, triggering the same
  BAD_REQUEST_ITEM_VALUES_NEGATIVE error.
- Note lines: note lines on the invoice were not being uploaded/included
  in the invoice submission.

This commit fixes the handling of global discounts and down payments by
ensuring negative values are properly transformed before being sent to
Sinvoice, and adds support for uploading note lines in the invoice.

task-5875158

X-original-commit: 914faf6
Part-of: #255001
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Signed-off-by: Jonathan Andika (jand) <jand@odoo.com>
Update account_production_wip_account_id from
chart154 to chart1541 so the default production
WIP account is correctly configured.

task-5875158

closes #255001

X-original-commit: 74b3baf
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Signed-off-by: Jonathan Andika (jand) <jand@odoo.com>
Currently, when a user creates a Sale Order for MTO products that share the same
component (which itself has a BOM), the system does not create a separate
child MO for each manufacturing order.

Steps to produce:
- Install Sales and Manufacturing
- Go to Settings and turn on Replenish on Order (MTO).
- Create products 'Wooden Arrow' and 'Wooden Rod' with a BOM that includes:
   - 'Stick', which itself has a BOM with 'Raw stick'.
- On each product page, go to Inventory and enable the MTO route,
  except for 'Raw Stick' .
- Create a Sale Order for Wooden Arrow and Wooden Rod for
  Customer 'Administrator'.
- Confirm the Sale Order.
- Go to Manufacturing > Open and check both Manufacturing Orders.

Observed Behavior:
Currently, the manufacturing order for 'Wooden Arrow' has a child MO, but the
order for 'Wooden Rod' does not.

The child MO under 'Wooden Arrow' produces two sticks at once. However, each
manufacturing order should have its own separate child MO so that every item
is produced and tracked individually.

Root cause:
The issue happens because when a Sale Order is confirmed, `_run_manufacture` is
called. This method creates a new MO or updates an existing one based on the
domain returned by `_make_mo_get_domain` [1].

For 'Wooden Arrow' and 'Wooden Rod; new MOs are created because no existing MO
matches their BOM ID, product ID, or reference.
They are added to `new_productions_values_by_company` [2], which is then used to
create the MOs [3].

When `_run_manufacture` runs for 'Stick', it is triggered twice since both
MOs require it as a component. The first time, no MO matches the domain, so a
new one is created. The second time, the domain matches the existing MO
(same BOM ID and product ID), so that MO is updated instead [4]. Because of
this, `new_productions_values_by_company` is not filled again,
and no second child MO is created.

Solution:
To resolve this issue, the domain has been tightened to include the parent
production group ID. Since the parent MO’s group ID is passed through the
procurement variable when _run_manufacture is executed for its component
products, this group ID can be used to ensure the correct MO is matched.

Why modify the existing test case?:
With this change, in the test_sale_mrp_pickings test case, a new child MO for
'Stick' is created under the MO for 'Arrow' instead of modifying
another parent MO for 'Stick'. The test case has been updated accordingly.

[1]:
https://github.com/odoo/odoo/blob/c2595e47e3b36120f4c3da8bfe8c16f6c5969a70/addons/mrp/models/stock_rule.py#L146-L165
[2]:
https://github.com/odoo/odoo/blob/c2595e47e3b36120f4c3da8bfe8c16f6c5969a70/addons/mrp/models/stock_rule.py#L98-L103
[3]:
https://github.com/odoo/odoo/blob/c2595e47e3b36120f4c3da8bfe8c16f6c5969a70/addons/mrp/models/stock_rule.py#L115
[4]:
https://github.com/odoo/odoo/blob/c2595e47e3b36120f4c3da8bfe8c16f6c5969a70/addons/mrp/models/stock_rule.py#L105-L110

opw-5480133

closes #255157

X-original-commit: ae18363
Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
Signed-off-by: Anshik Gopalbhai Brahmbhatt (agbr) <agbr@odoo.com>
…roduct

Steps to reproduce:
- Create a product with type = Goods and Track Inventory by Quantity 
- Go to product category > inventory valuation > costing method = FIFO
- Create a BOM for the product with BOM Type = Kit
- Create and validate a POS order
- Open the order in the backend

Issue:
- The total cost was shown as 0.0 for kit products. Also, the margin amount and
  margin percentage were incorrect.

Fix:
- Ensure that the total cost and margin are correctly computed for kit-type
  products in POS orders.

task-5924559

closes #254807

X-original-commit: 346022d
Signed-off-by: David Monnom (moda) <moda@odoo.com>
Signed-off-by: Dhruv Jitendrakumar Patel (djip) <djip@odoo.com>
Steps to reproduce:
1. Install `contacts`
2. Create an individual contact with a phone number
3. Try to edit the phone number on the mobile

Issue:
- Unable to edit in mobile view

Cause:
- On mobile devices, the utility buttons (Call, SMS, WhatsApp) inside the
  phone widget consume significant horizontal space. Due to the flex
  layout, this forces the actual phone input field to shrink too much
  making it hard/impossible to view or edit the number.

Solution:
- Hide the text labels of the utility buttons to save space, showing only the icons.
- make input's width 100% on mobile screens in partner form

opw-5489021

closes #253772

X-original-commit: 6948d02
Signed-off-by: Romeo Fragomeli (rfr) <rfr@odoo.com>
Signed-off-by: Piyush Sharma (pish) <pish@odoo.com>
For POS consolidated invoices, the PrePayment Amount was mapped to the
payment linked to the document. This incorrectly decreased the Total
Amount Payable to 0, since POS orders are already paid at the counter.

MyInvois tax officer and helpdesk requires that the Total Amount Payable
(cbc:PayableAmount) to reflect the total amount of the issued e-document
, regardless of prior payments.

This commit forces the PaidAmount to 0 for consolidated documents,
ensuring the PayableAmount correctly matches the TaxInclusiveAmount as
expected by the MyInvois API.

task-[6021698](https://www.odoo.com/odoo/all-tasks/6021698)

X-original-commit: 80b602f

runbot-[241948](https://runbot.odoo.com/odoo/runbot.build.error/241948)

closes #255210

X-original-commit: d2eaf4b
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Signed-off-by: Eric Lem (erle) <erle@odoo.com>
Issue:
The Anita Oliver contract starts on %Y-01-01, so her leave allocation begins
from that date.
When running with faketime set to 2027-01-01, the system attempts to create
leave for the previous month, which results in an error stating that there is no
allocation for that time off.

Fix:
Update the demo data to create the leave and payslip for the first month of the
year. This prevents failures when using faketime and ensures it works correctly
for real usage of `time off to defer`.

task-6026690

closes #255058

X-original-commit: 327f062
Related: odoo/enterprise#111435
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Signed-off-by: Priyanshu Goyal (prgo) <prgo@odoo.com>
avar-odoo and others added 30 commits March 27, 2026 10:04
This commit improves the Taiwanese localization by refining fiscal positions
and their associated tax mappings to better align with local accounting practices
and e-invoicing terminology.

Key changes:
- Updated Chinese translations (`name@zh_TW`) for B2B/B2C fiscal positions
  to explicitly include e-invoices (電子發票).
- Added a new fiscal position for VAT Exempt (`l10n_tw_fiscal_position_vat_exempt`).
- Removed redundant purchase-specific fiscal positions (Unified Invoices,
  Duplicate/Triplicate Cash Register) and Deemed Sales.
- Remapped purchase taxes to standard B2B/B2C fiscal positions to simplify
  the fiscal position structure.
- Updated `original_tax_ids` and `fiscal_position_ids` across sales and purchase
  taxes to reflect the consolidated fiscal positions.
- Fixed a typo in the invoice label for the "2% ART 11 GBRT" tax (changed "25" to "2%").

Task-6007589

closes #256269

X-original-commit: fbdd523
Related: odoo/enterprise#112271
Signed-off-by: Arnav Varshney <avar@odoo.com>
Signed-off-by: Arnav Varshney <avar@odoo.com>
Signed-off-by: Arnav Varshney <avar@odoo.com>
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Signed-off-by: Arnav Varshney (avar) <avar@odoo.com>
Accrual plan for leave days gets blocked, even when the remaining leave balance is below the cap. As a result, no additional leaves are accrued beyond a certain point, even though they should be.

Steps to reproduce:
-------------------

Go to time off app
* Create a new leave type.
* Create a new accrual plan with:
        - one milestone :
		- 2 days accrued per month
		- Cap: 10 days
		- start accruing 1 days after
		- No expiration
		- Carry over: All
* Create and validate a leave allocation
       - 1 year ago
       - new leave type
       - new accrual plan
* Take the maximum number of leaves available.
* Advance the computer calendar by 1 year.
* Again, take the maximum number of leaves.
* Advance the computer calendar by another year.
* Try to take a future leave.
-> Issue: It's not possible to take a future leave, the number of accrued days has stopped increasing. The accrual plan appears blocked.

Issue:
------

In the `_test_get_allocation_future_leaves1` added test, in the last line of the test :
`assert_virtual_leaves_equal(self, leave_type_day, 2, self.employee_emp, date='2023-02-01')`

When calling `get_allocation_data` with a `target_date` set in the future, the result is wrong. Here is how it works :
`get_allocation_data`
    ...
.....`_get_consumed_leaves` (1)
...........`_get_future_leaves_on` (2)
...............`_process_accrual_plans` (3)
....................`_compute_leaves` (4)
.........................`_get_consumed_leaves` (5)
..............................`get_future_leaves_on` (6)
...................................`process_accrual_plans` (7)

**A)** The method **(2)** try to calculate the added number of days each allocation will have on `target_date`. So it creates a copy of the allocation in memory using the 'new' method:
`fake_allocation = self.env['hr.leave.allocation'].with_context(default_date_from=accrual_date).new(origin=self)`
It will then update it to `target_date` using `_process_accrual_plans` and will return the difference of days between the
updated `fake_allocation` and the current allocation (`self`)

**B)** Before iterating over each accrual date, the `_process_accrual_plans` **(3)** will get the `leaves_taken` property which is a computed field. It will trigger `_compute_leaves`.

**C)** The method **(4)** will call `_get_consumed_leaves`, and so the nightmare begins.

**D)** The method **(6)** will create a second `fake_allocation` based on the origin of the first `fake_allocation` (see **A)**).

**E)** This time, `_process_accrual_plans` **(7)** will also look at the `leaves_taken`, but won't trigger the `_compute_leaves` probably because the current allocation is a `fake_allocation` of a `fake_allocation`, and one property of the `new` method is that `Two new records with the same origin record are considered equal.`. Therefore, the `leaves_taken` is considered to be already computed (but it's not).

So `_process_accrual_plans` read the `leaves_taken` which is 0 (probably the default value of `leaves_taken`), but it should be 20 !

**F)** As the value of `leaves_taken` is wrong, the fake_allocation n°2 is also wrong, and its `number_of_day` is 10 but the `number_of_days` of the origin allocation is 20. So `get_future_leaves_on` **(6)** will return -10 which makes no sense, and all the previous calls computations will be wrong. And the final `virtual_remaining_leaves` value will be 0 instead of 2.

Source:
-------

Before going further: the property `leaves_taken` of the `hr.leave.allocation` is supposed to contain the number of leaves this allocation cover until "today".

In the `_process_accrual_plans` method, for each allocation, `leaves_taken` is only computed once at the start of the loop over the allocation "important" dates (see `nextcall` property of `hr.leave.allocation`). At this moment, the method calculates the `leaves_taken` the allocation will have on the `accrual_date` parameter. Yet, this property can change depending on the date the allocation is on (`nextcall` property) which leads to some issues in the computation of the `allocation.number_of_days`.

Solution:
---------

For each allocation, compute the `leaves_taken` at every iteration trough the values of `nextcall`. BUT, this can trigger an infinite loop as computing `leaves_taken` calls `_get_consumed_leaves` which calls `_get_future_leaves_on`, which calls `_process_accrual_plans` ... To avoid this, this PR add the context variable `precomputed_allocations` (will be converted into a function parameter in master) which will prevent `_get_consumed_leaves` from calling `_get_future_leaves_on` for the allocations already up to date (contained by this very `precomputed_allocations` context variable).

Second Issue:
-------------

The accrual plan allocation engine (method `hr.leave.allocation._process_accual_plans`) is still using the `hr.work.entry.type.request_unit` field instead of the `unit_of_measure`. This PR changes that and adds the test `test_work_entry_unit_of_measure_hour` to ensure accrual plans granted days are computed correctly when using a work entry type with `unit_of_measure` set to 'hour' and `request_unit` set to 'day'.

community-239836
opw-5226806
opw-4934391

closes #254539

X-original-commit: 55bf157
Signed-off-by: Bertrand Dossogne (bedo) <bedo@odoo.com>
Invoicing users need to verify partner Nilvera status as part of the
regular invoicing workflow, but the check was failing due to missing
access rights on `l10n_tr.nilvera.alias` (create/unlink operations).

Granted access to `account.group_account_invoice` to allow the check
without requiring admin intervention.

task-6044307

closes #256088

X-original-commit: c32d783
Signed-off-by: Maximilien La Barre (malb) <malb@odoo.com>
Signed-off-by: Himilsinh Sindha (hisi) <hisi@odoo.com>
Issue:
------------------------------------------------
When a Manufacturing Order is created via an MTO flow from a Sales Order,
the Forecast Report was displaying the Sales Order in the "Available" section
instead of the Manufacturing Order.

Steps to Reproduce:
------------------------------------------------
1. Install `sale_mrp` and `sale_management`.
2. Create a storable product with BOM and MTO route
3. Confirm a Sales Order for the product
4. Open the Forecast Report
5. Observe incorrect reference in "Available" section

Cause:
------------------------------------------------
Before v19.0, finished moves of an MO created via MTO did not carry a
`sale_line_id`, but now it will propagate to the MO finished moves.
Because `_get_source_document()` is overridden in multiple modules,
the `sale_stock` implementation now matches first and returns the
Sales Order, preventing the MRP logic from returning the Manufacturing Order.

With this commit:
------------------------------------------------
This fix ensures that the Manufacturing Order is shown as the
source document providing correct traceability and aligning the behaviour
with the purchase MTO flows.

task-5941986

closes #256253

X-original-commit: 1c36d39
Signed-off-by: Tiffany Chang (tic) <tic@odoo.com>
Signed-off-by: Sahil Koladiya (sako) <sako@odoo.com>
Some taxes had a wrong tax exemption code and tax exemption reason.
This commit corrects them.

task-4976471

closes #256104

X-original-commit: 9efab6c
Signed-off-by: Wala Gauthier (gawa) <gawa@odoo.com>
Signed-off-by: Jugurtha Gaci (jugac) <jugac@odoo.com>
…method

The logic to download XML/PDF files from SInvoice and attach them to
the invoice was embedded directly in `AccountMoveSend`. To allow the
upcoming `l10n_vn_edi_viettel_pos` module to reuse this logic without
depending on `AccountMoveSend`, it is extracted into a dedicated
`_l10n_vn_edi_fetch_invoice_files()` method on `account.move`.

A `skip_fetch_sinvoice_files` context key is also introduced to let
callers bypass the fetch when needed.

This is a partial backport of 2f03c9c.

task-4844619

X-original-commit: 01d9639
Part-of: #255742
Signed-off-by: Jonathan Andika (jand) <jand@odoo.com>
Add Viettel SInvoice integration with the Point of Sale
module to support PoS e-invoicing for the Vietnamese market.

task-4844619

X-original-commit: ba92fec
Part-of: #255742
Signed-off-by: Jonathan Andika (jand) <jand@odoo.com>
Use currency_id.round() for the unitPrice field to align with the
currency's decimal places, preventing floating point precision issues
in the SInvoice payload.

task-4844619

closes #255742

X-original-commit: bd0aa00
Signed-off-by: Jonathan Andika (jand) <jand@odoo.com>
Steps to reproduce:
- Enable the customer rating from project's setting.
- Go to project > Reporting > Customer Ratings.
- Open any rating record.
- Observe that the 'Comment' field is displayed twice.

Issue:
- The form view contains a two different field with same string i.e feedback and
  publisher_comment

Fix:
- Made the publisher_comment field invisible in project's customer rating

closes #256220

Task-id: 5359052
X-original-commit: 1f76203
Related: odoo/enterprise#112246
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
Mails are sent to users containing an acceptation and cancellation link
that accepts GET requests but preforms an action on visit

Some mail defender software analysis urls in links by actually visiting
the URL.
This leads to both actions being triggered without user input.

Instead we now send buttons with a neutralizing parameter in the mail.
Recipients may then visit the url and click a form button to "accept" or
"decline".

As these are post requests the email bots should avoid clicking them.

task-4555579

closes #256134

X-original-commit: a9481cf
Related: odoo/enterprise#112202
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Signed-off-by: Renaud Thiry (reth) <reth@odoo.com>
Since Odoo 18.4, the general logic for the fetchmail Cron Job was
refactored to align it with the new changes to how cron jobs are
handled (i.e. the _commit_progress etc.)
See #191911

But it certain (legitimate) edge-cases, the current logic might not
handle real-life scenario correctly

Analysis:

When having a high number of legitimate and working fetchmail.server records (>10).
The cron job was repeatably finishing in a "partially done" state,
reporting 0 done progress and retriggering immediately.
Also if there was a notable latency when establishing the IMAP connection,
this had for effect of:

- The cron would process the first few (empty, no new unseen mail) inboxes
 stop break early because of this
 https://github.com/odoo/odoo/blob/4056fa8036ddad11c898cd775b7fa21ba4f8a5de/addons/mail/models/fetchmail.py#L329
 , i.e. if no progess is commited, the cron job handler stops the job
 after 10 secs see https://github.com/odoo/odoo/blob/4056fa8036ddad11c898cd775b7fa21ba4f8a5de/odoo/addons/base/models/ir_cron.py#L495-L498
- Thus the job would stop early in the partially done state, which would
create a cron trigger and relaunch it at the earliest
(usally 1 min later if no other jobs running)
- In the new run, because _fetch_mails always browses the fetchmail.server
 records in the same order, it will check the same inboxes again, and
 because they are empty and there is a connection lag, it would take
 longer than 10 secs again and stop the cron early
 in partially done → rinse and repeat
- In practice in this edge-case we will never check the remaining
fetchmail servers, so unseen emails on those would never be processed →
customer complains that emails are not coming in
- The repeated triggering of the job and it never officially reporting
progress seems to trigger the automatic deactivation on the odoo.sh
platform, further aggravating the situation

Issues with current business logic of the cron:

1) The `total_remaining` variable (tracking the "units" of work to be done)
 does not distinguish between number of servers to be process and the
 number of unseen emails to be processes on the current fetchmail server.
 At the same time it does not commit an explicit progress when finishing
 an outer loop (at the server level) when the inbox was empty
2) The use of `remaining_time` as a circuit-breakers seems like a good
idea at first, but combined with point 1, will terminate the cron early
if checking empty inboxes takes too long and will break the inner loop
(fetching emails) early on subsequent loops of the cron
3) `_fetch_mails` will always return the model records in the same order,
and everything being equal, will not account for that fact if some
fetchmail.server records have been fetched more recently than others

Proposed changes to logic:

    1. We add a time buffer to the 'cron_end_time' context value, initialized at the beginning of a job an usually accounting for 10 secs of wall-time per job. We scale the time buffer as 4 * N secs, N being the number of total fetchmail records that need to be checked. This is to ensure that, assuming that all mail inboxes are empty, we have enough time to loop over all of them even if there is "extreme" latency of 2s to connect and 2s to get a response from the mail server.

    2. We make the ordering in _fetch_mails "smarter" by  adding a
    custom order argument for more dynamic queuing:
	A) Records with the lowest priority first
	B) Records having the oldest date first, i.e we dynamically penalize
    records that were fetched recently given the date fields get's
    updated every time it fetched/checked a server successfully

    3. If a customer still hits the implicit threshold (i.e. it takes longer than 10 + 4 *N s to loop over all current fetchmail servers), the cron will simply rerun at the next recurrence and the custom order should ensure that the backlog get's resorbed. If the time buffer is still not enough in extreme latency scenarios, then users should either fix the root cause (connection latency between the Odoo DB and the mail servers) or opt for an alternative to route the emails to the DB (setting up an MX record and redirecting mails into a mailgate).

OPW-6054244
OPW-6019730

closes #256237

X-original-commit: e02c26b
Signed-off-by: Joel Rodrigues Vitória (jorv) <jorv@odoo.com>
The issue is raised in this pr(v19.2) :
#236971

The compute method used a `return`
https://github.com/odoo/odoo/pull/236971/changes#diff-4e1a18a369f7dd4de264139227676dd818c06612681c88019f43d238bd8a1490R91
statement when a `if condition` was met.
While this works correctly for a single record, it causes issues when multiple
records are present.
For example, if `self` contains records like `project.project(3, 2, 4)`,
and the condition is satisfied for the first `record (3)`, the method exits
early.
As a result, the remaining `records (2 and 4)` are not processed.

When the compute method is triggered,
https://github.com/odoo/odoo/blob/8c3043b436f8aae295f247341e3ac427fab05474/odoo/orm/fields.py#L1746
this incomplete computation leads to
missing values for some records and can result in errors.

To resolve this issue, `return` has been replaced with `continue`.
This ensures that:
Only the current record is skipped when the condition is satisfied.
The loop continues processing the remaining records.

Traceback:
```
Traceback (most recent call last):
  File "/tmp/tmp2cuqrnuy/migrations/testing.py", line 483, in test_check
    self.check(value)
  File "/tmp/tmp2cuqrnuy/migrations/base/tests/test_mock_crawl.py", line 228,
 in check
    self.assertFalse(diff, msg)
AssertionError: [('project.menu_projects', 391, 'Project > Projects', 593)] is
not
false : At least one menu or view working before upgrade is not working after
upgrade.

('project.menu_projects', 391, 'Project > Projects', 593):
 Traceback (most recent call last):
   File "/tmp/tmp2cuqrnuy/migrations/base/tests/test_mock_crawl.py", line
335, in crawl_menu
    self.mock_action(action_vals)
   File "/tmp/tmp2cuqrnuy/migrations/base/tests/test_mock_crawl.py", line
348, in mock_action
    return self.mock_act_window(action)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/tmp/tmp2cuqrnuy/migrations/base/tests/test_mock_crawl.py", line
508, in mock_act_window
    mock_method(model, view, fields_list, domain, group_by)
   File "/tmp/tmp2cuqrnuy/migrations/base/tests/test_mock_crawl.py",
line 541, in mock_view_form
    [data] = record.read(fields_list)
             ^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 2735, in read
    return self._read_format(fnames=fields, load=load)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 2991, in
_read_format
    vals[name] = convert(record[name], record, use_display_name)
                         ~~~~~~^^^^^^
   File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 6007, in
__getitem__
    return self._fields[key].__get__(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   File "/home/odoo/src/odoo/saas-19.2/odoo/orm/fields.py", line 1805, in
__get__
raise ValueError(f"Compute method failed to assign {missing_recs}.{self.name}")
ValueError: Compute method failed to assign
project.project(2, 4).stat_timesheet_value
```
opw-6046808

closes #256048

Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
…om SO to PO

Steps to reproduce:
- Enable analytic distribution in Accounting settings
- Create a storable product "P1":
  - Routes: MTO + Buy
  - Vendor: add any supplier
- Create a Sale Order:
  - Add 1 unit of P1
  - Set any analytic distribution
- Confirm the Sale Order

Result:
A Purchase Order is created, but the analytic distribution is not
propagated to the purchase order line.

Problem:
When the Sale Order is confirmed, `_action_launch_stock_rule()` is
triggered. It creates and confirms the corresponding stock move with
values from the sale order line.

Since the product uses the MTO route, the procurement rule is executed.
The rule prepares procurement values from the stock move, but the
analytic distribution is not included in these values:

https://github.com/odoo/odoo/blob/18.0/addons/stock/models/stock_move.py#L1539

Later, `_run_buy` is triggered. It uses the procurement values coming
from the stock move to find an existing purchase order line candidate or
to create a new one. Because the analytic distribution is missing from
the values, the created (or matched) purchase order line does not
contain the analytic distribution:

https://github.com/odoo/odoo/blob/621a93b7b723999d943f1c4da78547763498c008/addons/purchase_stock/models/stock_rule.py#L113

Solution:
Propagate the analytic distribution from the sale order line through the
stock move so it can be included in the procurement values and correctly
applied to the purchase order line.

opw-5936971

closes #256136

X-original-commit: 8d55cd7
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Djamel Touati (otd) <otd@odoo.com>
next_by_code() can return a sequence with multiple '/' in the prefix
(e.g. "BATCH/test/00002" or "batch/test/2026/00002"). Using split('/')
causes a ValueError: too many values to unpack.

Use rsplit('/', 1) to always split on the last '/' and correctly extract
the sequence prefix and number.

Steps to reproduce the bug:
- Go to settings > technical > sequences & identifiers > sequence:
    - batch transfer:
        - prefix: BATCH/test/

- Create a new batch:
    - operation type: delivery orders
    - Try to save

Problem:
a traceback is triggered:
```ValueError: too many values to unpack (expected 2)```

opw-6043880

closes #256080

X-original-commit: db43fa1
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Djamel Touati (otd) <otd@odoo.com>
Problem
---------
Currently, when importing a move, `ubl_cii_xml_file` gets set with said
XML. This XML is then re-used during the export rather that regenerate
a new XML each time.

This is fine for customer bills as those are not meant to be modified.
This is not the case of customer invoices. Client may import an invoice
XML and later update that invoice. In such a case, we want to regenerate
the XML and not reuse the imported version.

Solution
---------
Only set `ubl_cii_xml_file` for purchase move during the import.

no-task

closes #256075

X-original-commit: 6168795
Signed-off-by: Laurent Smet (las) <las@odoo.com>
Signed-off-by: Antoine Boonen (aboo) <aboo@odoo.com>
…pace

Problem:
Sometimes pressing space in content containing a symbol pattern
creates the symbol even when the space is not placed directly before
it.

Cause:
`leftLeafOnlyNotBlockPath` sums the `spaceOffset` of all non-block leaf
nodes, then performs a substring on the whole block containing those
leafs.

In this case, the file box contains a `span` with `d-flex`, which is
considered a block. Therefore, the file box text content length is not
included in the `spaceOffset` calculation.

However, we later call `substring` on the `textContent` of the
`closestBlock`, which includes the file box content. This leads to an
incorrect `spaceOffset`, effectively skipping the file box text.

This can happen by chance when the `substring` returns the file box
text content with `"-->"` immediately after it, making it the last
character and triggering symbol creation.

Solution:
When computing the `substring`, consider only the `textContent` of the
leaf nodes traversed while calculating `spaceOffset`. This ensures the
offset matches the actual traversed content and prevents accidental
symbol generation.

Steps to reproduce:
- Use the same HTML structure as in the test.
- Place the selection as in the test case.
- Press space.
- Observe that a symbol is incorrectly created.

task-6004954

closes #256133

X-original-commit: 1cbb262
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Walid Sahli (wasa) <wasa@odoo.com>
Specification:
- When a user uploads a file in the link popover, user can not
reupload another file without manually removing previous URL.

After this commit:
- This commit allows user to re-upload a file without removing
previously generated URL first.

task-5470111

closes #256195

X-original-commit: 09e096d
Signed-off-by: Jinjiu Liu (jili) <jili@odoo.com>
Signed-off-by: Rahil Ghanchi (rahg) <rahg@odoo.com>
### Contains the following commits:

odoo/o-spreadsheet@f3beabc758 [REL] 19.2.5 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
odoo/o-spreadsheet@d5c6bc0a1b [FIX] grid_renderer_store: keep wrapping width with explicit align [Task: 6032407](https://www.odoo.com/odoo/2328/tasks/6032407)
odoo/o-spreadsheet@49c9574a44 [FIX] functions: stop debugging context [Task: 6052128](https://www.odoo.com/odoo/2328/tasks/6052128)
odoo/o-spreadsheet@f809d67a5c [FIX] config: fix release flow [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
odoo/o-spreadsheet@a962b50527 [FIX] SheetView: dirtify sheet viewport at UPDATE_CELL [Task: 5953775](https://www.odoo.com/odoo/2328/tasks/5953775)
odoo/o-spreadsheet@f915568943 [FIX] xlsx: do not export dynamic tables to excel [Task: 5214240](https://www.odoo.com/odoo/2328/tasks/5214240)

closes #256279

Signed-off-by: Rémi Rahir (rar) <rar@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>
Problem:
On Website Events, when uploading a file as a URL in a link on a public
page, portal users cannot download the file.

Cause:
The upload process attaches the current `res_model` to the file. As a
result, access to the file depends on model permissions. Even if users
can view the page, they may not have the rights required to download the
attachment.

Solution:
Files uploaded through link URLs in website should be public otherwise
depends on the `res_model`.

Steps to reproduce:
- Go to Website > Events.
- Upload a file as a URL in a link.
- Save the page.
- Open the page in a new unauthenticated session.
- The page and link are visible, but the file cannot be downloaded.

opw-5993708

closes #256287

X-original-commit: 8a24456
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Walid Sahli (wasa) <wasa@odoo.com>
When computing the product cost in `_get_product_cost_with_moves`,
iterating over `product.bom_ids` would include BOMs from all companies,
causing an `AccessError` when the current user lacked read access to a
BOM belonging to another company.

opw-6060735

closes #256178

X-original-commit: 851fd3c
Signed-off-by: Adrien Guilliams (adgu) <adgu@odoo.com>
Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
…es) to have some inherit point (useful for integrators)

closes #256236

X-original-commit: fe0cb69
Signed-off-by: Tiffany Chang (tic) <tic@odoo.com>
Steps to Reproduce
- Go to To-Do
- Add a table
- Type content inside the table
- Select all using Ctrl + A
- Apply formatting (e.g., Bold)

Issue:
An empty line appears above the table and the layout shifts unexpectedly after
applying formatting.

Cause:
`data-selection-placeholder` nodes exist before and after the table. These nodes
normally have zero height.
When selecting all content, these placeholder nodes are also included in the
selection. Applying formatting styles them as well, which changes their height
from zero. As a result, they become visible and appear as newly added blank
lines, even though no new line was actually inserted.

Solution
Exclude system nodes, such as selection placeholder elements, from formatting
operations. This prevents them from being styled and avoids unintended layout
shifts.

task-5976361

closes #256235

Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: DHAVAL BARAIYA (dhba) <dhba@odoo.com>
Steps to Reproduce

- Create a draft manufacturing order : Desk Combination
- Update bom using ECO
- Add a new Line with Screw with 10 qty
- Apply Changes
- Update BOM in the manufacturing order

-> Record does not exist or has been deleted.

Changing bom_id causes the computes state/move_finished_ids/move_raw_ids
& workorder_ids to be triggered.

Since #195995, raw_material_production_id have ondelete='cascade'
Therefore
https://github.com/odoo/odoo/blob/95c73aa4dd7433f394799fdaaad57a84d750ec5a/addons/mrp/models/mrp_production.py#L828
will unlink the raw moves, see
https://github.com/odoo/odoo/blob/95c73aa4dd7433f394799fdaaad57a84d750ec5a/odoo/orm/fields_relational.py#L980

Due to
https://github.com/odoo/odoo/blob/95c73aa4dd7433f394799fdaaad57a84d750ec5a/addons/mrp/models/mrp_bom.py#L265
unlink cannot be removed, so exists() will do the job.

Also fix unlinking of workorder_ids which causes the same error message in 18.0

closes #256211

Issue: 254376
X-original-commit: 877289c
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Jean-Francois Aubert (ajf) <ajf@odoo.com>
**STEP TO REPRODUCE**
1. install l10n_dk_nemhandel, and activate nemhandel.
2. Create a company partner, with a EAN/GLN as the nemhandel id.
3. Create an individual partner linked to the company partner.
4. Create an invoice with this individual partner.
5. Send the invoice with nemhandel.
6. open the xml file, and notice that the EndpointID doesn't use the
EAN/GLN of the company partner. (It falls back to the VAT instead).

opw-5945440

closes #256135

X-original-commit: 548689c
Signed-off-by: Wala Gauthier (gawa) <gawa@odoo.com>
Signed-off-by: Léo Gizard (legi) <legi@odoo.com>
The Availability fields are no longer available for pick up in store as they
were removed from the view.
However, old databases that were upgraded might still have those fields filled,
quietly preventing the option from showing up but also not allowing those fields
being changed from the UI.

To reproduce:
- In 18, create a pick up carrier and add some countries and states.
- Upgrade to 19.
- Try to use pick up with an address not belonging to those states, it won't be
possible but it also won't be possible to modify the carrier.

closes #255900

X-original-commit: 4dba2da
Signed-off-by: Valeriya Chuprina (vchu) <vchu@odoo.com>
Before this commit, a spacing was missing between
the employee image and the employee name. It was
added by switching the noSpacing to false.

task-5960515

closes #256222

X-original-commit: ce7625f
Signed-off-by: Abdelrahman Mahmoud (amah) <amah@odoo.com>
Tests for synchronizing Gelato products with Odoo and buying Gelato
products are added.

task-4527206

closes #254446

X-original-commit: 5e15d10
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Signed-off-by: anko-odoo <anko@odoo.com>
When a PDF is received by a journal email alias, a race condition occurs
between the notification email process and the OCR (IAP) callback.

The notification email template generates a portal URL. Accessing
this URL triggers a lazy-generation of the 'access_token' on the
account.move record. If the OCR callback (which is asynchronous) updates
the same record while the main thread is busy communicating with the
SMTP server, the main thread fails with a SerializationError
(Concurrent Update) when it finally tries to commit the new token.

This results in a "bouncing email" error for the user, even though the
invoice was created and the OCR worked correctly.

This commit forces the generation and flush of the 'access_token'
immediately before the notification process begins. By ensuring the
write happens early and is flushed to the DB, we avoid a conflicting
lazy-write during the post-SMTP commit phase.

Traceback example (simplified):
------------------------------
INFO: iap jsonrpc .../invoice/2/parse
INFO: POST /account_invoice_extract/request_done/... HTTP/1.0" 200
ERROR: bad query: UPDATE "account_move" SET "access_token" = ...
ERROR: could not serialize access due to concurrent update
psycopg2.errors.SerializationFailure: could not serialize access due to concurrent update

OPW-5887922

closes #256312

X-original-commit: d9b8116
Signed-off-by: Thomas Becquevort (thbe) <thbe@odoo.com>
Signed-off-by: Joel Rodrigues Vitória (jorv) <jorv@odoo.com>
Co-authored-by: Louis Baudoux <lba@odoo.com>
…on batch backorder

Scenario:
 - Create two pickings with same partner with at least two moves each,
the picking type should have auto_group and auto_confirm
 - Add to a batch transfer
 - Change the quantity on a move line, unlink the other
 - Validate the batch
 - Create backorder
Without this PR the "incompatible types" error appear because tries
to assign the batch currently validating to the backorder picking

closes #255934

X-original-commit: 7ab5bf1
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
When sending an invoice via Peppol, the PDF and XML attachments are
logged in the chatter. This automatically triggers a synchronization
with the Documents app. However, the Peppol sending flow also includes
a dedicated document linking step later in the process.

This caused the same attachments to be registered as documents twice.

This commit skips the document synchronization during the initial
chatter logging step. The attachments will now only be synchronized
once during the dedicated linking phase.

Note: ec6e559 prevented duplicate attachments in the chatter with
some cleanup code, but this cleanup code runs after the document has
already been created and does not remove the document, resulting in
duplicate documents, which this commit fixes.

Task-6030468

closes #256412

X-original-commit: 6419581
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
Signed-off-by: Jérôme Belpaire (beje) <beje@odoo.com>
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.