Thursday, October 9, 2025
11 changes · saas-18.2
Resolved issues and error corrections
Stripe payment amounts are now calculated correctly for currencies with special decimal handling, including the Ugandan shilling. This prevents valid low-value orders from being rejected or interpreted as the wrong amount during card checkout.
Original PR description
Steps: - Activate the 'UGX' currency. - Make a sale order with amount 100 with 'UGX' currency - Try to pay that order (100 USh) using card Issue: - stripe throws the following error - > 'The Checkout Session's total amount must convert to at least 50 cents. 1.00 USh converts to approximately €0.00.' - Hence 100 USh sent was identified as 1 USh by stripe. This confirms issue with decimals and currency mapping. Cause: - 'UGX' is zero-decimal currency but stripe identify it as two-decimal. Fix: - Update mapping for such special currency cases for stripe that don't follow general rules opw-5075707 Forward-Port-Of: odoo/odoo#227688
This fix ensures French POS order integrity hashes are created only after an order is fully processed. It prevents valid orders from being incorrectly flagged as altered during compliance checks.
Original PR description
Description of the issue/feature this PR addresses:
Starting from version 18.0, inalterability hashes in the FR localization are sometimes calculated with incomplete data, leading to incorrect `l10n_fr_hash`. Related orders are then wrongly flagged as altered when running the POS Inalterability Check.
Current behavior before PR:
When you post a POS order and a related draft order exists, Odoo updates the existing order with the new vals. Because `{'state': 'paid'}` is amongst the new vals, it triggers the generation of the `l10n_fr_hash` before the order is fully processed. For instance, the hash will be generated before a new payment line is added for change with `_process_payment_lines()`.
Desired behavior after PR is merged:
The hash should be generated at the end of the order processing, with the final write in `action_pos_order_paid()`.
Forward-Port-Of: odoo/odoo#226032Updating a product variant on a sales order no longer resets the selected packaging or unit choice back to default units. This prevents incorrect quantities or packaging from appearing on quotes and helps sales teams keep customer orders accurate.
Original PR description
## Versions
18.2+
Note: 18.4 needs `product.uom_id` to be replaced by `product.uom.id` to work properly.
## Issue
On a SO, if a product has variants and packaging is allowed, modifying the variant resets the packaging to units.
## Steps to reproduce
*Ensure "Units of Measure & Packagings" is enables in Sales' app's settings*
- Create a new product
- Under "Attributes & Variants" tab, add the following:
- Color: add 2 colors;
- Legs: add 2 legs;
- Under "Sales" tab, select "Pack of 6" for "Packagings" (under "Upsell & Cross-Sell" section);
- Create a new quote and add that new product:
- Change its "Unit" for "Pack of 6";
- Modify the product variant by clicking the pen button next to the product name (appear on hover):
- Click "Confirm" (no changes needed);
- See the order line's product's units change back to "Units".
opw-4814166Fixed an issue where survey respondents could see an incorrect “answer required” warning after providing a comment on certain multiple-choice questions. This improves the survey experience by accepting valid comment-based responses and adds safeguards to prevent invalid multiple answers.
Original PR description
Issue: When answering a question with a comment in multiple choice with roaming activated for the survey, the UI will display a warning message that says the question requires an answer. Cause: The backend creates a skipped record if none of the pre-created answers is chosen. Solution: Don't create a skipped record if a comment counts as an answer and a comment is provided. Added validation of input and unittests Task-5062984 Forward-Port-Of: odoo/odoo#226022
This fix prevents an error when saving a manufacturing order after one operation has started and another is not yet scheduled. It ensures production dates are calculated only from scheduled work orders, improving reliability for users managing shop floor operations.
Original PR description
**Steps to reproduce:** 1. In Settings, enable "Work Orders". 2. Create a product with a BOM that has 2 operations: op1 and op2. 3. Create and confirm an MO for 1 unit. 4. Start op1 and change the…
**Steps to reproduce:** 1. In Settings, enable "Work Orders". 2. Create a product with a BOM that has 2 operations: op1 and op2. 3. Create and confirm an MO for 1 unit. 4. Start op1 and change the Real Duration of op2. 5. Try to save. **Issue:** - Traceback : `'<' not supported between instances of 'datetime.datetime' and 'bool'` **Cause of the issue:** Starting the first operation launches a call of the `button_start` method creating a `resource.calendar.leaves` to set on the `leave_id` of this first operation: https://github.com/odoo/odoo/blob/97a70e71c32ea6183f87fd5eb558b32bcbd2d231/addons/mrp/models/mrp_workorder.py#L630-L641 Then, setting the duration of the second operation from the form view of the MO and saving triggers a call of the write of the MO containing the `[Command.update(op_2.id, new_duration)]` as vals.This, in turn, calls `_plan_workorders`: https://github.com/odoo/odoo/blob/97a70e71c32ea6183f87fd5eb558b32bcbd2d231/addons/mrp/models/mrp_production.py#L939-L942 while the first operation has a set `leave_id` but the second do not However, the `min` operator will be applied to both the set and the unset values, comparing a `boolean` with a `datetime`: https://github.com/odoo/odoo/blob/97a70e71c32ea6183f87fd5eb558b32bcbd2d231/addons/mrp/models/mrp_production.py#L1581-L1588 **Solution:** Only workorders with a `leave_id` (i.e., those planned in work-center schedule) should be considered when computing MO `date_start` and `date_finished`. Workorders without a `leave_id` are not yet scheduled and therefore should not influence MO start and end dates. As both `date_start` and `date_finished` of a workorder are related to the `leave_id` record. As per `mrp_workorder._compute_dates`, these dates reflect the work-center scheduling (`leave_id.date_from` and `leave_id.date_to`). https://github.com/odoo/odoo/blob/6a075fa3c090920499ccbd5fe673819da7e3f95e/addons/mrp/models/mrp_workorder.py#L250-L260 Therefore, when computing MO dates, it logically follows that only workorders with an assigned `leave_id` should be used. This avoids mixing unscheduled operations (`leave_id = False`) with scheduled ones, preventing invalid comparisons and ensuring accurate production timing. **opw-5068080** Forward-Port-Of: odoo/odoo#226436
This fix prevents Chrome on iOS from automatically modifying certain text, such as emails or measurements, in a way that could disrupt page rendering. It helps keep the Odoo web interface stable and correctly displayed for affected mobile users.
Original PR description
Chrome iOS wraps some text nodes (like measures, email...) with a `<chrome_annotation>` tag, which breaks OWL rendering. This commit works around it by adding the (undocumented) `<meta name="chrome"…
Chrome iOS wraps some text nodes (like measures, email...) with a `<chrome_annotation>` tag, which breaks OWL rendering. This commit works around it by adding the (undocumented) `<meta name="chrome" content="nointentdetection">` tag to disable this Chrome behavior. The tag has to be set before the onDOMContentLoaded event to be taken into account. Note: Looks like this behavior was present in Chrome iOS 127 and disabled afterward (because it already had issues) but it appeared again in version 140-141. References: - https://issues.chromium.org/issues/353650041 - https://issues.chromium.org/issues/388718411 - https://stackoverflow.com/questions/78207646/how-do-i-disable-chrome-annotation-tags - https://stackoverflow.com/questions/78575970/prevent-auto-detection-of-phone-numbers-in-chrome-mobile - https://stackoverflow.com/questions/78725191/stop-chrome-ios-auto-detecting-numbers-followed-by-letter-m-as-metre-units-an - https://github.com/solidjs/solid/issues/2235 opw-4969197 Forward-Port-Of: odoo/odoo#230081
Adyen checkout requests now send the country code and line item details required by some payment methods such as Klarna. This helps affected customers complete payments that could previously fail during redirect-based checkout.
Original PR description
Some payment methods eg. Klarna require 'country code' and 'line items' in order to process the transaction. opw-5077617 Forward-Port-Of: odoo/odoo#230292
This fix adjusts how certain Spanish service sales taxes are reported so they are treated as not subject to VAT rather than exports. It also corrects the refund sign for the related tax, helping businesses produce more accurate Modelo 303 VAT reports.
Original PR description
The s_iva_e tax (IVA 0% Extracomunitaria (Servicios)) is configured as no_sujeto_loc, but is reported as "Exportacion" in modelo 303. There might have been the idea that we need a tax for services that are just a complement to some goods, but this tax is not used that way in practice. So, it is better to treat it as a duplicate of the s_iva_ns tax (Not Subject To VAT (services)) where we also see that the refund sign was wrong. opw-5079297 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#230383 Forward-Port-Of: odoo/odoo#229752
This fixes an issue where public holidays could be incorrectly counted as excess leave when a time off request spans two consecutive allocations. Employees and HR teams should now see more accurate leave balances for requests crossing allocation periods with public holidays.
Original PR description
### Steps to reproduce: - Install Time off apps - Create two consecutive allocations (e.g. one for 2025 and one for 2026) - Create a leave that overlap with the two allocation (e.g. from 8th Dec to…
### Steps to reproduce: - Install Time off apps - Create two consecutive allocations (e.g. one for 2025 and one for 2026) - Create a leave that overlap with the two allocation (e.g. from 8th Dec to 3rd Jan) - Create a public holiday at the beginning of the second allocation (e.g. on 1st Jan 2026) ### Cause: When we are checking the leave duration after having a public holiday the will return the attendance without the public holidays duration so when subtracting the attendance duration from the leave duration we will have a remaining amout equals to the public holiday duration and it will be considered as excess days. https://github.com/odoo/odoo/blob/06e47d8601ba56b1650eeaeef71ebd7a4af39b8b/addons/hr_holidays/models/hr_employee_base.py#L228-L230 https://github.com/odoo/odoo/blob/06e47d8601ba56b1650eeaeef71ebd7a4af39b8b/addons/hr_holidays/models/hr_employee_base.py#L246-L254 ### Fix: We check for public holidays in the interval we are fetching its attendance to avoid assuming it is an excess days in the leave opw-5006119 Forward-Port-Of: odoo/odoo#225433
Emails sent from Odoo could fail when they included an attached email file containing accented or other non-ASCII characters. This fix handles those attached email files correctly so messages can be sent reliably.
Original PR description
The previous fix for `message/rfc822` attachments forced binary encoding (`cte='binary'`) to comply with RFC 2046. However it also introduced a new issue: emails containing `.eml` attachments with…
The previous fix for `message/rfc822` attachments forced binary encoding (`cte='binary'`) to comply with RFC 2046. However it also introduced a new issue: emails containing `.eml` attachments with non-ASCII characters could not be serialized ### Steps to reproduce 1. Send an email via the chatter with a `.eml` file attached containing non-ASCII characters (e.g., "é") in its body. The sending of that email will fail with a `UnicodeEncodeError` error ### Cause Commit 6197233ef1611ddd974cfdb06ae2568e4af369de attempted to fix an issue where `.eml` (`message/rfc822`) attachments were not RFC-compliant. It did this by forcing the `Content-Transfer-Encoding` to `binary` for the raw byte content of the attachment. While this worked for simple ASCII attachments, it failed for attachments containing non-ASCII characters. When Python's `email` library later tried to serialize the entire message, it treated the attachment's content as an opaque binary blob. It did not understand the character encoding within that blob, leading to a `UnicodeEncodeError` during the final serialization process. ### Fix Instead of attaching the raw bytes, we now: * Parse `.eml` contents using `email.parser.BytesParser`, producing a proper `Message` object. * Attach the parsed message directly, letting the email library handle correct encoding and transfer settings automatically. opw-4655868 Forward-Port-Of: odoo/odoo#230384 Forward-Port-Of: odoo/odoo#223790
This fixes an issue where confirming a batch transfer could lose barcode scanning settings. Warehouse users can now scan locations such as WH-Stock after creating a batch without the scan being incorrectly split into individual characters.
Original PR description
### Steps to reproduce: - In the settings enable: "Batch, Wave & Cluster Transfers" - Create 2 deliveries - Barcode > operations > Delivery orders > Batches > New - Add your two deliveries and…
### Steps to reproduce: - In the settings enable: "Batch, Wave & Cluster Transfers" - Create 2 deliveries - Barcode > operations > Delivery orders > Batches > New - Add your two deliveries and confirm - Scan WH-Stock #### > The scan fails considering you scanned each letter independently. ### Cause of the issue: When the barcode is scanned a call of the split barcode will be launched to split the barcode in multiple barcodes according to the `barcode_separator_regex` present in the config: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/models/barcode_model.js#L613-L632 The issue lies in the fact that even thought the is `barcode_separator_regex` was conrrectly populated at the onWillStart of the mainComponent: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/components/main.js#L209-L213 https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/controllers/stock_barcode.py#L97 https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/components/main.js#L229 https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/static/src/models/barcode_picking_model.js#L36-L38 It was reset by the batch confirmation here: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode_picking_batch/static/src/models/barcode_picking_batch_model.js#L123-L135 because this part of the config is not meant to be returned by the private method `_get_barcode_data` but rather by public complete version `get_barcode_data`: https://github.com/odoo/enterprise/blob/aeb9343f4b7dfab0fbc04bca4623ae85b3ea6030/stock_barcode/controllers/stock_barcode.py#L91-L98 Now, since no `barcode_separator_regex` was provided to our new config, each character will be considered to be considered as an independent barcodes and the `WH-Stock` barcode will not match any location. opw-5062331 Forward-Port-Of: odoo/enterprise#94056