Wednesday, February 18, 2026
18 changes · saas-19.1
Enhancements to existing features
This update simplifies how product containers are handled on the website, making it easier for developers to customize and extend the shopping experience. Previously, changes required extensive modifications, now a dedicated method allows for simpler, more flexible updates without impacting the core functionality. This enhances future compatibility and reduces maintenance efforts.
Original PR description
The product_container element may vary across modules and cannot be hardcoded. Modifying it currently requires overriding the entire add_to_cart method, which reduces flexibility and maintainability. This change extracts the product_container logic into a dedicated method, making it easier to extend and customize without duplicating the full add_to_cart implementation. This ensures better forward compatibility and modular extensibility. Enterprise PR: https://github.com/odoo/enterprise/pull/107343 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update resolves an issue where document previews weren't appearing in the chatter after editing activities and attaching new documents. The fix, originally developed for a related framework component, has now been fully implemented within the Mail module, ensuring accurate document previews are displayed.
Original PR description
Description: Previously, when editing an existing activity and attaching new documents from the user’s device, the edits were saved correctly, but the document previews were not displayed in the chatter. This issue had already been addressed by the framework editor team; however, their fix was not applied to the Mail module. In this PR, we apply the existing framework fix to the Mail module to restore document preview functionality. related PR: https://github.com/odoo/odoo/pull/240114 task-5423808 Forward-Port-Of: odoo/odoo#243805
This update corrects a bug where applicants were seeing job postings from different companies within the recruitment process. The system now ensures that job listings displayed are only those belonging to the applicant's company, improving the accuracy and usability of the application search. This change enhances the applicant experience and reduces potential confusion.
Original PR description
[FIX] hr_recruitment: prevent showing jobs from different company than applicant belongs Bug production steps: Select My Belgium Company -> Recruitment -> Applications -> All applications -> Create new application -> In the job position field, many jobs can be seen that are belong to other companies from applicant company Bug cause: In the previous domain for job_ids, it should be either False (can belongs to many companies) or should be the company that our applicant belongs to. Bug solution: Convert the domain such that it only lists the jobs that the job company and applicant company are same. Also, company_id field made visible when >= 2 companies are selected in the environment. task - 5498859 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 Forward-Port-Of: odoo/odoo#244072
This update corrects a bug where duplicate activities were created on purchase orders when a sale order was cancelled, specifically within the dropshipping feature. The fix ensures that the correct template is only triggered when a purchase order originates from a sale order for a product, preventing unnecessary activity and streamlining the process.
Original PR description
**Steps to Reproduce** * Install `sale_management`, `purchase`, and `stock` with demo data. * In Inventory → Settings, enable `Dropshipping`. * Create a product: * Set a vendor under the Purchase…
**Steps to Reproduce**
* Install `sale_management`, `purchase`, and `stock` with demo data.
* In Inventory → Settings, enable `Dropshipping`.
* Create a product:
* Set a vendor under the Purchase tab.
* Set routes to `Dropshipping` and `Buy`
* Create and confirm a sale order for this product.
* Confirm the generated purchase order.
* Cancel the originating sale order.
* Go back to the linked purchase order.
**Observed behavior**
* Two activities are created on the purchase order when the sale order is cancelled.
**Cause**
* Both templates — `exception_on_so` (from sale_stock) and
`exception_purchase_on_sale_cancellation` (from sale_purchase)
are triggered during sale order cancellation.
* Each module overrides `_action_cancel` and triggers its corresponding exception template.
* When both modules are installed, both templates run.
https://github.com/odoo/odoo/blob/98da30375a5ae50a77d848b838781aa7247bd362/addons/sale_purchase/models/sale_order.py#L26-L32
https://github.com/odoo/odoo/blob/98da30375a5ae50a77d848b838781aa7247bd362/addons/sale_stock/models/sale_order.py#L206-L208
* The template `exception_purchase_on_sale_cancellation` should only be triggered
when the PO originates from an SO and the product is a service, but
the domain lacks the required product-type condition.
**Fix**
* Add the missing condition to ensure that `exception_purchase_on_sale_cancellation`
is not triggered for dropshipped products, preventing duplicate activities.
---
`NOTE` - This issue is resolved from version 19.0 in this [commit](https://github.com/odoo/odoo/pull/212679/changes/ede2898278220a3ba4d8910ef268fe59f1587c72)
---
opw-5153488
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#239569This update fixes a potential issue where abrupt system clock changes could disrupt IoT driver jobs, leading to delays and errors. The system now automatically detects and adjusts schedules to prevent misfires, ensuring consistent operation of custom IoT handlers. This enhances the reliability of the IoT system.
Original PR description
Before this commit: If IoT system clock is wrongly set (happened on a Wi-Fi environment with slow connection). The system clock will abruptly change for a date in the future which will trigger all…
Before this commit:
If IoT system clock is wrongly set (happened on a Wi-Fi environment with slow connection). The system clock will abruptly change for a date in the future which will trigger all `schedule` jobs (which will think they are several days late).
In addition to this oversight, on an IoT on which "custom IoT handlers" configuration is enabled, if the `upgrade.check_git_branch` job is called on IoT boot, it will trigger the following traceback:
```py
2026-02-17 13:53:41,751 1371 ERROR ? odoo.addons.iot_drivers.exception_logger: Exception in thread Thread-4:
2026-02-17 13:53:41,757 1371 ERROR ? odoo.addons.iot_drivers.exception_logger: Traceback (most recent call last):
2026-02-17 13:53:41,758 1371 ERROR ? odoo.addons.iot_drivers.exception_logger: File "/usr/lib/python3.13/threading.py", line 1043, in _bootstrap_inner
self.run()
~~~~~~~~^^
2026-02-17 13:53:41,759 1371 ERROR ? odoo.addons.iot_drivers.exception_logger: File "/home/pi/odoo/addons/iot_drivers/tools/helpers.py", line 50, in run
service.server.restart()
~~~~~~~~~~~~~~~~~~~~~~^^
2026-02-17 13:53:41,759 1371 ERROR ? odoo.addons.iot_drivers.exception_logger: File "/home/pi/odoo/odoo/service/server.py", line 1622, in restart
os.kill(server.pid, signal.SIGHUP)
^^^^^^^^^^
2026-02-17 13:53:41,759 1371 ERROR ? odoo.addons.iot_drivers.exception_logger: AttributeError: 'NoneType' object has no attribute 'pid'
```
Which will prevent the IoT to restart thus to load custom handlers
After this commit:
Brutal time changes (of 10 minutes (in a 3-second loop)) are detected, and jobs schedules are updated to prevent misfire callsThis update resolves an issue where the 'Mark as Paid' button was hidden for users in Mexico when the l10n_mx_hr_payroll_account module was installed. This change ensures the standard payment flow is clear and functional for Mexican users, improving their experience.
Original PR description
The "Mark as Paid" (action_payslip_paid) button on the hr.payslip form view [is hidden](https://github.com/odoo/enterprise/blob/19.0/hr_payroll_account/views/hr_payslip_views.xml#L39) when the l10n_mx_hr_payroll_account module is installed, making the standard payment flow confusing for users in Mexico. target: 19.0 task-5434674 Forward-Port-Of: odoo/enterprise#104390
This update fixes a bug where customers could still redeem expired ewallet points. The change ensures that ewallet points are no longer available for claiming after their expiration date, improving the accuracy of point balances and preventing potential revenue loss. This resolves issue OPW-5476686.
Original PR description
### Issue: Due to this issue, ewallet points are claimable after expiry. #### Steps to reproduce: 1- Create a ewallet program, and generate an ewallet for a partner. 2- Set the expiration date in the past. 3- Create a SO with the same partner. 4- Click on reward. Expected: The ewallet shouldn't be claimable. Current outcome: The ewallet is claimable. opw-5476686 Forward-Port-Of: odoo/odoo#248931 Forward-Port-Of: odoo/odoo#247740
This update fixes a bug preventing embedded videos from showing correctly within shopfloor work order instructions. The issue stemmed from a previous fix being lost during a code refactor, and the original solution has now been reapplied. This ensures that video instructions are displayed as intended, improving visual guidance for shop floor operations.
Original PR description
Issue ----- Embedded videos are not displayed in the shopfloor. Steps to reproduce ----- - Create a BOM with at least one operation - Create an instruction in the work order operation - In the instruction text, add a video link - Create a MO and plan it - Open the work order in shopfloor - Open the instruction > Empty window, no video Cause ----- Fix of 61fdab3 got lost in some refactor, so reapplying the logic. ----- Ticket: opw-5926557 Forward-Port-Of: odoo/enterprise#107538
This update resolves an issue where the "Order Now" button disappeared in the self-order mobile interface after deleting or paying for an order. The fix ensures that order updates are correctly reflected in both the mobile and POS UIs, improving the customer experience and order management.
Original PR description
**Issues:** 1. Order deleted from backend When a self-order is deleted from the backend, the customer self-order UI is not updated, causing the “Order Now” button to be missing. 2. Order sent and…
**Issues:**
1. Order deleted from backend When a self-order is deleted from the backend, the customer self-order UI is not updated, causing the “Order Now” button to be missing.
2. Order sent and paid from POS UI Steps:
- Create a self-order from mobile
- Load the order in the POS UI
- Add additional items (eligible for preparation)
- Proceed to payment and validate
- Click Order in the Send for preparation popup Problem: After order validation, the customer self-order UI is not refreshed and the “Order Now” button does not reappear.
**Fixes:**
- Ensures order deletion triggers notify calls to refresh both POS and self-order UIs
- Synchronize deleted orders with the customer self-order UI
- Fix the case where setting Service at = `Table` and Pay after = `Meal` in a single operation resets Pay after to `each`.
Task-5373116
Related: https://github.com/odoo/enterprise/pull/103052
Forward-Port-Of: odoo/odoo#248844
Forward-Port-Of: odoo/odoo#240523This update ensures that the preparation display in the backend accurately reflects changes when a POS order is cancelled or deleted. Specifically, related preparation orders and data are now correctly removed, preventing outdated information and improving data consistency.
Original PR description
**In this commit:** Ensure the preparation display UI is updated when a POS order is cancelled or deleted from the backend. - On order cancellation, the preparation display is refreshed accordingly. - On order deletion, related preparation orders, lines, and states are removed via notify call. Task-5373116 Related: https://github.com/odoo/odoo/pull/240523 Forward-Port-Of: odoo/enterprise#107522 Forward-Port-Of: odoo/enterprise#103052
This update resolves an issue where the website editor would crash after saving changes in Safari and Epiphany. The problem stemmed from outdated event listeners being attached to the parent window, causing conflicts when the iframe reloaded. This fix ensures the editor receives the correct, current service object, improving stability and reliability.
Original PR description
Steps to reproduce: =================== 1. In Website > Shop, open any product. 2. Click "Edit" on the product. 3. Make a change (for example, toggle "Zoom on click") 2 times. -> In the second time a…
Steps to reproduce:
===================
1. In Website > Shop, open any product.
2. Click "Edit" on the product.
3. Make a change (for example, toggle "Zoom on click") 2 times.
-> In the second time a traceback will appear `(Safari, Epiphany)`.
Cause:
======
The website builder uses two contexts:
- The **iframe** runs services (e.g. websiteEditService)
- The **parent window** runs editor plugins (e.g. EditInteractionPlugin)
They communicate via custom events on window.parent.document. The service (in the iframe) registers a listener for
"edit_interaction_plugin_loaded" on the parent document, and responds with a "transfer_website_edit_service" event carrying its service object.
When the iframe reloads after a save, the old listener was never removed from window.parent.document. The new iframe added a second listener. This meant two listeners existed on the parent document:
1. Old listener → responds with OLD websiteEditService (stale)
2. New listener → responds with NEW websiteEditService (correct)
Both fire when the plugin dispatches "edit_interaction_plugin_loaded". But the plugin only accepts the first response ({ once: true }), and since listeners fire in registration order, it always received the OLD stale service.
With the stale service:
- installPatches() early-returned (patches.length > 0 from session 1)
- destroy() called uninstallPatches() on the old service, removing stopInteractionByName from the old prototype
- stopInteraction() then tried to call the now-deleted method → crash: TypeError: publicInteractions.stopInteractionByName is not a function
Solution:
=========
Extract the anonymous event handlers into named functions and register a "beforeunload" listener on the iframe's window that removes them from window.parent.document. This ensures that when the iframe reloads, the old listeners are cleaned up before the new iframe registers its own, so the plugin always receives the current service.
opw-5864798
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#248042This update corrects a bug where the 'CFDI to Public' checkbox was incorrectly checked when creating new invoices in the Mexican accounting module. The fix ensures this checkbox remains unchecked until a customer is selected, preventing incorrect public invoice generation. This improves compliance and accuracy for Mexican businesses using Odoo Enterprise.
Original PR description
Steps to produce: --- - Install `l10n_mx` and `accountant` modules. - Switch to a Mexican company. - Go to Accounting > Customers > Invoices. - Click on New to create a new invoice. Issue: --- - The `CFDI to Public` checkbox is automatically checked even when no customer is selected. Root cause: --- - Here at [1], the field l10n_mx_edi_partner_address_complete evaluates to False when no partner is set. - Due to the OR condition, this causes l10n_mx_edi_cfdi_to_public to be set to True, even though no partner has been selected yet. Solution: --- - We should only evaluate partner address completeness when a partner is explicitly set. - Also, add VAT check for `l10n_mx_edi_partner_address_complete`, as requested by mial(PO). [1] https://github.com/odoo/enterprise/blob/cc00e8f3bb75b8c782fea3a42ad3bbcdbc240e2f/l10n_mx_edi/models/account_move.py#L649 opw-5911542 --- Forward-Port-Of: odoo/enterprise#106943
This update fixes an issue where the MTO replenishment route was incorrectly suggested by default. The change ensures the system correctly identifies the appropriate replenishment route based on product vendor information, improving the efficiency of stock replenishment processes. This impacts the purchase and stock modules.
Original PR description
*mrp,purchase_mrp,stock Issue ----- MTO gets suggested by default as the replenishment route for products. Steps to reproduce ----- - Enable routes - Unarchive MTO - Create a product with a vendor…
*mrp,purchase_mrp,stock Issue ----- MTO gets suggested by default as the replenishment route for products. Steps to reproduce ----- - Enable routes - Unarchive MTO - Create a product with a vendor and MTO route - Open the replenishment wizard > The default/suggested replenishment route is MTO Cause ----- When creating the widget, we go through its' `default_get` to set its' default route https://github.com/odoo/odoo/blob/310897cf07ebbf484ea6877fb329215e45c481d7/addons/stock/wizard/product_replenish.py#L76-L77 the domain is computed by `_get_route_domain`, which in turn calls `_get_allowed_route_domain` https://github.com/odoo/odoo/blob/310897cf07ebbf484ea6877fb329215e45c481d7/addons/stock/wizard/product_replenish.py#L165-L170 However, since we are creating a new, it does not have a `warehouse_id` yet, so we don't go into the `if` condition. https://github.com/odoo/odoo/blob/310897cf07ebbf484ea6877fb329215e45c481d7/addons/stock/models/stock_replenish_mixin.py#L26-L39 We only get routes from the product, but since buy is set on the warehouse and not the product anymore, it doesn't get included. Solution ----- There is an override of `_get_route_domain` in `purchase_stock` https://github.com/odoo/odoo/blob/310897cf07ebbf484ea6877fb329215e45c481d7/addons/purchase_stock/wizard/product_replenish.py#L91-L96 it filters out the buy route if there is no `seller_ids` for the product, but since the buy route cannot be a part of the domain anymore, the condition should be changed to include buy if the product has a seller. Note: `_get_route_domain` is only ever called in `default_get`. Other changes ----- The same change is also applied for the manufacture route, as the logic is the same. It makes no sens to include route that do not lead to an internal location. ----- Ticket: opw-5388728 Forward-Port-Of: odoo/odoo#246304
This update fixes an issue where loyalty rewards weren't correctly calculated when products were ordered in quantities other than the standard unit. Previously, orders using multiples of the base unit (like dozens) didn't trigger the discount. This change ensures that loyalty rewards are accurately applied regardless of the product's unit of measure, improving the customer experience and discount accuracy.
Original PR description
### Issue: Due to this issue, applying a different uom than unit one, will not apply the reward regarding to quantities. #### Steps to reproduce: 1- Create a program: buy 12 get 6 free. 2- Create a SO, add a dozen of product to SOL. 3- Click on reward. Expect: 6 free unit is added. Current outcome: Nothing is added. Unless you add 12 dozens which is going to add 6 units. ### Cause: In checking rules, `product_uom_qty` is directly used without conversion to quantity. Note: `test_different_uom_to_hours_on_sale_order_confirmation` is failing due to this fix, because the uom_id unit/dozens and hours/days are not compatible. As this is not possible in UI, IMO we can delete the breaking SOL in that test. opw-5913638 Forward-Port-Of: odoo/odoo#248527 Forward-Port-Of: odoo/odoo#247743
This update fixes a memory error that occurred when calculating standard deviation and average for quality points. By disabling a data fetching process and focusing on only two key fields, the system now handles larger datasets more efficiently, preventing crashes and improving performance. This change impacts the Quality Control module.
Original PR description
Before this commit, computing the `standard_deviation` and the `average` of a `quality.point` involved fetching all the quality checks and all their fields. This can cause a memory error because of the field called `notes` that might involve HTML code. To avoid this, I have disabled the prefetcher since we only need two fields for the computation (`x_quality_state` and `measure`). The benchmark done below involved a recordset of quality points of size 1000 and the average size of the `notes` field was 6MB. The recordset was ordered by the size of the note section descending and for the different test cases it was sliced by the $K$ top elements and the compute function was triggered on the sliced version. | Scenario | Before | After | | :--- | :--- | :--- | | 100 | Memory LIMIT | 289.0MB | | 200 | Memory LIMIT | 290.0MB | | 500 | Memory LIMIT | 292.0MB | | 1000 | Memory LIMIT | 331.0MB | Forward-Port-Of: odoo/enterprise#106493
This update fixes an issue where multi-employee payslips were defaulting to the language of the first employee. The change ensures that each employee's payslip is printed in their correct, selected language, improving accuracy and user experience. This resolves a previous bug related to date formatting and language selection within the payroll system.
Original PR description
Steps to detect the bug: - Install payroll - Create more than one employee with different payslip languages - Add a contract for the employees - Payroll -> Payslip -> Pay run - Create a new payroll for more than one employee - Select all the employees in the pay run - Click 'print' button - Dates for the employees that are not the first one are in the language of the first employee This commit will allow the user to create multiemployee payslips maintaining the correct selected payslip language for each one of them. The issue was caused by a cache dictionary that used only the date and date format as a key, failing to include the user language. This led the system to reuse the first translated date for all subsequent employees. opw-5865260 Forward-Port-Of: odoo/enterprise#107269 Forward-Port-Of: odoo/enterprise#106575
This update reverts a recent change that was causing all upsell quotes to be canceled and disrupting legitimate business processes. The issue stemmed from a technical error in how quotes were handled, specifically related to alternative quotes and a faulty action call. This fix ensures upsell quotes function as intended.
Original PR description
…mmit/55b6bbe27cc31abcaee40cd4a196e087fdfd4ce5 This commit introduced an issue. All upsell quote were canceled and no filtering was done on "alternative quotes". As a result it could disrupt legit business flow. Moreover, action_cancel was called instead of _action_cancell which can lead to ValueError: Expected singleton as action_cancel can require single record sometimes. Forward-Port-Of: odoo/enterprise#107503 Forward-Port-Of: odoo/enterprise#107417
This update addresses a recent finding that the Mexican SAT now accepts accented characters in tax documents. Previously, the system automatically removed accents to align with SAT practices. This change temporarily allows the ‘É’ character, and further investigation is underway to determine the full extent of accepted accents.
Original PR description
An improvement in September (PR #95207) began removing accents from names in documents sent to the SAT, in order to comply with their own practices. In recent months, it has become clear that the SAT…
An improvement in September (PR #95207) began removing accents from names in documents sent to the SAT, in order to comply with their own practices. In recent months, it has become clear that the SAT does accept accents sometimes. First with umlauts on the `ü` in October (PR #96043), then all umlauts in February (PR #106557). As this PR has found another accepted accented character `É`, it may be necessary to undo the original improvment entirely. The [Anexo 20 Guía de llenado de los comprobantes fiscales digitales por Internet](http://omawww.sat.gob.mx/tramitesyservicios/Paginas/documentos/Anexo_20_Guia_de_llenado_CFDI.pdf), pg 17, indicates that accented characters are maintained in legal names. At least, `Í` is allowed. At this point in time I only added the exception for `É`. Steps to reproduce are [on the ticket](https://www.odoo.com/mail/message/999357619), as it requires a real person's tax information. [opw-5915515](https://www.odoo.com/odoo/project.task/5915515) ---- *Edit: Miguel (mial) confirmed that names are not always sanitized, but that we expect them to be.* Forward-Port-Of: odoo/enterprise#107677