Skip to content

Merged from upstream 18 260131 01#1183

Open
davidtranhp wants to merge 75 commits intoViindoo:18.0from
davidtranhp:merged_from_upstream_18_260131_01
Open

Merged from upstream 18 260131 01#1183
davidtranhp wants to merge 75 commits intoViindoo:18.0from
davidtranhp:merged_from_upstream_18_260131_01

Conversation

@davidtranhp
Copy link

Description of the issue/feature this PR addresses:

Current behavior before PR:

Desired behavior after PR is merged:


I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr

kaju-odoo and others added 30 commits January 26, 2026 02:05
closes odoo#245384

X-original-commit: 382d0dc
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
The official language is English, but Spanish is spoken by ~41 million.

task-5247124

closes odoo#245358

Related: odoo/enterprise#105246
Signed-off-by: Tiffany Chang (tic) <tic@odoo.com>
Issue:

Due to this bug, user's inbox can crash and become inaccessible by
another user.

Steps to reproduce:
1- Create a db with two companies and sale installed with demo data.
2- Demo user should only have access to company A
3- Demo user preference should be handle in Odoo
4- Admin should access both companies
5- Create a partner called partner_b with company set to company B
6- Using admin create a SO in company B, with the partner_b
7- Send a message (not internal note) in SO chatter,
   and mention Demo user
8- Login using Demo user
9- Open discuss app. As you see the inbox is not accessible anymore.

Cause:

This is caused because Demo user doesn't have read access to
partner_b. This cause issue in adding notification for partner_b.
https://github.com/odoo/odoo/blob/6e262e8cf7666216305a04f92c213578452fd652/addons/mail/models/mail_message.py#L1042-L1064

opw-5089738

closes odoo#232894

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
When sending a customer invoice via Peppol, the system
creates duplicate attachments (4 instead of 2 expected), cluttering
the chatter and the attachment sidebar.

This commit:
- Implements a search-and-update logic for attachments to ensure
idempotency (updates existing instead of creating duplicates).

task-5438951

closes odoo#245370

X-original-commit: be94b8a
Signed-off-by: Laurent Smet (las) <las@odoo.com>
Steps to reproduce:
- Set company to (AR) Responsable Inscripto
- In Accounting > Settings, choose Round per Tax as the rounding method.
- Go to Accounting > Taxes, duplicate IIBB WTH CABA 0%, and set Amount to 4.5%.
- Open partner ADHOC SA, in the accounting tab add the new tax in Purchase Withholding
- Create a new vendor Bill to vendor ADHOC SA with unit price 156,087.00
- Confirm and open Payment wizard

Issue:
Withholding amount is 7023.91, but it should be 7023.92

It occurs that the computed amount is 7023.915. Then when the
tax repartition values are computed, the value is rounded and rounding
difference are redistributed in the tax lines, so it seems the value has
been rounded down.

opw-5154585

closes odoo#241633

Signed-off-by: Laurent Smet (las) <las@odoo.com>
Issue:
Payment link should expire if payment is expired.

Steps to reproduce:
1- Create a new quotation.
2- Set the expiry date in the past.
3- Open the action menu and generate a payment link.
4- Open the payment link and pay.

Expected result: The payment should fail if the so is expired.

opw-5478691

closes odoo#245601

X-original-commit: 24b269f
Signed-off-by: Mohammadmahdi Alijani (malj) <malj@odoo.com>
Before 8c199f7, it was possible
to use the float widget with a monetary field in qweb (not used in
standard code).
By using something like:
```
<span
   t-field="o.amount"
   t-options="{
       'widget': 'float',
       'precision': o.currency_id.decimal_places
   }"
/>
```
where `amount` is a monetary field.
It worked as `precision` is defined in the options, which means that
`get_digits` was not called, so no errors were raised (the method only
exists for float fields).

Now that `min_precision` has been added, `get_min_display_digits` is
called if it is not set.
Which causes an error, as the method does not exist for monetary
fields.

As we are in stable, we cannot ask users to add a `min_precision` key
to their options, so the fix is to use `hasattr` to avoid calling a
method that doesn't exists.

closes odoo#245699

Signed-off-by: William André (wan) <wan@odoo.com>
Steps to reproduce:

- Drag and drop a Carousel.
- Add content to the first slide of the carousel to make the snippet
taller.
- Save the snippet as a custom snippet.
- Open the snippet dialog.
- Issue: The height of the preview for the saved snippet is forced to
550px, causing the snippet to be truncated.

After this commit, the height is no longer forced; it now adapts to the
snippet content.

task-5156137

closes odoo#244251

Signed-off-by: Francois Georis (fge) <fge@odoo.com>
**Description of the problem**
In the website editor, the user can manipulate the page in such a way to generate a
problematic `SelectionPlugin.activeSelection`, which still points to an existing
`anchorElement`, but has an invalid `offset`.

**How to reproduce**
This seems to be reproducible only on Chrome.
1. Enter in the website edit mode
2. Drop the `s_newsletter` snippet
3. Drop the `s_popup` snippet
4. Click on the popup, and delete it
5. Click on the blank space inside the `s_newsletter` snippet
6. Delete the `s_newsletter` snippet
7. The error occurs

