Friday, October 10, 2025
17 changes · saas-18.3
New functionality added to Odoo
Belgian companies can now connect Odoo to Codaclean through IAP to automatically import CODA bank statement files into bank journals. This reduces manual banking work by fetching files twice daily or on demand once the connection and journal are configured.
Original PR description
This module adds support for "codaclean" integration. CODA files can be periodically (or on demand) fetched from codaclean and imported into bank journals. The module only connects to the IAP server.…
This module adds support for "codaclean" integration. CODA files can be periodically (or on demand) fetched from codaclean and imported into bank journals. The module only connects to the IAP server. The IAP side does the actual calls to codaclean (with a secret API key). To use the module you have to create a connection to IAP / codaclean and set up a bank journal: - To manage the connection to IAP / codaclean go to Settings -> Accounting -> Codaclean -> Manage Connection - To set up the bank journal you need to configure the following in the "Journal Entries" tab on the journal: - Put the IBAN in the "Bank Account Number" field - Select "Codaclean Synchronization" for the "Bank Feeds" field Coda files will be automatically fetched 2 times per day via the scheduled action called "Accounting: Sync Coda Files from Codaclean". They can also be manually fetched by clicking "Fetch from Codaclean" below the journal on the accounting dashboard (only available when the journal and connection are setup correctly). On an empty journal we start fetching from 1 year ago. When the journal is not empty we start fetching after the last bank statement / bank statement line in the journal. task-4844423 backport of commit 518ab9e Forward-Port-Of: odoo/enterprise#96705 Forward-Port-Of: odoo/enterprise#95747
Enhancements to existing features
Point of Sale users can now mark an electronic terminal payment as completed when it remains stuck waiting for a card response. This helps cashiers finish orders when the payment succeeded on the terminal but Odoo did not receive the update, reducing checkout delays and unnecessary retries.
Original PR description
Current behavior before PR: If we faced an issue with a terminal payment while the `line.payment_status` being "waitingCard", only possible option for the user would be to "Cancel" the payment and try again or choose another payment method. This is an issue for the cases where the payment went through on the terminal but Odoo didn't update the status for some reason. Desired behavior after PR is merged: We add the possibility to "Force done" while the status is "waitingCard" to avoid blocking the user in such situations and have a possible fallback. opw-4978772 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229557 Forward-Port-Of: odoo/odoo#228406
Resolved issues and error corrections
Sale orders and invoices no longer crash when a customer contact has no name and sale warnings are enabled. This keeps sales and billing workflows running smoothly even when contact records are incomplete.
Original PR description
When creating a Sale Order or Invoice for a partner without a name, a traceback occurs. Steps to reproduce the error: - Install ``sale_management`` with demo data - Enable ``Sale Warnings`` from settings - Open ``Azure Interior`` Contact > In Contact, Add Contact > Type: invoice > Save & close - Create a sale order with the newly created partner AND - Create an invoice with the newly created partner Traceback: ``TypeError: unsupported operand type(s) for +: 'bool' and 'str'`` https://github.com/odoo/odoo/blob/7a1b27e5985b3b16768bea450c51226ae3659c76/addons/sale/models/sale_order.py#L822 https://github.com/odoo/odoo/blob/7a1b27e5985b3b16768bea450c51226ae3659c76/addons/sale/models/account_move.py#L59 Here, ``partner_id.name`` is ``False``, which leads to string concatenation with a boolean in sale warning messages and results in the above traceback. sentry-6912482256 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Belgian POS blackbox setups now get a preparatory IoT action that prompts users to update their IoT device. This helps ensure systems are ready for an upcoming queue-based communication change between the POS and blackbox, reducing rollout friction later.
Original PR description
This commit is the first of two which will introduce a queue mechanism in the communication between the POS and the blackbox. This commit adds an action to the iot and invites users to update their iot to be prepared for the next commit which will effectively add the queue mechanism and use the new action. Second part: https://github.com/odoo/enterprise/pull/90747
This fix ensures Indian HR leave records calculate durations correctly when sandwich leave rules include consecutive non-working days or public holidays. It also corrects half-day leave so it is counted as 0.5 days instead of a full day, helping payroll and time-off balances stay accurate.
Original PR description
**Steps to reproduce:** - Install l10n_in and l10n_in_hr_holidays module - Time off > configuration > Public holidays - Create a public holiday for Independence Day (15/08/2025) - Go to Time off >…
**Steps to reproduce:** - Install l10n_in and l10n_in_hr_holidays module - Time off > configuration > Public holidays - Create a public holiday for Independence Day (15/08/2025) - Go to Time off > configuration > 'Time off Types', - Create a Time off type with - 'Sandwich leave' ticked and `Take Time Off in` to half a day - Go to Time off > Management > Time off - Case 1: Create a paid time off leave for the employee from 13/08 to 17//08/2025 - Case 2: Create a paid time off with any date and mark it as a half-day **Observation:** - Case 1: You will see Duration 3 days with the sandwich leave policy. - Case 2: Half-day leave shows 1 day instead of 0.5 **Root Cause:** - Case 1: For the sandwich leave rule, here we checked only one day after and before, leave start and leave end, respectively. It will cause an issue if an employee applies leave that starts or ends with 3 non-working days. https://github.com/odoo/odoo/blob/5d2f1510c08d5570fc2c6c8de0cb4042bacf12d6/addons/l10n_in_hr_holidays/models/hr_leave.py#L39-L46 - Case 2: We forcefully added a 1-day leave, without checking if the leave is half day or not. https://github.com/odoo/odoo/blob/5d2f1510c08d5570fc2c6c8de0cb4042bacf12d6/addons/l10n_in_hr_holidays/models/hr_leave.py#L19 **Solution:** - Case 1: Extend the sandwich leave logic to check every day before and after until a working day is found. - Case 2: Fixed duration calculation to add 0.5 for half-day leaves. opw-5025766 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226883
Changing the quotation template on a sales order now removes the old linked quote calculator spreadsheet. This prevents users from accidentally working with pricing details from the previous template and keeps the sales order aligned with the selected template.
Original PR description
Step to reproduce: - Create a new SO - Add a customer and quotation template to the order - Click on quote calculator smart button - Return to sale order (click on SO number in top left) - Change the quotation template - Result: it does not change the quote calculator that is linked to the new quotation template Cause: - Clicking on Quote Calculator creates a copy of the quotation template spreadsheet and links it to the SO. https://github.com/odoo/enterprise/blob/8bc6098335d283e6d210dc788463a8ef8c559b14/spreadsheet_sale_management/models/sale_order.py#L30-L35 - When the quotation template is later changed, the spreadsheet linked to the old template remains attached to the SO. Fix: - On changing the sale_order_template, the old spreadsheet should be unlinked from the SO. - Keeping it linked is inconsistent, as it does not matches the current template opw-4998587 Forward-Port-Of: odoo/enterprise#95652 Forward-Port-Of: odoo/enterprise#93970
Fixes invoice tax calculations when multiple price-included taxes are used and only some affect later tax bases. This prevents incorrect tax report warnings and improves the accuracy of invoice totals, tax bases, and discount calculations, with only minor rounding differences possible.
Original PR description
**Issue** When creating an invoice with two price-included taxes, one that affects the base of subsequent taxes (`include_base_amount=True`) and another that does not, the tax computation is…
**Issue** When creating an invoice with two price-included taxes, one that affects the base of subsequent taxes (`include_base_amount=True`) and another that does not, the tax computation is incorrect. This leads to inconsistent base amounts and triggers a warning in the tax report, particularly visible in the Tax Return Report. **Steps to Reproduce** 1. Create two taxes with `price_include=True`: Tax1 with "Affect Base of Subsequent Taxes" disabled Tax2 with it enabled 2. Add both taxes to the same invoice line and confirm the invoice 3. Open the Tax Report and filter by the invoice date 4. The report shows an inconsistency because the computed base is wrong **Root Cause** The batching logic separates taxes into groups when their properties differ. In this case, because the two taxes have different `include_base_amount` values, they are split into different batches. Since batching drives how price-included taxes are reversed to compute the base, splitting the batch leads to misinterpreted base amounts and incorrect tax calculations. **Fix** Adjusting batching conditions to allow taxes to be grouped together even if their `include_base_amount` flags differ. This ensures that price-included taxes are handled consistently and the base is computed correctly across all taxes in the group. Opw-4863100 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221401
Sales order lines now keep the selected packaging unit, such as a pack of 6, when a user reviews or updates a product variant. This prevents quotes from accidentally reverting to single units, helping preserve accurate quantities and customer pricing.
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-4814166
Forward-Port-Of: odoo/odoo#224574Batch invoice sending now applies Peppol only to invoices that are actually eligible for it. This prevents invoices meant to be sent by email, such as those for non-Peppol customers, from being incorrectly routed to Peppol and failing instead of being delivered.
Original PR description
…ng methods When sending invoices in batch with multiple sending methods (for example 1 by Peppol, 2 by Email), Peppol was wrongly set on invoices where it didn't make sense. Steps to reproduce: 1. Go into a Peppol compatiable company (Eg: Belgium) 2. Go into settings, enable Peppol. 3. Create & post two invoices: one to an US partner, the other one to a Peppol partner (For example a belgian partner with a vat set.). Make sure to set the email on both. 4. Send them in batch: the wizard says 1 by Peppol, 2 by Email, which is correct. 5. If you send them, the one to the US partner that is not supposed to go through Peppol will end up in error, with the email not sent either. Root cause: We are doing some Peppol checks before checking if it actually make sense to apply this sending method on the move. task-none (reported from our production)
This fix ensures the date picker properly resets when users move from one journal entry to a new one. It prevents accounting entries from staying unsaved or missing their draft title when the same prior-month date is selected again.
Original PR description
Steps to reproduce ================== - Install accounting - Go to Accounting > Accounting > Journal Entries - Create a new record - Select an Accounting Date in the previous month - An onchange is called and the title is changed to draft - Save the record - Click on New - Select the same date - The onchange isn't triggered - Save the record - The record stays dirty and the title is missing Cause of the issue ================== https://github.com/odoo/odoo/commit/44f69ae726b1ff8876c38e858c64fed0f5b1a766 lastAppliedStringValue should be reset inside computeBasePickerProps Solution ======== We backport the code from 19.0 where this was fixed opw-5145113
SEPA direct debit payments now correctly validate whether a payment mandate is still active. This prevents valid future-expiring mandates from being wrongly rejected and helps avoid unnecessary payment failures.
Original PR description
The check to ensure that the mandate used in a token payment is still valid had two issues: - It was comparing a date (the mandate's end date) with a datetime. - It was incorrectly rejecting mandates expiring in the future, while it should have done the opposite. Forward-Port-Of: odoo/enterprise#96426 Forward-Port-Of: odoo/enterprise#96143
Sales confirmations using Gelato now create a temporary draft order first, then only confirm it after the sale is safely completed. This prevents duplicate Gelato orders when payment or order processing is retried because of concurrent updates.
Original PR description
In case on a concurrent update happen in the same transaction as the sale order confirmation (was observed during payment transaction post-processing), we may currently create duplicate Gelato orders on each retry. This commit avoid duplicate order creation by splitting the Gelato order creation in two steps: - during the sale order confirmation we create a 'draft' order on Gelato - on post-commit/post-rollback we either try to confirm or delete the Gelato draft order. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228107
Appointment video call links now use the website linked to the appointment type, so customers receive links with the correct company website domain. This prevents incorrect meeting URLs in multi-company setups with separate websites.
Original PR description
**Steps to reproduce:** - Create 2 companies - Create a website for each company - Set a custom website domain on the second one - Create appointement type for each website - Create an appointement on both websites - The link created for the video call has the wrong base for one of them **Issue:** Appointment `get_base_url` finds its base_url without considering the current website. **Fix:** Compute the base_url according to the appointement type to ensure the current website is taken into account. opw-4880715 Forward-Port-Of: odoo/enterprise#92734
Sales orders with multiple global discounts now create the correct number of discount lines. This prevents confusing extra lines on orders and keeps tax and discount calculations clearer for users.
Original PR description
Because of the grouping on the computation_key in the taxes engine, when a second global discount was applied on a SO, it was creating two additional lines instead of one. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Time off requests that span consecutive allocations now account for public holidays correctly during balance checks. This prevents public holidays from being mistakenly treated as extra leave days, reducing incorrect excess leave warnings or calculations.
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#230600 Forward-Port-Of: odoo/odoo#225433
This fixes an issue where related list fields were not displayed properly in generated reports. Reports that include these fields should now show the expected information, improving accuracy for business documents.
Original PR description
For now, `One2Many` fields are not displayed correctly in reports. This is because for other types of fields (`ManyToMany`, `ManyToOne`, etc.), there are Converter classes (`ManyToManyConverter`) `ir.qweb.field.many2many` that implement `value_to_html`. However, for `OneToMany` fields, no implementation is present. This commit adds a `OneToManyConverter`, which is essentially the same as the `ManyToMany `one. opw-5098466 Forward-Port-Of: odoo/odoo#230675 Forward-Port-Of: odoo/odoo#229289
Fixed an issue where changing a coupon reward on a confirmed sales order could leave the coupon with the wrong remaining points. Coupon balances now correctly reflect the reward currently applied, helping avoid customer credit discrepancies.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have a coupon program; 2. add a 10% discount on order reward for 1 point; 3. add a 50% discount on order reward for 5 points; 4. generate a coupon with 10…
Versions -------- - 17.0+ Steps ----- 1. Have a coupon program; 2. add a 10% discount on order reward for 1 point; 3. add a 50% discount on order reward for 5 points; 4. generate a coupon with 10 points; 5. use coupon code on a confirmed order; 6. select 10% discount reward; 7. change to a 50% discount reward; 8. check coupon point total. Issue ----- Even though the 5 point reward was used, only 4 out of 10 points remain. Cause ----- When updating the reward line of a confirmed order, it keeps track of point cost changes before & after a write. Its purpose is to restore back the point difference on the coupon record. The issue is that while point changes are stored, coupon changes are not. When updating reward lines, `_reset_loyalty` is used, which removes the `coupon_id` from the lines. As a consequence, attempting to restore the point difference on `line.coupon_id` after an update, it writes to an empty record. Solution -------- Store both coupons & their used points before write. After write, restore the previous points to the previous coupon, and subtract the current point cost from the current coupon. This way, any combination of coupon/point changes should have the points updated as expected. opw-4910922 Forward-Port-Of: odoo/odoo#230907 Forward-Port-Of: odoo/odoo#222054