Friday, September 18, 2026
11 changes · 18.0
Enhancements to existing features
French partner records without the expected electronic invoicing address scheme are now checked against the official directory data available through IAP. When matching entries are found, the system selects the most appropriate identifier automatically, improving accuracy for French e-invoicing preparation.
Original PR description
for existing french partners that dont have their EAS set to the FRCTC, a check will be made to see if they are on the annuaire using the IAP annuaire lines, if one line exists, the identifier is set to that, if more than one line exists, we set the identifier to one of the lines in this priority: siren_siret -> siren -> shortest identifier (most general) task-id-6327357
Large reports that reuse the same barcode or QR code now avoid redrawing the same image over and over during generation. This can dramatically reduce report creation time for documents with many repeated codes, improving productivity without changing report content.
Original PR description
### Description of the issue/feature this PR addresses: Reports with hundreds of pages and repeated barcodes or QR codes (same document number, same lot code on every page) re-run reportlab's…
### Description of the issue/feature this PR addresses: Reports with hundreds of pages and repeated barcodes or QR codes (same document number, same lot code on every page) re-run reportlab's createBarcodeDrawing and PNG encoding on every occurrence, even when type, value and options are identical. ### Current behavior before PR: Every call to ir.actions.report.barcode() re-renders the barcode/QR from scratch, regardless of whether an identical (type, value, options) combination was already rendered earlier in the same report. On a 900-page report with 4 barcodes/page, this dominates generation time. Benchmark, 900 pages x 4 barcodes/page, 4 distinct combos, 3600 calls: 19.131s. ### Desired behavior after PR is merged: The pure rendering step (createBarcodeDrawing + mask + PNG encoding) is extracted to a module-level function keyed on (barcode_type, value, options, mask) and wrapped with functools.lru_cache. Repeated barcodes reuse the cached PNG instead of re-rendering. Same benchmark after the fix: 0.020s (946.7x speedup, cache_info hits=3596 misses=4). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
Customers with AvaTax tax exemptions can now complete checkout when using product discounts from the loyalty program. The fix ensures taxes are recalculated at the final payment step, preventing validation errors caused by outdated tax amounts.
Original PR description
Steps to reproduce: - Activate AvaTax in db - Configure a discount for a product in Discount & Loyalty - Log in as a portal user that has a tax exemption set in the AvaTax portal (Avalara) - Add the product with the discount to your cart - Try to check out Current Behavior: - You can't check out due to validation error Expected Behavior: - You can check out Clarification: You are currently unable to checkout under these conditions because when you hit pay, the final check does not recompute taxes which will lead to a mismatch and thus an error opw-5285825 Forward-Port-Of: odoo/odoo#262285
Opening an order from the Sales report is now faster, especially in databases with many sales lines. The system now finds the related order directly instead of running a slow report calculation first.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. On a database with many sale order lines, open Sales > Reporting > Sales and switch to the list view. 2. Click a line to open its order. Issue ----- Opening the order takes seconds. Cause ----- `action_open_order` reads `order_reference` off the `sale.report` view. The view's `id` is `MIN(sale_order_line.id)`, so reading one record filters on an aggregate. PostgreSQL therefore has to aggregate every sale order line and POS order line before keeping one row. Solution -------- The report id is itself a line primary key, so the order can be resolved without reading the view. Add a `_get_order_reference` hook returning the order from the `sale.order.line` record directly.
Orders paid through express checkout now avoid showing placeholder names when the shipping address does not include a recipient name. The delivery contact falls back to the billing or customer name, so delivery slips and confirmation emails look correct for customers and staff.
Original PR description
Steps to reproduce ================== 1. Enable an express checkout provider on the shop, e.g. Stripe with Link. 2. Sign in as a customer having a saved address, then put a deliverable product in the…
Steps to reproduce ================== 1. Enable an express checkout provider on the shop, e.g. Stripe with Link. 2. Sign in as a customer having a saved address, then put a deliverable product in the cart. 3. Pay with the express checkout button, confirming a shipping address that differs from the saved one. Address validation does it on its own by completing a zip code, e.g. 61820 becomes 61820-1234. => The order's delivery and invoice addresses read "Anonymous express checkout partner for order S00xxx", and so do the delivery slip and the shipping confirmation email. Root cause ========== When the received shipping address matches none of the customer's contacts, `express_checkout_process_shipping_address` creates one to hold it. As the payment form has yet to send the customer information, that contact is named after the order [1]. `process_express_checkout` then completes it with the address of the payment form [2]. Express checkout wallets don't necessarily send a recipient name, and Stripe Link never does, so the placeholder name is left untouched. It remains on the order, which uses that contact as its invoice address too when both addresses match. Fix === Fall back on the billing name, then on the customer's own name, when the shipping address holds no name. [1]: https://github.com/odoo/odoo/blob/18.0/addons/website_sale/controllers/delivery.py#L197-L206 [2]: https://github.com/odoo/odoo/blob/18.0/addons/website_sale/controllers/main.py#L1677-L1684 opw-6366612 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update makes e-invoicing choices easier to understand by renaming confusing labels and improving automatic format selection for local and international invoices. It also prevents disabling required Peppol services, reducing compliance risk, and fixes missing print/download options for invoice-related files.
Original PR description
#### [FIX] account: invoice edi format selection placeholder The placeholder of the field "eInvoice format" (`invoice_edi_format`) is confusing currently. It says "XML format". It is unclear to the…
#### [FIX] account: invoice edi format selection placeholder The placeholder of the field "eInvoice format" (`invoice_edi_format`) is confusing currently. It says "XML format". It is unclear to the user what this means / will do. This commit changes it to "Automatic Selection". This better reflects what is happening: If no value is selected for the field (= the placeholder is selected in the UI) we try to automatically select a value. (See `_compute_invoice_edi_format` / `_get_suggested_invoice_edi_format` on model 'res.partner') #### [FIX] account_peppol: disallow disabling services Currently it is possible to disallow any services in the configuration. This can lead to complicance issues; i.e. if someone disables "BIS Billing 3.0". 1. Ensure Peppol is activated (test mode or production; not demo) 2. Settings -> Accounting -> PEPPOL Electronic Invoicing -> Configure Peppol Services 3. Any service can be disabled. This commit hides the button to open the service wizard. (Also in the wizard it is now not possible to disable services anymore.) #### [FIX] account: generation of print-related entries in cog menu Before this commit: The dynamic generation of the print related entries in the cog menu does not work correctly. Problem / Solutions: There is a check in the javascript that does not work as intended. Thus the entries are not added to the cog menu in all cases. The check was intended to only block it for "new" records (not saved yet); to avoid issues in case the move has no id yet. After this commit we just check the id directly. #### [FIX] account: explicit local format Explicitly separate the suggested "eInvoice format" into local format (intra-country) and other (inter-country). This is done by adding the following functions to `_get_suggested_invoice_edi_format`: - `_use_local_invoice_edi_format`: Checks whether the partner is from the same country as the company. - `_get_local_invoice_edi_format`: The function that can be extended for every country to specify the local format. #### [FIX] account: generic extra print items Before this commit: It is not possible to explicitly generate XML files in BIS 3.0 or local formats. This commit adds the following formats to the "Download" item in the cog menu: - the "eInvoice format" (field; `invoice_edi_format`) - local format (from function `_get_local_invoice_edi_format()`) - suggested format (from function `_get_suggested_invoice_edi_format()`) All formats are labeled with their name (so e.g. "Xrechnung CIUS"; and not "Local Format") In case the file can not be generated we log the errors in the chatter. The "XML UBL" button was renamed to "XML Attachment (UBL/CII)". This avoids confusion with the new buttons. The aforementioned button downloads any existing UBL attachment (from field `ubl_cii_xml_id`). #### [FIX] account_edi_ubl_cii: missing parenthesis in invoice_edi_format Follow-up to commit 860c0974f9b541be63f4079ef52366f91c1994ce . There we improved the eInvoice format labels for clarity. But 2 label were formatted differently than the others. This commit fixes that. #### References task-4737164
This fixes a Peppol invoice issue where sending an invoice line without a product or label could crash instead of showing the expected validation message. Users will now receive a clear warning about the missing item information, helping them correct the invoice and continue the sending process.
Original PR description
### Steps to Reproduce: 1. Activate Peppol 2. Create invoice for customer with Peppol 3. Add line without product name or label 4. Send invoice through Peppol and observe the Traceback error ###…
### Steps to Reproduce: 1. Activate Peppol 2. Create invoice for customer with Peppol 3. Add line without product name or label 4. Send invoice through Peppol and observe the Traceback error ### Issue: When generating a Peppol invoice, there will be a Traceback error if an invoice line is missing both a product and a label. The XML builder evaluates the missing `cbc:Name` element as `None` instead of an empty dictionary. Therefore, attempting to directly subscript `['_text']` on it throws a TypeError traceback. This prevents the user from seeing the standard validation warning about the missing item data. ### Solution: We can update the document node constraint check to safely access the dictionary keys using `.get()` with an empty dictionary fallback. This prevents the traceback and ensures that the system will correctly display the intended validation error to the user. opw-6577441 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Odoo now highlights when a company's own currency has exchange rates that are not 1:1, helping users spot and fix imported rate mistakes. This prevents inaccurate currency calculations by showing warnings on the currency form and list views and making the related rates easier to correct.
Original PR description
Currently, if a user mistakenly imports currency rates to current company currency, and the rates are not equal, i.e not 1:1, then this may create issues in rate computations. This commit shows warning in currency form view if currency rates are not 1:1, also makes the rate_ids visible so that user can correct it. It also shows currency in list view in warning color for users to identify and correct issue. task-5402018 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Customers using AvaTax with tax exemptions can now complete checkout when discounts or loyalty rewards create negative tax adjustments. The final payment check now refreshes external tax calculations, preventing false validation errors and reducing blocked online sales.
Original PR description
Steps to reproduce: - Activate AvaTax in db - Configure a discount for a product in Discount & Loyalty - Log in as a portal user that has a tax exemption set in the AvaTax portal (Avalara) - Add the product with the discount to your cart - Try to check out Current Behavior: - You can't check out due to validation error Expected Behavior: - You can check out Clarification: You are currently unable to checkout under these conditions because when you hit pay, the final check does not recompute taxes which will lead to a mismatch and thus an error opw-5285825 Forward-Port-Of: odoo/enterprise#116765
Mexican payroll now prorates the worked-days amount for weekly payslips based on the monthly contract wage. This avoids showing a full month of salary in the weekly worked-days line while keeping the actual net pay calculation unchanged.
Original PR description
Issue: On the Mexican localization, setting a contract with a monthly wage (e.g. MXN 20,000) together with a weekly payable structure showed the wage labelled as "/ semana". The generated payslip…
Issue: On the Mexican localization, setting a contract with a monthly wage (e.g. MXN 20,000) together with a weekly payable structure showed the wage labelled as "/ semana". The generated payslip then displayed the full 20,000 on the worked days input, making it look like the weekly period was not prorated. Steps to reproduce: - Install the l10n_mx localization - Set a contract with a monthly salary of MXN 20,000 and a weekly schedule - Generate a payslip and open the worked days lines Cause: The wage caption on the contract form is driven only by schedule_pay, so a weekly schedule renders "/ semana". In this version the payroll engine has no MX-specific proration and consumes the contract wage as a monthly base (the amount computation divides by the period's own worked hours). The label therefore contradicts how the value is actually used. https://github.com/odoo/enterprise/blob/5f9cf56372a7faa1bce55c418454d3aacbff04c4/hr_payroll/views/hr_contract_views.xml#L36-L48 Solution: Force the wage to always be shown as a monthly amount for Mexican contracts and hide the schedule-based period suffixes. This aligns the displayed label with the monthly base the engine requires, without altering how wages or worked days are computed. opw-6535787
The Ecuador ATS report now includes invoices from branch companies that share the same tax ID as the parent company. This prevents missing invoice data in the exported tax XML and gives businesses a more complete compliance report across their branches.
Original PR description
**Steps to reproduce:** * Install `l10n_ec_reports_ats`. * Create a parent company with an Ecuadorian RUC. * Create a branch/sub-company under that parent (sharing the same RUC). * Post invoices…
**Steps to reproduce:**
* Install `l10n_ec_reports_ats`.
* Create a parent company with an Ecuadorian RUC.
* Create a branch/sub-company under that parent (sharing the same RUC).
* Post invoices under both the parent and the branch company.
* Open the ATS report (Report 104) from the parent company and export the ATS XML file.
**Observed behavior:**
* The generated ATS XML only includes invoices whose `company_id` matches the parent company exactly.
* Invoices posted under the branch company are silently omitted, even though the branch shares the same RUC.
**Cause:**
* `_get_sale_values`, `_get_purchase_values`, and `_get_void_moves` all filtered `account.move` and `account.journal` records using `('company_id', '=', company.id)`.
* In Odoo, branch companies share the parent's journals but invoices carry `company_id == branch.id`. The strict equality filter excluded all branch invoices.
* `_get_internal_vat_tax` similarly filtered `account.tax` by the parent company only, missing taxes associated with branch invoices.
* `branch_allowed` was not set on the report options, preventing the UI from offering branch selection.
**Fix:**
* Collect all companies sharing the same RUC via `company._get_branches_with_same_vat(accessible_only=True)`.
* Replace every `('company_id', '=', company.id)` domain clause with `('company_id', 'in', company_ids)` across journal, move, and tax lookups so that records from all same-RUC branches are consolidated.
* Set `branch_allowed = True` in `_custom_options_initializer` to align the report options with multi-branch behaviour.
opw-6504463