Notes:
1. Snippet different than `s_newsletter` can be used to reproduce the problem, as
long as they contain a blank space.
2. It is important to make sure that the movement of the mouse pointer does not
trigger any preview when going from step 5 to step 6.

**Why the problem happens**
On Chrome, clicking on a blank area can cause `document.getSelection()` to return a
selection with a null `anchorNode.` When this happens, `SelectionPlugin.getSelectionData()`
will use the already existing `activeSelection` if `activeSelection.anchorNode` is still
connected. Before this commit, this method only checked that `anchorNode` was connected,
without validating offsets. This leads to the following edge case:
1. The user removes the `s_popup`
2. At this point, `document.getSelection()` would point to the `s_newsletter` snippet, so if the
user just deletes the snippet nothing bad would happen. But instead, if:
3. The user clicks on a blank area in `s_newsletter`, `document.getSelection()` will now return
a null `anchorNode`
4. The user delete the `s_newsletter` snippet, and `SelectionPlugin.getSelectionData()` is called
by an handler after the deletion
5. At this point: `document.getSelection()` has a null `anchorNode`, so the method will check if
`activeSelection.anchorNode` is still connected, WITHOUT validating the offsets.
6. Since `anchorNode` is still connected, this selection will be used, and an error will be
triggered shortly after, because the offset is too high (pointing to `s_popup` which does not
exist anymore).

**Fix**
After this commit, when `SelectionPlugin.getSelectionData()` checks that `activeSelection.anchorNode`
is still connected it also checks that the offsets are valid (meaning that they are smaller than the
number of nodes).

task-5430500

closes odoo#244331

Signed-off-by: Jinjiu Liu (jili) <jili@odoo.com>
…nsibility

Since this controller returns raw markup, it is impossible to inherit.
By splitting the controller `registration_new`, allows to manage custom
developments with the inheritance of the prepare method instead.

closes odoo#244156

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Steps to reproduce:
1. Install 'contact'
2. Create 501+ contacts (e.g. by duplicating existing one)
3. Select all contacts in list view and click Send Email (from Action menu)
4. Try to add an attachment

Issue:
- A traceback is raised in the mail composer:
`SyntaxError: Unexpected end of JSON input`

Cause:
`res_ids` is not set on the composer when more than 500 records are selected.
This is expected, as the compute method `_compute_res_ids()` does not write
`res_ids` when the number of active_ids exceeds 500 (to avoid storing large payloads on the field).
Because of this, the code trying to JSON.parse(res_ids) fails. see:
https://github.com/odoo/odoo/blob/abc8417413faf598fb83106de4328571d71888aa/addons/mail/wizard/mail_compose_message.py#L400

Solution:
- Fallback to context.active_ids when res_ids is not available

opw-5351374

closes odoo#238311

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Have a tourPointer somewhere on the main page -- eg on the app switcher
Open a dialog, eg Click on the My Profile menu

Before this commit, the tourPointer was visible above the modal, which
has nothing to do with the tour and creates inelegant noise.

After this commit, we hide the pointer if its trigger is not in the current active element.

task-5490670

closes odoo#243852

Signed-off-by: Bastien Pierre (ipb) <ipb@odoo.com>
…oretax

Description of the issue/feature this PR addresses:
This issue occured because in the previous update we add a condition to restrict multiple
tax groups excluding the STLG. Apparently there is a case where some users create their own
tax groups (for example for PPH) so when they want to print an efaktur it will raise an error.

Current behavior before PR:
If a user create their own tax with a new tax group (outside of the 6 groups defined in l10n_id)
and use it in invoice line along with one of the 6 tax groups excluding the STLG then the print
efaktur will be blocked because it will raise an error in the multiple tax groups check.

Desired behavior after PR is merged:
- The restriction in tax groups only applied for the 6 tax groups in l10n_id so if an invoice line
  has multiple tax groups as long as there no more than one of the 6 tax groups excluding the STLG then
  it should be able to print the efaktur.
- Also when building the efaktur coretax value, the new tax group should not be included in the regular_tax
  variable which will cause the value to be 11/12 of the original value.
- Add new condition to block the print efaktur if there is a tax inside the invoice but none of it
  belong to the 6 ppn tax groups (there is already a condition to block if no tax is given, but now since there
  are cases where they use tax group outside of the defined tax groups then it will print the efaktur)
- If an invoice line does not have any ppn_tax_groups but there are other line in the same invoice
  that has it then it will still be able to print the efaktur, but the line without the ppn tax will
  have the OtherTaxBase and VATRate set to zero which will calculate the VAT as 0 too.

5434656

closes odoo#244760

X-original-commit: d0af138
Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Signed-off-by: William Lucianto Santoso (wilu) <wilu@odoo.com>
Step to reproduce:
1. Install `sale_management`
2. Open any email template (e.g., Sale: Order Confirmation).
3. Add an attachment to it
4. Create a Sale Order, confirm it, and click "Send by Email".
5. In the mail composer, remove the template attachment

Issue:
- The removed attachment is deleted from the database (`ir.attachment`).
  Consequently, the attachment is permanently removed from the source Email Template
  and will not appear in future emails.

