Friday, February 20, 2026
16 changes · saas-18.4
Resolved issues and error corrections
The website editor now prevents images and similar content from being dropped into invalid areas that could later cause an error. This improves editing reliability for product descriptions and other website content by enforcing the intended placement rules.
Original PR description
Steps to reproduce the issue: ================================= 1. Go to Website > Products and edit a product. 2. In the product description, add a header using the editor. 3. You can now drop an…
Steps to reproduce the issue: ================================= 1. Go to Website > Products and edit a product. 2. In the product description, add a header using the editor. 3. You can now drop an image in that place, so drop it. 4. Click on the image and try to add an anchor for it. -> Traceback Cause: ====== The reason an image can be dropped in that location is because the editor added an adjacent element, such as a `<p>` or `<h1>`, which is considered a valid drop zone by the drop zone plugin. However, when trying to create a link, the parent element checks if it is valid to have an anchor, but then when adding an anchor the element text is undefined, causing a traceback. Why can an image be dropped in that location after adding the editor? The bug was due to passing `excludeNearParent` as a property name instead of `excludeParent` to the `getSelectorSiblings` function, which always evaluated to false. So it allowed dropping images in invalid locations. Solution: ========= Pass the correct property name. Impact: ======= This fix enforces the intended dropzone behavior where content snippets (like images, buttons with `.o_snippet_drop_in_only`) cannot create dropzones next to elements that are direct children of `.oe_structure` containers. Test Changes Required: ======================= The button tests were failing after the fix because they were testing buttons as direct children of `<div id="wrap" class="oe_structure oe_empty">`. This was only working before due to the bug - `excludeNearParent` was being ignored. The fix wraps the test buttons in a `<div>` container, making them children of a child of `.oe_structure` rather than direct children. opw-5489444 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures by-products from manufacturing are stored in the correct child location of their intended destination, instead of sometimes defaulting to an unrelated storage area. It helps prevent inventory from being routed to the wrong place when multiple warehouse views and putaway rules are involved.
Original PR description
Steps to reproduce ----- - Enable locations & by products - Create 4 locations - View A of type view (parent: Stock) - View B of type view (parent: Stock) - Storage A of type internal location…
Steps to reproduce ----- - Enable locations & by products - Create 4 locations - View A of type view (parent: Stock) - View B of type view (parent: Stock) - Storage A of type internal location (parent: View A) - Storage B of type internal location (parent: View B) - Create a "Manufacture to A" route - Rule 1: Manufacture, Stock -> Stock - Rule 2: Push To, Internal Transfer, Stock -> View A - Create a "By Products to B" route - Rule 1: Push To, Internal Transfer, Stock -> View B - Create a "Bonus" product with route "By Products to B" - Create a "Finished" product with route "Manufacture to A" - BoM with "Bonus" as by product - Create a MO for Finished, and produce it - Open the linked transfers' list view - Open the "Bonus" transfer > "Destination Location" states View B - Open the line's details (hamburger button) > "Store To" states View A/Storage A Cause ----- When retrieving the location in https://github.com/odoo/odoo/blob/26dbbdaf460a91ef4b33392c27a28951d5de2c57/addons/stock/models/stock_move_line.py#L280-L282 we pass `locations` as a context key. The problem is that `locations` contains the childs of **all** of the SMLs' locations https://github.com/odoo/odoo/blob/26dbbdaf460a91ef4b33392c27a28951d5de2c57/addons/stock/models/stock_move_line.py#L260 This means that, in `_get_putaway_strategy`, when no `putaway_location` is found, we end up defaulting to the first element of the list https://github.com/odoo/odoo/blob/26dbbdaf460a91ef4b33392c27a28951d5de2c57/addons/stock/models/stock_location.py#L370-L371 which might not be a child of the location. Solution ----- By removing the context key, locations get populated as such https://github.com/odoo/odoo/blob/26dbbdaf460a91ef4b33392c27a28951d5de2c57/addons/stock/models/stock_location.py#L328-L330 This is ok because we know the call to `_get_putaway_strategy` is made on a single record (`sml.move_id.location_dest_id`) so the default will correctly be a child of said location. ----- Ticket: opw-5359945 Forward-Port-Of: odoo/odoo#249262 Forward-Port-Of: odoo/odoo#247403
This fix prevents invoices from crashing when a tax repartition line is configured with a negative percentage. Instead of an unexpected error during invoice creation, the accounting app can surface the intended validation behavior for invalid tax configuration.
Original PR description
Steps to reproduce: - Install `account` module - Taxes > open any existing tax > Set `factor_percent(%)` of repartition lines to negative(eg:…
Steps to reproduce: - Install `account` module - Taxes > open any existing tax > Set `factor_percent(%)` of repartition lines to negative(eg: [Image](https://www.awesomescreenshot.com/image/58851592?key=ce0017bb467a583ad020f33d21d4d8ba)) - Create a Invoice and add tax in move line and save Traceback: `IndexError: list index out of range` We are getting `factors` as empty because `target_factors` from `_add_accounting_data_to_base_line_tax_details` is empty. This happens because, in `tax_reps`, we are filtering repartition lines with a `factor` greater than `0`. However, when the `factor` is less than `0`, `tax_reps` becomes empty, which leads to the error. We are reverting this PR: https://github.com/odoo/odoo/pull/234334 because it prevents the validation error from being raised when there is a negative value in the repartition lines. [factors]: https://github.com/odoo/odoo/blob/de056cc784a3bbe2575fd3c9e81ca62e73c362d4/addons/account/models/account_tax.py#L1641 [tax_reps]: https://github.com/odoo/odoo/blob/de056cc784a3bbe2575fd3c9e81ca62e73c362d4/addons/account/models/account_tax.py#L2429-L2431 sentry-7102210210 Forward-Port-Of: odoo/odoo#249220
This fix prevents shipping costs from being counted twice when customers use Stripe express checkout options such as Apple Pay or Google Pay. It ensures the final checkout total shows the correct delivery amount, reducing overcharges and payment confusion.
Original PR description
Versions: --- - 17.0+ Issue: --- Delivery amount is doubled in stripe express payment checkout. Steps to reproduce: --- 1- Setup a stripe payment express checkout. (In my client case it is apple pay…
Versions: --- - 17.0+ Issue: --- Delivery amount is doubled in stripe express payment checkout. Steps to reproduce: --- 1- Setup a stripe payment express checkout. (In my client case it is apple pay express checkout but we also reproduced it in google pay) 2- Set fixed price on standard delivery: 10 3- Navigate to website: add a product to cart. Use express checkout. Outcome: The delivery price is calculated twice which is wrong. Cause: --- This regression is due to #238574. Once `/compute_taxes` is called, there is delivery lines included in SO. As a result returning `amount_total` will cause `this.paymentContext['minorAmount']` to include delivery amount. Then we add delivery carrier `minorAmount`: https://github.com/odoo/odoo/blob/469220cde82ecebf4a59451cc1325add6bfc3e69/addons/payment_stripe/static/src/js/express_checkout_form.js#L188-L196 Which cause delivery amount be added twice. Fix: --- We could exclude delivery amount from total amount in `express_checkout_shipping_address_compute_taxes`, which is going to calculate the tax for lines excluding delivery lines. opw-5424398 Forward-Port-Of: odoo/odoo#249340 Forward-Port-Of: odoo/odoo#248415
Tasks created from a sales order will now be detached from that sales order when their sales order item is removed, allowing users to make the task temporarily non-billable or link it to a different order later. Field service tasks keep their sales order link so materials can still be added to the existing order.
Original PR description
Currently, a task remains linked to its original sales order even when it has no sales order item. This prevents users to not bill a task and temporarily detach it from a sales order until it can be…
Currently, a task remains linked to its original sales order even when it has no sales order item. This prevents users to not bill a task and temporarily detach it from a sales order until it can be linked to a new one. **Steps to produce:** * Install Sales, Project * Products > Virtual Home Staging > Create On Order > Project and Task * Create and confirm quotation with that product. * Tasks > Empty the Sale Order Item Field **Observed Behavior:** * Sale Order is still linked to the task despite sale order line has been unlinked from that task. **Root cause:** * Compute method [1] only detaches the sale order if the customer has been changed. **Solution:** * Only detach the sale order when there are no sale order items and the record is not a field service task. * Field service tasks should always keep the sale order linked so materials can still be added to the existing sale order, even when the task is non-billable (i.e., no sale order line is linked). This logic is handled by the compute override at [2], which reassigns the sale order when needed. [1]: https://github.com/odoo/odoo/blob/3f4e45ecaca46a98c904536658728a1f1571bdbd/addons/sale_project/models/project.py#L916-L935 [2]: https://github.com/odoo/enterprise/blob/6658581828dcdc43ffc5823814a05cb936cd0500/industry_fsm_sale/models/project_task.py#L178-L194 Related Enterprise PR: https://github.com/odoo/enterprise/pull/103487 opw-5215989 Forward-Port-Of: odoo/odoo#249107 Forward-Port-Of: odoo/odoo#241446
Peppol invoice processing now uses the company linked to the invoice or EDI user when creating related records. This prevents default values from another company being applied, reducing cross-company errors and failed invoice processing.
Original PR description
Currently, the created move does not always use the company context of the related move/proxy user. As a result, default values may be taken from another company, which can lead to cross-company inconsistencies and access errors. Steps to reproduce: - Set up two companies, A and B - In company A, configure a default value for the partner.company_id field, applicable only to company A - When a Peppol invoice arrives for company B but is processed using the context of company A, and a new partner must be created, the partner is created with company A as the default value - This results in an incompatible companies on record error This fix ensures that the company context of the move or EDI user is used when creating the move, preventing cross-company issues. opw-5473233 Forward-Port-Of: odoo/odoo#249409 Forward-Port-Of: odoo/odoo#249059
The Time Off balance report now only counts allocations that apply to the selected reporting period. This prevents future or out-of-period allocations from inflating an employee’s displayed remaining leave balance, giving managers more accurate planning information.
Original PR description
The balance report aggregates allocations regardless of the period in which they occur resulting in wrong information when an employee has two allocations in different periods and a filter is used in the report Steps to reproduce: 1. Install Time Off app 2. Open Time Off app and go to Management > Allocations 3. Create a new allocation of 100 days for employee "Mitchell Admin" of time off type "Paid Time Off" with a validity period from 01/01/2027 to 31/12/2027 and approve it 4. Activate debug mode 5. Go to Time Off > Reporting > Balance 6. The number of days left for "Mitchell Admin" for "Paid Time Off" is 120 days even though the default filter is on the period of 2026 Solution: Refactor the entire query: we order the allocations by date_from so we can subtract taken leaves from the allocations in that order opw-5156142 Forward-Port-Of: odoo/odoo#249334 Forward-Port-Of: odoo/odoo#245860
Spanish Facturae invoice XML now rounds euro amounts to two decimal places where required by regulation, preventing validation failures when invoices are submitted. This helps businesses avoid rejected electronic invoices caused by overly precise amount fields.
Original PR description
Steps to reproduce: - Have facturae modules installed - Generate invoice with any amount - Send to Facturae Issue: Resulting XML has 8 digits after the decimal point on several fields, such as unit…
Steps to reproduce: - Have facturae modules installed - Generate invoice with any amount - Send to Facturae Issue: Resulting XML has 8 digits after the decimal point on several fields, such as unit price, gross amount, and total cost. When trying to validate such an XML, this results in validation error: "RCF06001: En facturas emitidas en euros, alguno de los importes de las líneas tiene más de dos decimales (regla 6a del anexo II de la Orden HAP/1650/2015)." According to regulation HAP/1650/2015 [1]: For invoices issued in euros, it will be validated that the total line amounts related to the total cost are numeric and rounded, according to the common rounding method, to two decimal places. This commit introduces dynamic decimal precision: 2 places for EUR and 8 places (the previous default) for other currencies. [1] https://www.boe.es/diario_boe/txt.php?id=BOE-A-2015-8844 Machine translated [BOE-A-2015-8844 (1).pdf](https://github.com/user-attachments/files/25345382/BOE-A-2015-8844.1.pdf) opw-5927356 Forward-Port-Of: odoo/odoo#248882
Belgian electronic invoices now include the required registry identifier scheme, improving compliance with Peppol billing rules. The update also prevents an error when creating Dutch party legal information without registry or endpoint details, making e-invoice generation more reliable.
Original PR description
1) This commit adds the new generic methods to build an UBL file. The big objective is to remove the hierarchy of UBL later on and make BIS3 completely standalone. In this commit, BIS3 is not independent of UBL 2.1 & 2.0. 2) Missing schemeID for Belgium Company registry Since https://github.com/odoo/odoo/commit/d40652c17b43b6a9fd4d19ce84b943b2a51fad9c, in Belgium, we set by default the company registry. However the schemeID is missing and should be part of the ISO 6523 ICD list: https://docs.peppol.eu/poacc/billing/3.0/codelist/ICD/ 3) Fix PartyLegalEntity when the country is NL and there is no company registry/EAS/Endpoint That case was raising a traceback before this commit. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#246377
Odoo now avoids creating duplicate vendor bills when a Peppol invoice import hits an error after the bill has already been saved. This helps businesses keep accounts payable records cleaner and prevents extra work correcting duplicated invoices.
Original PR description
When importing invoices, if an error occurs in `_peppol_import_invoice`, Odoo crashes before acknowledging the already created bills. But, since `rollbackable_transaction` is used in `_extend_with_attachments`, the invoice is already committed. Since the acknowledgement is not sent while the invoice is committed, the next `_peppol_get_new_documents` attempt duplicates the invoice. opw-5937044
Expense report PDFs now skip encrypted receipt files that cannot be merged, instead of failing with an error. The report includes a note explaining why the file was skipped, helping users complete reporting while preserving visibility into missing attachments.
Original PR description
**Steps to reproduce:** - Install hr_expense - Create an expense - Attach several receipts with at least one encrypted PDF - Create Report - From cog menu, print "Expenses Report" **Issue:** A traceback is raised while trying to add the attachments to the report: 1) With a version of PyPDF2 lower than 2.12.1 (e.g. 1.26.0), a PdfReadError is raised: "File has not been decrypted". 2) With version 2.12.1 of PyPDF2, if PyCryptodome library is not installed, a DependencyError is raised: "PyCryptodome is required for AES algorithm". **Cause:** The encrypted file cannot be appended to the report PDF. **Solution:** Skip encrypted files and log a note with the reason in the report. opw-5194501 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#249365 Forward-Port-Of: odoo/odoo#248869
This update resolves an issue where tasks remained linked to sales orders even without associated order items, preventing users from properly billing tasks. The change ensures tasks can be cleanly detached from sales orders when no items are linked, streamlining billing processes and improving task management. This fix maintains the ability to add materials to existing sales orders for field service tasks.
Original PR description
Currently, a task remains linked to its original sales order even when it has no sales order item. This prevents users to not bill a task and temporarily detach it from a sales order until it can be…
Currently, a task remains linked to its original sales order even when it has no sales order item. This prevents users to not bill a task and temporarily detach it from a sales order until it can be linked to a new one. **Steps to produce:** * Install Sales, Project * Products > Virtual Home Staging > Create On Order > Project and Task * Create and confirm quotation with that product. * Tasks > Empty Sale Order Item Field **Observed Behavior:** * Sale Order is still linked to the task despite sale order line has been unlinked from that task. **Root cause:** * Compute method [1] only detaches the sale order if the customer has been changed. **Solution:** * Only detach the sale order when there are no sale order items and the record is not a field service task. * Field service tasks should always keep the sale order linked so materials can still be added to the existing sale order, even when the task is non-billable (i.e., no sale order line is linked). This logic is handled by the compute override at [2], which reassigns the sale order when needed. [1]: https://github.com/odoo/odoo/blob/3f4e45ecaca46a98c904536658728a1f1571bdbd/addons/sale_project/models/project.py#L916-L935 [2] https://github.com/odoo/enterprise/blob/6658581828dcdc43ffc5823814a05cb936cd0500/industry_fsm_sale/models/project_task.py#L178-L194 Related community PR: https://github.com/odoo/odoo/pull/241446 opw-5215989 Forward-Port-Of: odoo/enterprise#107716 Forward-Port-Of: odoo/enterprise#103487
This update resolves an issue where users could inadvertently assign partners from different companies when managing multiple companies. The change ensures that partners are correctly associated with the intended company, improving data accuracy and streamlining accounting processes. This fix enhances the reliability of financial reporting across our enterprise solutions.
Original PR description
Before this commit, it was possible to add a partner that was from another company when multiple companies were selected. task-5941113 Forward-Port-Of: odoo/enterprise#107546
This update resolves an issue preventing early bill printing with the Italian fiscal printer. The fix addresses a traceback caused by incorrect data handling during the printing process, ensuring receipts are now printed correctly when the 'early print' option is enabled. This improves the restaurant's ability to efficiently manage and print customer bills.
Original PR description
Fix 1: ------- Using the early receipt printing option leads to a traceback when using the italian fiscal printer. Steps to reproduce: ------------------- * Setup the italian fiscal printer for a…
Fix 1:
-------
Using the early receipt printing option leads to a traceback when using the italian fiscal printer.
Steps to reproduce:
-------------------
* Setup the italian fiscal printer for a restaurant
* Enable Early Receipt printing
* Open restaurant
* Open a table, add an item to cart
* Try the early print option
> Observation: Traceback
Why the fix:
------------
Initially the traceback is related to trying to read `decimal_places` out of undefined. The current order doesn't have yet a currency.
To solve this initial issue we can just take the currency of the config if there's none on the order. The pos does not handle multicurrency so the order will always have the same currency as the config anyway.
After solving this part another issue would still happen. If the order was no sent to the kitchen yet. Such orders are not yet synced to the backend and do not have an id of type number. If the order had been send to the display.
This scenario was sending the printer, the data to print and with a successful print we were trying to sync data to the server with
```
await this.data.write("pos.order", [order.id], updateData);
```
which was triggering an error in `orm_services` with `validatePrimitiveList`.
> Invalid ids list: pos.order_4
If we try to reprint AGAIN the bill for some reason, we get another traceback. It's because the nb_print is now 1 and therefore we now try to print with
```
printResult = await this.fiscalPrinter.printContentByNumbers({
order: order,
});
```
which will try to split undefined here
```
this.receiptNumber = this.props.order.it_fiscal_receipt_number;
const dateParts = this.props.order.it_fiscal_receipt_date.split("/");
```
Those two last issues are solved by not syncing the data to the server when we simply print the bill early.
-------
-------
Fix 2:
-------
Currently the early printing option does not work as desired. The fiscal printer does not print the receipt.
Steps to reproduce:
-------------------
* Setup the italian fiscal printer for a restaurant
* Enable Early Receipt printing
* Open restaurant
* Open a table, add an item to cart
* Try the early print option
> Observation: the printer stops in the middle of printing the receipt
Why the fix:
------------
The early receipt was trying to be printed as a fiscal document. However it cannot be considered as such.
We backport this fix that enables basic receipt printing and alter it to also work with early printing.
Fix being backported: https://github.com/odoo/enterprise/commit/b8fd13b802729ccee080ab14f2958d59f57d0f97
There are a few differences between the early receipt and the basic print, mainly the fact that prices need to be shown on the early receipt.
There are a few differences with the original commit. In the documentation of the printer, `printNormal` uses data and the original commit mixes between `data` and `message` so it is harmonized here.
opw-5387572
Results:
-----------
Basic receipt:
<img width="672" height="835" alt="image" src="https://github.com/user-attachments/assets/3de96523-22db-4a27-adbd-3464802604aa" />
Early receipt:
<img width="658" height="842" alt="image" src="https://github.com/user-attachments/assets/f6b7ab24-e27b-4deb-8d5f-1b0c41bb28f0" />
Forward-Port-Of: odoo/enterprise#107720
Forward-Port-Of: odoo/enterprise#105511This update fixes a compatibility issue with the Dutch tax (OB) and ICP report templates. It replaces outdated taxonomy data with the final 20251210 NT20 taxonomy, ensuring successful processing of these reports by the Digipoort system. This ensures accurate reporting for Dutch tax compliance.
Original PR description
Update the Dutch tax (OB) and ICP report templates from the 20251210.a pre-release to the final 20251210 NT20 taxonomy to ensure successful processing by Digipoort. Fixes: https://github.com/odoo/enterprise/commit/5becacff48f1a2490ce2f57a4679020615b6b8c2 opw-5911496 Forward-Port-Of: odoo/enterprise#108126
This update ensures that timesheet entries with excessively large negative hour values (over six digits) are now properly flagged as errors. Previously, these entries could be added without warning, leading to potential data inaccuracies. This fix maintains data integrity by enforcing consistent hour limits across all timesheet entries.
Original PR description
Currently, a user can add a timesheet entry with a negative Hours Spent value `exceeding six digits`. **Steps to reproduce:** - Install the `timesheet_grid` module. - Open the `Timesheets` app and click `Add a line`. - Set Hours Spent to a `negative` value with more than six digits (e.g., -1000000). **Observation:** The line is added without any warning, whereas entering a positive value with more than six digits correctly raises an `error`. **Root cause:** At [1], the constraint validates only positive values exceeding six digits. As a result, negative values with more than six digits are not checked and bypass the `UserError validation`. **Fix:** This commit updates the constraint to ensure the six-digit limit applies to both positive and negative values. [1]: https://github.com/odoo/enterprise/blob/660905872909405c0a07a8317b4eb0a42e5854ca/timesheet_grid/models/analytic.py#L46-L49 opw-5909417 Forward-Port-Of: odoo/enterprise#106781