Thursday, February 12, 2026
16 changes · saas-18.3
Enhancements to existing features
This update improves the customer-facing display in Point of Sale by automatically showing the correct currency symbol (like '$' or '€') alongside the total amount and change. This change is required to meet certification standards and ensures a more professional and accurate presentation of prices for our customers.
Original PR description
This PR adds the currency symbol on the customer display for point of sale for the total amount + change. (formatted based on the currency, e.g. $ before, eur after the amount) This is required by the scale certification Before: <img width="777" height="604" alt="image" src="https://github.com/user-attachments/assets/28688075-b387-477a-930d-410f1107cc83" /> After: <img width="787" height="638" alt="image" src="https://github.com/user-attachments/assets/724a1360-78a7-4630-a034-e115dd09f057" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247674 Forward-Port-Of: odoo/odoo#247591
Resolved issues and error corrections
This update replaces the SFU (Server Fast Update) bundle with the latest version (v1.3.3). This ensures Odoo continues to operate efficiently and reliably by addressing potential performance issues and incorporating the newest features from the SFU project.
Original PR description
https://github.com/odoo/sfu/releases/tag/v1.3.3 Forward-Port-Of: odoo/odoo#246979 Forward-Port-Of: odoo/odoo#244971
This update resolves an issue that occurred when users attempted to process ZATCA OTP requests with an 'SA Company' setup where the company's street address was not entered. The fix corrects a data type error, ensuring the system correctly handles missing street information and prevents a crash.
Original PR description
This error occurs when attempting to set the "OTP" received from "ZATCA". Steps to reproduce: - Install `l10n_sa_edi` module > Switch to `SA Company` - Go to `SA Company` and remove `Street` - Journals > Open journal with type 'Sale' > ZATCA > Onboard Journal > Enter any OTP > Request Traceback: `TypeError- value argument must be a str` At [1], the error occurs because the company has an empty street field, causing the value argument to be a `boolean` instead of the expected `string`. [1]- https://github.com/odoo/odoo/blob/40a0b44231fd9a725ccf3667c4992e691e24cde7/addons/l10n_sa_edi/models/certificate.py#L71 sentry-7185302332 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243525
This update resolves a potential error that could occur when loading images in the Odoo system. The change ensures the system waits longer for image updates, preventing a sporadic issue caused by encoding delays. This improves the reliability of image display for users.
Original PR description
Encoding the data to base64 can take some times. Before this commit we used this code: ```js await runAllTimers(); await animationFrame(); ``` Now we explicitly wait for the change to happen as awaiting an animation frame can't be enough. runbot-error-237568 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248166
This update fixes an error that occurred in the Point of Sale module when a unit of measure (like 'Pack of 6') was deleted. The POS module relies on these UoM records, and without them, it couldn't properly load. This ensures the POS module functions correctly even after users manage their unit of measure settings.
Original PR description
Currently, an error is produced when loading the pos module when a referenced UoM record (e.g., Pack of 6) has been deleted by the user.
**Steps to Reproduce:**
- Install Sales Module.
- Enable **"Units of Measure & Packaging"**.
- Delete the **"Pack of 6"** Units.
- Install POS.
**Error:**
```
ParseError:
while parsing /home/odoo/src/odoo/saas-19.1/addons/point_of_sale/data/point_of_sale_data.xml:38, somewhere inside <record id="uom.product_uom_pack_6" model="uom.uom">
<field name="is_pos_groupable">True</field>
</record>
Exception:
Cannot update missing record 'uom.product_uom_pack_6'
```
The POS module overrides `uom.product_uom_*` records. If the original UoM record has been deleted, the override fails because the record no longer exists.
sentry-7237815280
Forward-Port-Of: odoo/odoo#246940This update fixes a bug where combo product prices weren't accurately calculated when a combo included no free items. The change ensures that the total price of combo products is now correctly computed, improving the accuracy of sales reporting and customer billing. This resolves an issue reported in opw-5241225.
Original PR description
If a combo product is configured with no free item, the parent product's price was not computed in total correctly. opw-5241225 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue preventing custom JavaScript code added to the website from functioning properly. A recent change in how Odoo handles JavaScript files meant the system no longer recognized custom scripts, leading to errors. This fix ensures that custom JavaScript modifications are correctly applied to the website.
Original PR description
[FIX] website: enable custom javascript on website Steps to reproduce the problem: - Go to the "HTML/ CSS Editor". - Go to the JS tab. - Uncomment the example and save. -> Problem: the confirmation…
[FIX] website: enable custom javascript on website Steps to reproduce the problem: - Go to the "HTML/ CSS Editor". - Go to the JS tab. - Uncomment the example and save. -> Problem: the confirmation dialog does not appear. The problem is that since [1], `/* @odoo-module */` has been removed from the file as since [2], js files in `/static/src` and `/static/tests` are considered as odoo module without the need of the annotation `odoo-module`. In order to understand the problem, here is a summary of what happens when a custom js code is saved; - An attachment is created with the custom js code. - An asset is created to replace the user custom rules of `user_custom_javascript.js` by the one of the newly created attachment. Because the url of the newly created attachment looks like `/_custom/web.assets_frontend_lazy/website/static/src/js/user_custom_javascript.js`, the transpiler does not recognize it as an odoo module. task-5925607 [1]: https://github.com/odoo/odoo/commit/6d2fda172ec9cc7642abe9625ca486c7769e8297 [2]: https://github.com/odoo/odoo/commit/5f2c505836002ac7851c29c28d612f721d467bc4 Forward-Port-Of: odoo/odoo#247959
This update prevents the deletion of attachments when removing them from email templates. Previously, removing an attachment from the mail composer would permanently remove it from all future emails. The fix ensures attachments remain associated with templates, maintaining consistent email content.
Original PR description
**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…
**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 `mailComposerAttachmentList` to include `res_model` in `relatedFields` so it is fetched from the server. 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 Forward-Port-Of: odoo/odoo#245886 Forward-Port-Of: odoo/odoo#238692
This update resolves a technical issue that caused Odoo module updates to fail with an error when encountering certain field types. The fix adds a check to ensure only 'selection' and 'reference' fields are processed, preventing crashes and ensuring smoother updates. This improves stability and reliability during module updates.
Original PR description
Description of the issue/feature this PR addresses: Fix AttributeError that occurs during module updates when processing selection field deletions. Current behavior before PR: When updating modules, an `AttributeError` occurs when trying to access the `ondelete` attribute on fields that are not Selection fields: AttributeError: 'Char' object has no attribute 'ondelete' Desired behavior after PR is merged: Add validation to check if the field type is 'selection' or 'reference' before attempting to access field.ondelete as a dictionary. Skip processing for incompatible field types to prevent AttributeError. @moduon MT-13588 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247971
This update resolves an issue where the website's redirection process was losing URL parameters, causing errors and incorrect behavior. The fix ensures that all parameters are properly encoded during redirection, maintaining data integrity and preventing errors when users interact with the website.
Original PR description
Scenario from 17.0:
- set domain on website
- go to website /website/force/1?path=%2F%3Fa%3Db%26c%3Dd with another
domain
=> you are redirected to {domain}/?a=b instead of {domain}/?a=b&c=d
Scenario from 18.0:
- set domain on website
- go to /appointment/1 on other domain, select person date and time
- click on "Editor"
=> you get error:
> TypeError: AppointmentController.appointment_type_id_form() missing 1
> required positional argument: 'duration'
Cause: the /website/force/ domain redirection doesn't encode the
parameter when redirecting, so we lose parameters after the first one.
Fix: encode parameters when redirecting domain in /website/force/ route.
opw-5441957
Forward-Port-Of: odoo/odoo#247679
Forward-Port-Of: odoo/odoo#242252This update resolves a rare issue where the popover animation in tests finished too quickly, leading to additional steps and test instability. By adjusting the animation timing, this fix ensures tests run reliably and consistently, improving overall software quality. This change focuses on internal test stability.
Original PR description
Because the popover had his animation enabled in tests, it could in very rare occasion end too fast and call it's finished callback, triggering extra repositionning (and thus extra expect.steps). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247341 Forward-Port-Of: odoo/odoo#244491
This update fixes an issue where the duration of quick-created calendar events wasn't accurately reflected after manual adjustments. The change ensures that the displayed duration always matches the intended length, improving event management accuracy. This aligns with previous versions of Odoo.
Original PR description
Currently, an incorrect duration is displayed when the start or end time is `manually changed` during event creation. **Steps to reproduce:** - Install the `Calendar` module and open the app. - Drag…
Currently, an incorrect duration is displayed when the start or end time is `manually changed` during event creation. **Steps to reproduce:** - Install the `Calendar` module and open the app. - Drag on the calendar to create a `2-hour` time slot (quick-create popup opens). - Manually adjust the start or end time to make the event `3 hours` long. - Click `Save & Close`. - Click on the event: it correctly displays (3 hours). - Click `Edit` and observe the `Duration` value. **Observation:** The duration field shows 2 hours instead of 3 hours. **Root cause:** - The `duration` field is not available (and therefore not stored) in the `quick-create view` at [1]. - When the `stop` time is set manually, the `duration` is computed at [2]. - When the `start` time is changed, the `stop` time is computed based on the previously computed `duration` at [3]. **Fix:** This commit adds the `duration` field to the `quick-create` view as `invisible` (preventing it from being recomputed on each onchange) and `force_save`. This aligns the behavior with `19.0` by preserving the last computed duration in the front-end model, as implemented in PR [4]. [1]: https://github.com/odoo/odoo/blob/84571c03ff38ee768ed135bef3afa98511e3ab7b/addons/calendar/views/calendar_views.xml#L294-L339 [2]: https://github.com/odoo/odoo/blob/84571c03ff38ee768ed135bef3afa98511e3ab7b/addons/calendar/models/calendar_event.py#L353-L356 [3]: https://github.com/odoo/odoo/blob/84571c03ff38ee768ed135bef3afa98511e3ab7b/addons/calendar/models/calendar_event.py#L358-L374 [4]: https://github.com/odoo/odoo/pull/226909 opw-5867946 Forward-Port-Of: odoo/odoo#247193
This update fixes an issue where the activity menu in web_studio displayed all records for custom models, regardless of whether the user had an activity assigned to them. Now, the menu only shows records with activities linked to the current user, improving performance and ensuring users only see relevant data. This change was driven by a bug fix (opw-5778806).
Original PR description
After commit odoo/odoo@5c5fbc10b7024c7227f03e37897d421bba64df82 , actions spawned by the activities menu have their domain managed by dynamic <filter /> rather than a plain readonly domain. Before this commit, clicking on the activity menu to go to a custom model showed every record, not just ones with activities after this commit, only records with activities assigned to the current user are showed opw-5778806
A test was failing due to a default pricelist being applied, which incorrectly inflated the total sale order amount. This fix ensures the test accurately reflects the expected pricing behavior during Shiprocket delivery calculations. The change corrects a discrepancy in the test results.
Original PR description
Issue
-----
`File "/data/build/enterprise/delivery_shiprocket/tests/test_delivery_shiprocket.py", line 317, in test_shiprocket_delivery_with_discounts
self.assertAlmostEqual(sale_order.amount_total, 55)
AssertionError: 32.0 != 55 within 7 places (23.0 difference)
`
Cause
-----
Test fails because a pricelist gets applied by default and overrides the taxes.
-----
Error runbot 232692
Forward-Port-Of: odoo/enterprise#105180This update resolves an issue where tests for the delivery_ups_rest module were unintentionally executed twice. This improvement ensures more efficient system performance and reduces unnecessary resource consumption. The fix focuses on streamlining the testing process without impacting core functionality.
This update fixes an issue preventing correct import of Zengin accounting files. The validation process now allows a wider range of characters, including standard hyphens and alphanumeric text, aligning with the Zengin specification. This ensures all valid Zengin files can be imported without errors.
Original PR description
Before this commit, the Zengin file import validation was permitting only digits, spaces, and half-width Katakana characters. This limitation caused valid files to fail validation if they contained standard ASCII characters, such as the standard hyphen (which differs from the Katakana prolonged sound mark) or alphanumeric text. This commit updates the validation regex to support the full range of characters allowed by the Zengin specification. The allowed character set has been expanded to include: - Uppercase alphanumeric characters (A-Z, 0-9) - Standard symbols (e.g., -, ., /, (, ), etc.) Ref: https://bqa.smbc.co.jp/faq/show/2473?site_domain=web21lite task-5928087 Forward-Port-Of: odoo/enterprise#107007