Cause:
- The `onFileRemove` function in `MailComposerAttachmentList` calls the `unlink` method
  of the `attachmentUploadService` for every file removed, without considering the existing template attachment.

Solution:
1. Update code to include `res_model` in `Attachment`
2. In `onFileRemove`, check the `res_model` of the attachment.
3. If the `res_model` is not "mail.compose.message", skip the database deletion (unlink)
   and only remove it from the composer view.

opw-5163679

closes odoo#238692

Signed-off-by: Julien Banken (jbn) <jbn@odoo.com>
Steps to reproduce the bug

- Create a storable product P1:
  - Tracking: Serial Number
- Log in as Marc Demo
- Create a sales order with 1 unit of P1
- Validate the delivery using serial number SN1
- Log in as Mitchell Admin
- Go to Settings:
  - Manage Users
    - Mitchell Admin
      - Sales: User: own documents only
- Go to the Serial Numbers list view:
  - Try to open SN1

Problem

An access error is triggered:

```
Uh-oh! Looks like you have stumbled upon some top-secret records.

Sorry, Mitchell Admin (id=2) doesn't have 'read' access to:
- Sales Order Line, S00025 - P1 (Deco Addict) (sale.order.line: 51)

Blame the following rules:
- Personal Order Lines
```

When clicking on SN1, the `stock.lot` form view.
it's contains the field "sale_order_count", which is a computed field
that needs to access all `sale.order` records using the serial number
in order to compute the count.

Since Mitchell Admin is restricted to his own sales orders only,
an access error is raised during the computation.

There is also a many2many view widget that triggers an access errors.
This widget can be removed since the smart button is now available.
The widget has already been removed in v19.

Solution

In this view, any stock user, admin or not, must be able to see how
many sales orders use a given serial number, regardless of whether
those sales orders belong to them or not.

opw-5400731

closes odoo#244570

Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
…nd preview

Steps to reproduce:
1. Install modules `sale_management` and `l10n_din5008_sale`
2. Go to Settings, Configure Document Layout and set layout to DIN 5008
3. Create a new Sale Order
4. Set a customer, add a product, and fill in Delivery Date (Other Info)
5. Click on Print or Preview

Issue:
The Delivery Date (commitment_date) is not displayed on:
- The DIN 5008 sale order report
- The sale order preview (portal view)

Functional experts confirmed that the Delivery Date must be visible when using
the DIN 5008 layout.

Cause:
The `commitment_date` field was not included in the DIN 5008 sale order report
template nor in the preview view.

Fix:
This commit adds the Delivery Date information to:
- The DIN 5008 sale order report template
- The sale order portal/preview view

opw-5490651

closes odoo#244917

Signed-off-by: Khushi Srivastava (khsr) <khsr@odoo.com>
Before this commit, on the partner form, it was possible to select
payment method lines (both inbound and outbound) that belonged to
archived journals. This allowed users to configure preferred payment
methods that should no longer be available.

This commit updates the domains for `property_outbound_payment_method_line_id`
and `property_inbound_payment_method_line_id` fields on the `res.partner`
model. It ensures that only payment method lines associated with active
journals [('journal_id.active', '=', True)] can be selected.

opw-5413309

closes odoo#240369

Signed-off-by: Maximilien La Barre (malb) <malb@odoo.com>
Issue:

When using negative amounts, for example to explicitly show a
discount, the tax calculation is incorrect due to the application of
the abs function. Furthermore, the way to find out if a tax is of the
withholding type is based on the sign of the value, which can lead to
error in these cases.

Cause:

