Wednesday, August 5, 2026
9 changes · saas-19.2
Enhancements to existing features
SEPA direct debit batch validation has been optimized to handle large payment batches more efficiently. This reduces processing time for companies validating hundreds or thousands of payments, helping avoid delays and timeouts during payment workflows.
Original PR description
- Replace the `id:recordset` aggregation in `_get_expiry_date_per_mandate()` with `date:max` to compute the latest payment date directly in SQL. - Render `email_from` for all payments in batch and cache the computed authors by sender email to avoid repeated partner lookups during SDD pre-notification. This reduces ORM/cache overhead when validating large SEPA batches containing thousands of payments. Measured on a production-sized database: | metric | before | after | factor | |--------|-------:|------:|-------:| | `_get_expiry_date_per_mandate` (500 payments) | 564 ms | 111 ms | ~5x | | `_send_after_validation` notification (500 payments) | 92.9 s | 55.7 s | ~1.7x | | `_get_expiry_date_per_mandate` (1000 payments) | 890 ms | 178 ms | ~5x | | `_send_after_validation` notification (1000 payments) | timed out (>159 s) | 108.9 s | completed | OPW-6377340 Forward-Port-Of: odoo/enterprise#126429 Forward-Port-Of: odoo/enterprise#125439
Resolved issues and error corrections
Date and datetime fields now disappear from the pivot popup once all available time breakdowns have already been added. This avoids duplicate entries and makes drag-and-drop behavior more reliable for users working with spreadsheet pivots.
Original PR description
Current behavior before PR: - Date and datetime fields remained visible even when all their granularities were already added to the pivot. - Users could add the same field with the same granularity multiple times, creating duplicate IDs and causing unexpected drag and drop behavior. Desired behavior after PR is merged: - Hide date and datetime fields from the popup once all available granularities have already been added to the pivot. - This prevents duplicate field IDs and keeps the popup behavior consistent with spreadsheet pivots during drag-and-drop. Task: [6295794](https://www.odoo.com/odoo/project/2328/tasks/6295794) Forward-Port-Of: odoo/enterprise#123280
This fixes an error that stopped users from confirming several Brazilian customer invoices at once when Avalara Brazil tax mapping was enabled. Businesses can now validate batches of invoices without interruption, reducing manual work and failed processing.
Original PR description
**_Steps to reproduce:_** * Install `l10n_br_avatax` and configure Avalara Brazil. * Create at least two customer invoices. * Ensure the fiscal position is set to **Automatic Tax Mapping (Avalara…
**_Steps to reproduce:_** * Install `l10n_br_avatax` and configure Avalara Brazil. * Create at least two customer invoices. * Ensure the fiscal position is set to **Automatic Tax Mapping (Avalara Brazil)**. * Select the invoices and click **Action → Confirm Entries**. **_Observed behavior:_** * A traceback is raised with `ValueError: Expected singleton: account.move(...)` and the invoices cannot be validated. **_Cause:_** * During tax extraction, `_extract_tax_values_from_l10n_br_avatax_detail` accesses `self.invoice_filter_type_domain` while `self` may contain multiple `account.move` records. * Accessing `invoice_filter_type_domain` on a multi-recordset raises an `Expected singleton` error, preventing the validation of multiple invoices. **_Fix:_** * Build the returned tax values by iterating over each invoice in the recordset and using the corresponding `invoice_filter_type_domain`. * This ensures `_extract_tax_values_from_l10n_br_avatax_detail` correctly handles multiple invoices during validation without raising a singleton error. opw-6334761 Forward-Port-Of: odoo/enterprise#126437 Forward-Port-Of: odoo/enterprise#124993
The aged payable and receivable report drill-down now hides bills and invoices that were already fully settled for the selected report date. This helps finance users see only genuinely outstanding items, including when reviewing historical balances.
Original PR description
Steps to Reproduce: 1. Create a vendor/customer with multiple bills/invoices. 2. Fully pay one or more, leaving at least one still open for the same partner. 3. Open Accounting > Reporting > Partner…
Steps to Reproduce:
1. Create a vendor/customer with multiple bills/invoices.
2. Fully pay one or more, leaving at least one still open for the same partner.
3. Open Accounting > Reporting > Partner Reports > Aged Payable/Receivable.
4. Set to any date and click into an aging bucket for that partner.
Issue:
The drill-down list shows fully settled bills (residual = 0.00) alongside genuinely outstanding ones. Only surfaces when the partner has at least one open balance — if everything is paid, there is no bucket to click into.
Root Cause:
aged_partner_balance_audit builds the drill-down domain filtering only by reconcile flag, journal type, and date range — never checking residual. Additionally it completely overwrites the XML action domain (account.action_amounts_to_settle) which already had ('amount_residual', '!=', 0), losing that protection entirely.
Fix:
Added ('residual_at_date', '!=', 0) to the domain in aged_partner_balance_audit and set recon_limit in the action context so residual_at_date computes as of the report's 'as of' date rather than today's value:
action['context'] = {
'recon_limit': options['date']['date_to'],
}
Without recon_limit, residual_at_date falls back to amount_residual (today's value) which incorrectly excludes bills that were genuinely open on the report date but paid after it.
Result:
The drill-down now correctly shows only genuinely outstanding items regardless of whether the report is run as of today or a historical date.
opw 6333699
Forward-Port-Of: odoo/enterprise#126021Cancelled Mexican CFDI invoices can now be reprinted with their required fiscal information, including QR codes, digital stamps, and fiscal folio details. This helps businesses keep legally relevant cancelled invoice records complete and verifiable.
Original PR description
### Issue before this commit: When an invoice's CFDI cancellation request is confirmed (state moves from sent to cancel), reprinting the invoice PDF no longer displays the fiscal information (QR…
### Issue before this commit: When an invoice's CFDI cancellation request is confirmed (state moves from sent to cancel), reprinting the invoice PDF no longer displays the fiscal information (QR code, digital stamps, fiscal folio/UUID, etc.), even though the signed CFDI attachment is still present on the invoice. ### Steps to reproduce the issue: 1. Download Accounting and l10n_mx 2. Create an invoice and send it to CFDI 3. Select 'Request for cancel' 4. Wait and click retry button in the CFDI tab until the invoice is marked as cancelled 5. Print the invoice again 6. See PDF does not show fiscal information (QR, fiscal folio, etc.) ### Cause of the issue: https://github.com/odoo/enterprise/blob/f6c94d4ca3ef4211a5ab00bf0b39f6a7675c8f79/l10n_mx_edi/models/account_move.py#L904-L909 Once the CFDI is cancelled, the computed field switches to 'cancel', so the condition fails and the method falls back to the generic account.report_invoice_document template, which has no knowledge of CFDI fiscal fields. ### Reason to introduce the fix: A cancelled CFDI invoice is still a legally relevant fiscal document in Mexico and must be reprintable with its fiscal data intact (to prove it was issued and later cancelled). The fix extends the condition to also cover the 'cancel' state, ensuring the CFDI-specific report template is used whenever a valid attachment exists, regardless of whether the CFDI is currently signed or cancelled. opw-6393656 Forward-Port-Of: odoo/enterprise#126466
Customer balances in Point of Sale now show the correct Total Due when the company currency differs from the PoS currency. This prevents pay-later amounts from being converted twice, giving staff an accurate view of what customers owe.
Original PR description
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any…
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any outstanding balance - open the PoS, create an order of USD 100 and validate it with the Customer Account (Pay Later) payment method - open the Customers screen and look at the Total Due of that customer Issue: The Total Due shows about USD 55.56, i.e. the amount converted once too many, instead of the expected USD 100. Cause: get_total_due() sums two amounts that are not expressed in the same currency before converting them. partner.total_due comes from the accounting entries, it is the sum of account.move.line.amount_residual and is therefore in company currency, while total_settled is the sum of pos.payment.amount of the still open sessions, which is in the currency of the order, so the PoS one. The addition is done first and the result is then converted from the company currency to the PoS one, so the pay later payments end up converted a second time. opw-6403320 Forward-Port-Of: odoo/enterprise#126402 Forward-Port-Of: odoo/enterprise#125798
Automatic bank reconciliation rules now use clearer text matching and consider transaction amounts, reducing incorrect or duplicate rule creation. Users also see only reconciliation rules relevant to the selected journal, making bank matching more accurate and easier to manage.
Original PR description
Reconcile models automatically created now use contains instead of match regex and take the amount into consideration when creating the rule as well as checking for existing rules, it's checked whether all of the lines are positive or negative. Added an extra filter on the reconcile models so that it only shows rules that would be applied on the journal, and did some optimizations in the substring matching. task-6140372 Forward-Port-Of: odoo/enterprise#117256
Peruvian electronic invoices now calculate down payment amounts consistently when withholding tax is involved. This prevents mismatched XML totals and avoids references to cancelled down payment invoices, reducing the risk of rejected or incorrect electronic documents.
Original PR description
### Issue: When an invoice has a down payment on a line with a withholding tax, the `PrepaidPayment/PaidAmount` in the UBL XML included the withholding tax amount, causing a mismatch with…
### Issue: When an invoice has a down payment on a line with a withholding tax, the `PrepaidPayment/PaidAmount` in the UBL XML included the withholding tax amount, causing a mismatch with `LegalMonetaryTotal/PrepaidAmount` which correctly excludes it ### Cause: `PrepaidPayment/PaidAmount` was set directly from `prepayment_move.amount_total`, which includes all taxes `LegalMonetaryTotal/PrepaidAmount` uses `_aggregate_base_line_tax_details` to exclude withholding taxes, but this was not applied to the `PrepaidPayment` node ### Fix: Using `prepayment_move.amount_total` directly includes all taxes and does not match the rounding logic of `LegalMonetaryTotal` Instead, `_aggregate_base_line_tax_details` is used with the same `total_grouping_function` as `LegalMonetaryTotal`, ensuring both nodes use the same rounding logic and exclude withholding taxes Reversed down payment moves are also excluded from `AdditionalDocumentReference` to avoid referencing cancelled invoices ### Steps to reproduce: - Install `l10n_pe_edi` and `sale_management` with demo data - Switch to the PE company - Create and confirm a Sale Order (Customer: PE Company, Product: Any, Unit Price: 200, Taxes: VAT 18% and 3% IGV Withholding) - Create, confirm and pay a Down Payment Invoice (Fixed: 28.92) - Go back to the SO and create the Regular Invoice - Confirm it and click Process Now - Open the EDI Document tab and download the XML Before the fix, the sum of `PrepaidPayment/PaidAmount` did not match `LegalMonetaryTotal/PrepaidAmount` opw-6273903 Forward-Port-Of: odoo/enterprise#121733
This fixes an issue where rental availability on the website could be blocked because stock from another click-and-collect warehouse was counted incorrectly. Customers can now place rental orders from a warehouse that still has the item available, reducing false out-of-stock errors.
Original PR description
When using the click & collect option, the available qty for renting was not taking the selected warehouse into account. Steps to reproduce: ------------------- * Create 2 different warehouses with 2…
When using the click & collect option, the available qty for renting was not taking the selected warehouse into account. Steps to reproduce: ------------------- * Create 2 different warehouses with 2 different adresses * Create a product available for renting * Setup the product to use serial numbers * Create 2 serial number, 1 in each warehouse * Activate the click & collect option on the website * Create a first sale order to collect in warehouse 1 * In the backend, confirm the order and pick it up * Go back to the website and make a second order for the second warehouse > Observation: When clicking on the "Add to cart" you get an error saying that there is no quantity available Why the fix: ------------ When computing the `product_rented_quantities` it would look for `sale.order.line` in all the warehouse. So it would find the line from the first order even if it's not linked to the selected warehouse. So we just add a new element to the domain to filter out the incorrect warehouses. opw-6328475 Forward-Port-Of: odoo/enterprise#126545 Forward-Port-Of: odoo/enterprise#124969