A previous change (odoo#237235) added the abs function so the
'TotalTaxesWithheld' would be always with positive value. But this
also affects the calculation of taxes 'TotalTaxOutputs' in some cases,
such as if the invoice line has negative values.

Steps to reproduce:

- Install l10n_es_edi_facturae
- With the ES company, create an invoice with some standard lines
  and one line with negative amounts, as an explicit discount
- Confirm the invoice and send (facturae)
- Open the XML attached in the chatter
- Observe that the taxes amounts (VAT and WITHHOLDING) are erroneous

A correct invoice should be for example:

Product        Price       Taxes       Amount
---------------------------------------------
PRODUCT-A       1000    21%VAT 15%WHI    1000
Discount        -100    21%VAT 15%WHI    -100
---------------------------------------------
                       Untaxed amount     900
                      Withholding 15%    -135
                              VAT 21%     189
                      -----------------------
                                 TOTAL    954

closes odoo#244428

Signed-off-by: Antoine Boonen (aboo) <aboo@odoo.com>
On MRP production kanban, if the name of the
product is too long, `product_qty` and
`product_uom_id` fields on the card shrink and
become unreadable.

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

closes odoo#245861

Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
An error occurs when the product is not set in the repair move line, and
the Scheduled Date is being updated.

Steps to Reproduce:
- Install the Repairs module.
- Create a new Repair Orders.
- Add a product and confirm the repair.
- In the Parts tab, add a new line and change the demanded quantity without
  selecting a product.
- Update the Scheduled Date.

Error:
AssertionError: precision_rounding must be positive, got 0.0
ValueError: Expected singleton: uom.uom() (v19.0)

When move line has no `product_id`, its Unit of Measure (uom_id) is also empty.
Updating the scheduled date triggers a computation, which leads to the error.

closes odoo#244179

Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
CUPS has a limit on printer names of 127 characters, which means that if
a device has a very long device URI, it can exceed this limit and cause
an error when we try to add it to CUPS:

```
Failed to add printer 'dnssdPhotosmart%207520%20series%20%40%20Guillaume%E2%80%99s%20MacBook%20Air%20(2)_ipp_tcplocalcups?96d0de60-096c-3d08-5e2d-893393e10c2b'
Traceback (most recent call last):
  File "/home/pi/odoo/addons/iot_drivers/iot_handlers/interfaces/printer_interface_L.py", line 242, in set_up_printer_in_cups
    self.conn.addPrinter(name=device['identifier'], device=device['url'], **ppdname_argument)
    ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cups.IPPError: (1024, 'client-error-bad-request')
```

We fix this error by truncating the identifier to 127 characters
maximum.

closes odoo#245910

Signed-off-by: Louis Travaux (lotr) <lotr@odoo.com>
…ents

The "Not Sent" filter in Payments list view was not returning
the expected records. This was due to an incorrect domain condition
in the search view.

This commit updates the filter logic to properly identify payments
that haven't been processed or sent, ensuring the filter displays
the correct records to the user.

closes odoo#245487

Signed-off-by: Antoine Boonen (aboo) <aboo@odoo.com>
…e off

Steps to reproduce:
-------------------
1. Install `l10n_in` and `l10n_in_hr_holidays`
2. Switch to an Indian company
3. Create a user and related employee without Time Off rights
4. Log in with the new user and create a past time off
5. Approve the time off as an time off manager/admin
6. Open the validated time off record as the employee

Issue:
------
Opening a validated time off raises the following UserError:
"You must have manager rights to modify/validate a time off that already begun"

Cause:
------
The `_get_durations` method in `l10n_in_hr_holidays` was updating the
`l10n_in_contains_sandwich_leaves` field every time it was executed.

When a user opened a validated time off record, this triggered a `write()`
operation. Since non-manager users are not allowed to write on already
started validated leaves, this caused a UserError

The field `l10n_in_contains_sandwich_leaves` does not need to be updated when
`l10n_in_is_sandwich_leave` is False.

And this part of the code is responsible to update
`l10n_in_contains_sandwich_leaves` value.

Solution:
---------
Ensure that `l10n_in_contains_sandwich_leaves` is updated only when
`indian_leaves` is applicable.

opw-5373055

closes odoo#240056

Signed-off-by: Abdelrahman Mahmoud (amah) <amah@odoo.com>
Description of the issue/feature this PR addresses:

This PR fixes an incorrect domain construction when restricting records to the current recordset.
The existing code attempted to combine domains using expression.AND() but did not apply the result, and referenced an invalid domain field.

Current behavior before PR:

   - expression.AND() was called without assigning its return value, so the combined domain was never applied.
   - The domain condition used ('ids', 'in', self.ids), which is not a valid searchable field.
   - As a result, the intended filtering by the current recordset was silently ignored.

Desired behavior after PR is merged:

   - The domain is correctly rebuilt and assigned using expression.AND().
   - The filter uses the valid field instead of ids
   - Records are properly restricted to the current recordset

Part-of: odoo#242799
Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
closes odoo#242799

Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
When adding a product with never variant, their name and values are not translated in the language of the partner.

Steps to reproduce:
-------------------
* Activate the setting Variants and Variant Grid Entry.
* Create a the product , add a translation for its name.
* Create an attribute and a translation for its name, with variant create set to never.
* Create values for the attribute and add translation for their name.
* Add the attribute and it's values to the product.
* Create a contact and change it's language to the language of the translation.
* Create a purchase order set the contact as the vendor
* Add the product, and set the grid number to 1
-> the attribute and attribute value is not translated.

Observation:
-------------
When adding a product via the variant grid, the attribute and value names are added. For other attribute creation types, this information is retrieved directly from the product:
https://github.com/odoo/odoo/blob/f95bcc097fd7e70af8d28a66c010ae9b9490f439/addons/purchase/models/purchase_order_line.py#L283-L288
But in case of never attribute, the name it retrieved after and we don't set the context:
https://github.com/odoo/odoo/blob/f95bcc097fd7e70af8d28a66c010ae9b9490f439/addons/purchase_product_matrix/models/purchase.py#L173-L174
-> we retrieve the information but in the wrong language

opw-5396058

closes odoo#242692

Signed-off-by: Lancelot Semal (lase) <lase@odoo.com>
…e in mails

**Steps to reproduce:**
- Install Mass Mailing and Website apps
- Create a new mailing
- Add Columns block with different content size
- In "Vert. Alignment" field > Select the "Stretch to Equal Height" option
- Columns are properly aligned in Odoo
- Save the record and send test mail
- The columns are not aligned anymore in the received mail

**Issue:**
Inline styling breaks in mail engines due to `website.scss` file.
The `color-mix` css function is used and cast as a `color()` functional
notation in the columns `border-color`. The inline styling is then removed
by the mail engine (with all siblings attributes) as it is not compatible
with this notation.
(e.g. `border-color: color(srgb 0.129412 0.145098 0.160784 / 0.15);`)
The color normalization step doesn't take this into account as it only
checks for rgb patterns.

**Fix:**
Overwrite the css with the color notation by a default value
for mailing.

opw-5225248

closes odoo#242649

Signed-off-by: Julien Banken (jbn) <jbn@odoo.com>
Fix regression of participant fetch cron introduced in forward port
odoo#245038
Indeed self might be a record set in lots of different cases, which leads to users
at least 1 existing edi proxy user in their company, all future registrations will
fail

closes odoo#246054

Signed-off-by: Claire Bretton (clbr) <clbr@odoo.com>
Steps to produce:
- Install `sale_management` module.
- `Create a SO > Click on Preview > Sign and Pay`.
- Remove all text from the Full Name`.

Issue:
- The `Accept & Sign` button remains enabled even when the
  Full Name field is empty.

Root cause:
- At [1], When the `drawCurrentName` method is called, it retrieves text using
  `getCleanedName`. This method returns an empty string when no name is provided
- Despite this, the code still generates an image and passes it to `printImage`,
  which keeps the button enabled.

Solution:
- If the cleaned name is empty or contains only spaces, do not generate image.
- Instead, immediately clear the signature pad so the button remains disabled.

[1]: https://github.com/odoo/odoo/blob/9dedf75810bd6b7a92fe5bd279bf6bae98834750/addons/web/static/src/core/signature/name_and_signature.js#L103-L109

opw-5361890

closes odoo#238638

Signed-off-by: Bastien Pierre (ipb) <ipb@odoo.com>
Steps to reproduce:

- In the settings enable: Batch, Wave & Cluster transfers
- Inventory > Configuration > > Warehouse Management > Operation types
- Enable Auto-batches, Batch grouping by partner on Delivery orders
- Create and confirm a delivery for 2 units of a storable product that
  you do not have in stock.
- Change the quantity of the move to 1 unit
> The delivery is not auto-batched

Expected behavior:

As the delivery becomes ready a batch transfer containing your delivery
should be created. This is by the way what happens if you had at least
1 unit in stock when you confirm the deliver.

Cause of the issue:

The auto-batching is suppose to be applied on assigned pickings via the
`_find_auto_batch` method:
https://github.com/odoo/odoo/blob/604d07ab324caa5f3aa6f3baa9902c2137ea24db/addons/stock_picking_batch/models/stock_picking.py#L194-L198
That being said a picking is only batchable if it is Ready hence his
state is 'assigned'. Now, the issue is that the `_find_auto_batch` is
only callable in two places in our workflow:
First at confirmation:
https://github.com/odoo/odoo/blob/604d07ab324caa5f3aa6f3baa9902c2137ea24db/addons/stock_picking_batch/models/stock_picking.py#L138-L142
Which will fail in our case but wokrs in the use case where you have at
least one unit in stock since the delivery is respectively not
"assigned" or "assigned" at this point. And, else, wehn the sate of a
move of the delivery is assigned:
https://github.com/odoo/odoo/blob/604d07ab324caa5f3aa6f3baa9902c2137ea24db/addons/stock_picking_batch/models/stock_move.py#L30-L38
Now, the only issue with this call is that the picking becomes assigned
if a move is partially assigned:
https://github.com/odoo/odoo/blob/604d07ab324caa5f3aa6f3baa9902c2137ea24db/addons/stock/models/stock_picking.py#L841-L845
But since the move is not "assigned" but only "partially_vailable"
this will not trigger a call of the `_find_auto_batch`.

opw-5441718

closes odoo#245542

Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
tau-odoo and others added 23 commits January 30, 2026 05:07
carrier type

After the user clicks on "Validate" button to validate the mobile barcode,
the carrier type selection is disabled and the carrier type pass to the
SO is None.

This commit fixes the issue by instead of disabling the carrier type
selection, we just set the input box of carrier number to readonly
and set back the carrier number to not readonly when the user changes
the carrier type to ensure the carrier number input is editable.

Also update some labels to be more user readable.

task-5880421

closes odoo#246053

Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
The _add_consolidated_invoice_base_lines_vals method computed the gross
subtotal using `price_unit * quantity`. When taxes are configured as
"Included in Price", `price_unit` contains the tax-included amount, but
`total_excluded` (used for the discounted amount) is tax-excluded.

This caused the tax amount to be incorrectly reported as an AllowanceCharge
(discount) in the MyInvois XML, because:
  discount_amount = price_unit * qty - total_excluded
                  = tax_included - tax_excluded
                  = TAX AMOUNT (not a discount!)

Example: Product priced at 110 MYR with 10% tax included:
- price_unit = 110 (tax-included)
- total_excluded = 100 (tax-excluded: 110 / 1.10)
- discount_amount = 110 - 100 = 10 ← incorrectly reported as discount

refs:

The cac:AllowanceCharge element in UBL is specifically for discounts and
surcharges, NOT for taxes. According to the Peppol Malaysia e-Invoice
specification:

https://docs.peppol.eu/poac/my/pint-my-sb/bis/#_allowances_and_charges

https://docs.peppol.eu/poacc/billing/3.0/codelist/UNCL5189/ (For this case we are interested in code 95)

Steps to Reproduce:
1. Configure a tax as "Included in Price" with Malaysia tax type
2. Create a product with that tax.
3. Create POS orders without any discount
4. Generate consolidated invoice and XML
5. XML incorrectly shows <cac:AllowanceCharge> with tax amount as discount

The fix uses `raw_total_excluded / discount_factor` (always tax-excluded)
instead of `price_unit * quantity` (may be tax-included), consistent with
the parent method:
https://github.com/odoo/odoo/blob/d645361a95037ac580d55e80bcb61d1eeb293efd/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py#L1846-L1876

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

closes odoo#245535

Signed-off-by: Nicolas Viseur (vin) <vin@odoo.com>
Since Chrome 144 disabled [^1] by default the WebGL fallback to the
software renderer SwiftShader, this commit reenables [^2][^3] it when
running in headless mode to allow to keep testing WebGL features (i.e.
image filters in website builder).

Note: the SwiftShader implementation is considered deprecated and less
safe than proper hardware based ones, hence not recommended for a
regular usage with untrusted content. However, as tests are run in a
more controlled environment, it looks reasonnable to opt-in to keep
actually testing WebGL features.

[^1]: https://chromium-review.googlesource.com/c/chromium/src/+/7128438
[^2]: https://issues.chromium.org/issues/476172421
[^3]: https://chromestatus.com/feature/5166674414927872

closes odoo#246380

X-original-commit: 1ac64d1
Signed-off-by: Pierre Paridans (app) <app@odoo.com>
Currently, the proxy_client_user is neutralized as demo.
But the edi_mode is set to test.
It's confusing for the users, and we should be consistent.

closes odoo#246300

X-original-commit: 4250485
Signed-off-by: Claire Bretton (clbr) <clbr@odoo.com>
Steps to reproduce:
1. Install `marketing_card`
2. Create a card campaign
3. Set Recipient, Post Link and Post Suggestion
4. Save and Preview
5. Copy the URL and replace `preview` with `redirect`
6. To reproduce in locale,  in the `contoller` make the
   marketing_card.card_campaign_crawler template the only return
7. Now paste the URL

Issue:
The `<meta property="og:description">` tag is empty in the inspect. It does not contain any content

Cause:
The controller `card_campaign_redirect` passes the campaign's
suggestion text to the view using the key `post_text`. However, the
template `card_campaign_crawler` attempts to access
`post_suggestion`, which is not present in the rendering context.

Solution:
Update the controller to pass `post_suggestion`

opw-5351041

closes odoo#238534

Signed-off-by: Damien Abeloos (abd) <abd@odoo.com>
We already wrap _PolicyBase.clone() to validate override keys and keep
policy objects predictable when composed dynamically. This commit makes
policy addition use the same API so incorrect inputs fail earlier,
avoiding hard-to-debug issues.

task-5871798
Issue:
Due to this issue, there is a traceback, in express stripe checkout
when there is a 100% discount and shipping cost.

Steps to reproduce:
1- Setup `Stripe` as the only payment provider in the db.
2- Create a discount code with 100% discount on order.
3- Set a fixed price on the delivery method.
4- On shop, add a product to cart, and then enter the discount code.
5- Refresh the page.

There is a traceback.

Cause:
This issue is introduced after odoo#209103, which set `minor_amount` to
amount excluding delivery. In the case it's 0, it's not going to be
rendered on express_checkout view as it is false.

Which cause a traceback here:
https://github.com/odoo/odoo/blob/8f7e3d588c6c1189e64442a33037666d5d70aae7/addons/payment_stripe/static/src/js/express_checkout_form.js#L73-L81

opw-5482646

closes odoo#246355

Signed-off-by: Valeriya Chuprina (vchu) <vchu@odoo.com>
- Adjusting the hrextac xmlns to the updated one
- Adjusting MER payment report button to not show incorrectly
- Improving error handling for MER payment reporting
task-none

closes odoo#246083

Signed-off-by: Antoine Dupuis (andu) <andu@odoo.com>
Backport of odoo@71de690

A UserError there can cause duplicates in peppol fetching.
It should never block an ack.
We can leave them unlinked
We also do the same for any unexpected error that occurs after we've created the move.

opw-5492092

closes odoo#246475

Signed-off-by: Claire Bretton (clbr) <clbr@odoo.com>
Issue:
Due to this issue, `coupon_ids` which are never used are still shown
in loyalty coupons history which is confusing for users.

Steps to reproduce:
1- Create two promotions:
   - Promo A: 10% discount
   - Promo B: 20% discount
2- Create a SO and add a line. Then confirm the SO.
3- Click on `Reward` button.
4- A dialog should show both promos. Discard the dialog.
5- Navigate to `Discount and Loyalty`.
6- Open Promo A and B and you can see both have lines with
   `coupon_id.order_id` = `created SO` which is confusing. `Issue 1`
7- Navigate back to SO. Click on `Reward` and select Promo A, apply.
8- Navigate to Promo B. As you see the the `coupon_id` related to
   the SO is still there. `Issue 2`

Cause and Fix:
This is due to unlinking `coupon_ids` only in SO confirm action,
causing this issue on already confirmed SOs:
https://github.com/odoo/odoo/blob/604d07ab324caa5f3aa6f3baa9902c2137ea24db/addons/sale_loyalty/models/sale_order.py#L132-L136

We can fix this issue by `unlinking` the `coupons_ids` when a reward
is applied or the diaolg is discarded.

However there are 2 limitations:
1- The view needs to be updated. Otherwise, `coupon_ids` will not be
   deleted upon clicking on `discard` button. However the fix is
   still stable.
2- What if the dialog is closed with the cross button or the tab is
   closed without selecting a reward? In that case the issue will
   still persist.

To fix these issues, we can show only used `coupon_ids` in
`loyalty_coupon_id` list view. However that cannot be done in
stable as it requires `use_count` to be stored.
NB: With some complex filters this also could be fixed on stable but
not worth it.

opw-5424753

closes odoo#245534

Signed-off-by: Louis Tinel (loti) <loti@odoo.com>
When pos_event was added, a difference in behavior with the existing
registration flow in website_event was missed. When answering an
'identification question' (name, email, phone, company_type) with the
'once per order' enabled, the values should be used and propagated
directly on the created event.registration records, with precedence
over other answers given to individual questions (not once per order)

STEPS
=====

1. Create a new event with name, email questions, once per order ticked.
2. Go to POS (reload data if needed)
3. Register and answer both questions
4. Continue the pos flow until both registrations are created
5. Go to backend > your event > registrations
6. You can see that even if the answers are propagated in the o2m field
registration_answer_ids, which is expected, the attendee's name and
attendee's email fields are empty. They should contain the values of step 3.

FIX
===

Align the website_event flow and precedence of OPO questions over
individual answers in pos_event. Now, the first non-null answer of an OPO
question will be used for each of the question_type values listed above,
if any, over answers to individual questions.

Also align the fact that after OPO answers, precedence should be given
to the first non-null answer to a given question type for identification
questions, and not the last as it is currently.

Task-4919080

closes odoo#231502

Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
1. Create a product with FIFO - automated costing method
2. Initial quantities updated 2 with the unit value 7. (2*7) =14
3. Create purchase order with 1 unit and price 10
4. Add this product into the repair order (as a line) > Validate the repair
5. Create a sale order from the repair order
6. Settle this sale order from the POS > Invoice the order

Expected behavior:
A cogs for 7$

Current behavior:
A cogs with 8$( std price )

It happens because the stock.move are linked to the repair order and not
generated from the PoS. So the cogs value can't be retrieve in the usual
way. In order to fix it, we check the move linked to the sale.order if
there is no move generated by the pos.

closes odoo#241286

Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
…en two days in hourly accrual plans

Issue:
Attendances overlapping on two days are ignored for hourly accrual plans based on attendances.

Steps to reproduce:
- Install 'hr_holidays_attendance'
- In Time Off > Configuration > Accrual Plan, create a new plan
	- Based on worked time
	- Hourly rule
	- Attendances as Source
- In Management > Allocations, create an allocation for an employee using the new accrual plan
- Create an Attendance for this employee in the period of the Accrual Plan
	- Check-in at 22pm for example
	- Check-out at 7am
- Run the cron "Accrual Time Off: Updates the number of time off"
- The Allocation ignores the worked time from the attendance

Cause:
`_get_accrual_plan_level_work_entry_prorata()` is called on each day of the accrual period.
So `start_dt` is `datetime.datetime(2026, 1, 2, 0, 0)` and `end_dt` is `datetime.datetime(2026, 1, 3, 0, 0)` for example.
This means that the search will always excludes attendances overlapping on two days.

https://github.com/odoo/odoo/blob/26f3026ed45cc409cd7f67fa219d44f1adbac9b7/addons/hr_holidays_attendance/models/hr_leave_allocation.py#L79-L83

Solution:
To count the attendances on several days, we need to split these attendances by day because `_get_accrual_plan_level_work_entry_prorata()` is only called with an interval of one day from midnight to midnight.

First we get all attendances overlapping with the day by changing the domain in the search.

Then we could simply take the difference between `max(attendance.check_in, start_dt)` and `min(attendance.check_out, end_dt)` but we also need to remove the lunch breaks (they were not counted in `attendance.worked_hours`).
This would mean duplicating the code present in `_compute_worked_hours()`.
To avoid this we create a new method for `hr.attendance` named `_get_worked_hours_in_range()`. That returns the number of hours worked due to this attendance in a given time frame.
This new method can be used in both cases to get the needed value.

opw-5172669

closes odoo#246381

X-original-commit: ea27f58
Signed-off-by: Mélanie Peyrat (mepe) <mepe@odoo.com>
Signed-off-by: Mathieu Coutant (mcou) <mcou@odoo.com>
Issue:
The odoo#244061 changes, the expired so leads to warning message.
However, the batch `res_id` is used instead of single record which is
an error.

opw-5478691

closes odoo#246399

X-original-commit: ca4d74c
Signed-off-by: Mohammadmahdi Alijani (malj) <malj@odoo.com>
Previously, it was assumed that if no 'error' or 'errors' key was present
that means we've received a valid response for obtaining CCSID or PCSID.

But sometimes the error is not sent with those keys, and the binarySecurityToken
is missing, therefore a traceback is shown to the user because the invalid
requests passes through the validation unnoticed. This kind of response is
the result of a new change introduced by zatca requiring csr fields to be
at most 64 characters long.

This commit improves the error handling mechanism of CSID responses, to show
the user an informative message, and handles the length check for csr fields
on the client side before sending to zatca.

task-5347269
opw-5350082

closes odoo#246343

X-original-commit: 15e1f51
Signed-off-by: Florian Gilbert (flg) <flg@odoo.com>
Signed-off-by: Omar Khalid (khom) <khom@odoo.com>
On large databases (millions of account moves), The FEC exported file can be huge.
This resulted in memory error since at some point we have the entire file in memory.

This commit aims to overcome this issue by streaming the content of the file to the user.

task-5404142

closes odoo#246005

X-original-commit: 0fdb1b2
Related: odoo/enterprise#105716
Signed-off-by: Ali Alfie (alal) <alal@odoo.com>
Signed-off-by: Ahmad Almaghraby (alah) <alah@odoo.com>
8c199f7 introduced minimum precision
for float fields, but it has a display issue.

Steps to reproduce:
- create an invoice, set the price of an an invoice line to `9417.2`
-> the web client displays `'9,417.200000000001'`

Issue:
In case of a minimum precision, the precision was set to 12.
But it should be dynamic in regards to the number of integer digits.

Solution:
The precision is set to 6 digits, but if the number of significant
decimal digits is lower, then it is set to that number.
The number of significant decimal digits is computed using:
15 - number of integer digits.
--

Also implementing the same logic in qweb.

To reproduce:
- create a an invoice with an invoice line of `300000000031.3`
- post and print
-> the price unit on the pdf shows "300,000,000,031.300232"

opw-5880951

closes odoo#246347

Related: odoo/documentation#16201
Signed-off-by: William André (wan) <wan@odoo.com>
Issue:
Due to this issue, website designer cannot optimize seo on category.

Steps to reproduce:
1- Create a `eCommerce Category`.
2- In demo user, set Sale access to `All Documents` and Website
   access to `Editor and Designer`.
3- Login with demo user and navigate to website.
4- In shop page, open category.
5- From site tab, click on `Optimize SEO`. You get access error.

Expected: You should be able to optimize seo with
`Editor and Designer` access.

Cause:
The user needs write access on record in order to optimize seo:
https://github.com/odoo/odoo/blob/ec5da99ca3f52420e7d973c3cf07167bd4104ffa/addons/website/controllers/main.py#L831-L834

opw-5443854

closes odoo#244724

Signed-off-by: Mohammadmahdi Alijani (malj) <malj@odoo.com>
…on values

Currently, an error occurs when a company-dependent selection field
(e.g. invoice sending method) keeps a value after the related module is
uninstalled.

Steps to Reproduce:
1. Install the Accounting app.
2. Disable 'Snailmail' from settings.
3. Send any invoice, make sure wizard Print & Send has selected "by Post" option.
4. Click on the Send button.

Error:
AssertionError

Cause:
Fields defined with `company_dependent=True` are stored as property fields
rather than regular values. In PostgreSQL, these fields are stored as JSONB
values keyed by company id.

When a selection value is removed (e.g. during module uninstallation), it
attempts to compare the JSONB column directly with a string value,
resulting in an invalid comparison and triggering the error. - [1]

Fix:
Update the SQL query to extract the value for the active company using
JSON operators (->>), ensuring correct comparison with the expected
selection value.

[1]: https://github.com/odoo/odoo/blob/92a9f6b19670685dfe9fb1714bf01449768e5f62/odoo/addons/base/models/ir_model.py#L1812-L1815

sentry-6970900918

closes odoo#241248

Signed-off-by: Chong Wang (cwg) <cwg@odoo.com>
- Added new fields to res.company to handle key, certificates and session numbers
- Added new fields to account.move to track KSeF status, session, reference number, attachments, errors.
- Updated the frontend view of the move and the settings. Some fields are debug-view only.
- Implemented the sending method with `account.move.send`, storing the xml attached to the move.
- Implemented the APIs to communicate securely with the KSeF
- Implemented the Check Sending and Download UPO functionality
- Implemented the rendering of the FA(3)-compliant XML structure.
- Implemented a cron to update invoice KSeF statuses.
- Implemented locking so cron and manual don't mess up with each other.
- Set as `auto-install` for those who have the Polish localization.
- Wrote minimal tests for basic use cases (to be expanded).
- Added `neutralize.sql` script to avoid leaking sensitive data when copying a database for support
- Added module to `.weblate.json` to make this i18n-able

task-4728713

closes odoo#230988

Signed-off-by: William André (wan) <wan@odoo.com>
@viinbot
Copy link

viinbot commented Jan 31, 2026

@davidtranhp Viindoo Test Suite has failed!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.