Thursday, October 23, 2025
14 changes · 17.0
Enhancements to existing features
Odoo now routes Peppol partner lookup checks through its IAP service so it can support the Peppol network’s upcoming DNS change. This helps keep electronic invoicing partner discovery working after the switch from CNAME to NAPTR records, without requiring unsupported package changes in stable versions.
Original PR description
Starting from 1st November, the Peppol SML will start to use NAPTR records instead of CNAME. This mainly allow them to enforce a specify a scheme (https). To be able to retrieve this specific type of records and follow the replacement record we need `pythondns` package which is not available in stable versions. We therefore will now use IAP to serves as a bridge to query the Peppol network when retrieving a partner services/existence on Peppol. This solution is also good to handle future changes by moving most of the logic into IAP where stable policy is easier to handle. Related: https://github.com/odoo/iap-apps/pull/1203 Documentation: https://docs.peppol.eu/edelivery/changelog/2025-04/Peppol%20CNAME%20to%20NAPTR%20Migration%20Process%20v1.0.0%202025-04-17.pdf task-5059508
Electronic invoices can now use a fallback payment code when no bank account is configured, avoiding validation errors in BIS3 exports. This makes initial setup smoother for businesses that have not added bank details yet.
Original PR description
Backport of commit 026743fb2627edeada5ae2a517b64bf05ae921ae . To generate a valid BIS3 format, if we put 30 - credit transfer as payment means, we need to have a bank account set. If it's not the case, it will raise an error. We improve the usability by changing that code to ZZZ - mutually defined if no bank account is provided to the invoice. This should improve the onboarding flow when no bank account is set yet. task-None Forward-Port-Of: odoo/odoo#232795
Resolved issues and error corrections
Creating a new warehouse could incorrectly generate many duplicate replenishment routes when an existing global route had been renamed for a company. This fix reuses the intended route name when checking for existing routes, preventing clutter and unnecessary records in inventory configuration.
Original PR description
In _find_or_create_global_route, use the asked 'route_name' instead of the potentially modified name of `data_route`. This ensures that if '_find_or_create_global_route' is called with the exact same values a new route will not be re-created. https://github.com/user-attachments/assets/815adf60-aa2d-4699-a79d-f9ad9607cbea ## How to reproduce (in runbot 17.0): - Enable "Multi-steps Routes" - Unarchive route "Replenish on Order (MTO)", change the name, set company to "My company (San Francisco)" - Go to "My Company (Chicago)" - Create new Warehouse => Check all the routes: ~100 MTO routes with the modified name have been created. OPW-5149842 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Odoo now checks live browser connections at the application level when no activity has occurred for a short period. This helps detect dropped connections more quickly on slow or unstable networks, reducing the time users may miss real-time updates.
Original PR description
When a TCP connection is not closed cleanly, it can take minutes to detect a closed WebSocket connection. During this time, no messages are received. This can happen in slow or unstable network conditions. Browsers do not expose WebSocket ping/pong mechanisms. To detect dead connections quickly, periodic application level messages are sent if no messages were either sent or received within a minute. This approach ensures quicker detection compared to relying on the OS TCP timeout, which is typically set to a high value. 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
Fixed an issue where Argentina VAT summary reports could overstate totals when price-included VAT was used with multiple IIBB taxes on the same vendor bill. The report now counts each tax amount only once, helping businesses rely on accurate tax summaries that match accounting records.
Original PR description
**Issue** When using a VAT tax marked as price included, together with multiple IIBB taxes on the same invoice, the VAT summary report displays an incorrect total. Specifically, the VAT amount is…
**Issue** When using a VAT tax marked as price included, together with multiple IIBB taxes on the same invoice, the VAT summary report displays an incorrect total. Specifically, the VAT amount is counted multiple times, once for each IIBB tax, leading to an inflated total. **Steps to Reproduce** 1. Install the Accounting app and the Argentinian localization (l10n_ar) 2. Set the 21% VAT Purchase tax as Included in Price 3. Create a vendor bill applying the 21% VAT tax and at least two IIBB taxes 4. Open the VAT summary report for that bill Expected Behaviour: The total in the VAT summary should match the total shown in the accounting form view, with each tax counted only once. **Root Cause** The VAT summary report in the Argentinian localization relies on an SQL query to aggregate tax information for each `account.move`. The query joins `account_move_line` with `account_tax`, `account_tax_group`, and the many-to-many relation table `account_move_line_account_tax_rel`. Each `account_move_line` related to a VAT tax line (via `tax_line_id`) is joined with the `account_move_line_account_tax_rel` table. If that base line is related to multiple IIBB taxes, the join multiplies the VAT line once per IIBB tax since multiple matching rows exist. **Fix** The solution separates the logic for computing tax lines and base lines into two distinct subqueries. Each is aggregated independently to prevent duplication caused by one-to-many and many-to-many joins. The results are then joined using the unique `account_move_line.id`, ensuring each tax amount is counted exactly once in the final totals. opw-4776861 Forward-Port-Of: odoo/enterprise#85873
This fix ensures the point of sale cash drawer can still be opened through an ePOS printer even when a configured IoT box is unreachable. It prevents store staff from being blocked at payment by an unrelated disconnected device.
Original PR description
Steps to reproduce: 1. Configure a POS to use an ePOS printer with the cashdrawer enabled. 2. Also configure the POS to use an IoT box with a dummy device, e.g. '[Shop] Scale'. The important thing is that the IoT box is not reachable when the POS opens, so the dummy devices work well for this. 3. Open the POS, make an order and go to payment, then click 'Open cashbox'. Expected behaviour: The cashdrawer opens Actual behaviour: Nothing happens task-5059502 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Italian electronic bill imports now avoid applying the same discount twice when the XML contains both a discount section and a separate negative line. This helps keep vendor bill totals accurate and prevents extra manual correction after import.
Original PR description
When importing a bill in an IT company the system will automatically parse the xml and populate the record. In case of discount, an element <ScontoMaggiorazione> will be present, either for the whole document or for a single line. However, an extra negative line may be present in the xml representation of the bill, creating a double discount **Steps to reproduce** - With an IT Company setup - Import an xml bill having <ScontoMaggiorazione> element and a negative line representing the same discount **Issue** Double discount line will be created in the bill **Analysis** This occurs because, when parsing the bill, the system will import also negative lines, even if a discount has been already applied opw-4913335 [Ticket link](https://www.odoo.com/odoo/project/49/tasks/4913335)
Large email campaigns can now retry failed sends in smaller batches, avoiding memory failures when hundreds of thousands of emails are involved. This helps larger organizations recover from temporary mail server outages without manual cleanup or lost campaign progress.
Original PR description
Steps to reproduce the issue: 1. Have 100s of thousands of recipients on a campaign 2. Disconnect your outgoing server and send 3. Reconnect the mailing server and retry sending. Current behavior before PR: A `MemoryError` is raised due to the large number of emails processed to `unlink()` Desired behavior after PR is merged: Larger-scale clients would be able to resend 100s of thousands of emails if they fail opw-5091567
Responsible HR users can now sign offers without errors when employees request extra time off and automatic allocation is enabled. This helps keep salary package and holiday workflows moving smoothly without manual intervention.
Original PR description
- When the employee requested extra time off, and the automatic allocation setting was turned on, signing the offer as the responsible HR caused an error. Task-5022631 Forward-Port-Of: odoo/enterprise#92663
Peppol document routing now uses Odoo's IAP service to handle the required DNS lookup changes before older CNAME-based lookups are discontinued. This keeps electronic invoicing connectivity working as Peppol infrastructure requirements change and centralizes future lookup updates.
Original PR description
From November 1st, CNAME DNS will be deprecated for Peppol lookups. From February 1st CNAME lookups will no longer be supported. The replacement are NAPTR DNS records. Multiple solutions were available, such as using DoH (e.g. with cloudflare DNS), but we ended up choosing to proxy DNS requests through IAP to centralize the lookups and make such specs upgrades easier to handle in the future. IAP is now responsible of doing the DNS lookup and fetching the service groups of the found SMP. IAP-side: https://github.com/odoo/iap-apps/pull/1227 task-5179969
This fixes an error that could interrupt Ingenico card payments in Point of Sale. The system now avoids unnecessary repeated status updates and only contacts the database when payment activity or driver status changes, improving payment reliability for store operations.
Original PR description
Currently when paying with ingenco there is an error: "Uncaught (in promise) TypeError: can't access property "payment_method", line is undefined." This is due to the fact that Ingenco sends requests to the database every second even when the status of the driver didn't change since the last payment. This PR fixes the issue by only sending requests to the database if a) THe driver status has changed b) A payment is being processed It also fixes the deprecation warning for isSet() replaced by is_set(). opw-5166439 opw-5181429 opw-5164612 opw-5170658
This fixes an issue where users could add tax tags to journal items dated before the tax lock date, potentially changing already locked tax reports. The system now checks tax lock rules before and after edits so protected tax reporting periods remain unchanged.
Original PR description
Despite the tax lock date, users are able to modify the tax report by adding tags.
**Steps to reproduce:**
Ensure the tax lock date is set
1. Journal Items list view
2. Edit one/many lines that
- have a date before the tax lock date,
- don't have a tax,
- nor tax tags,
- and is not a tax line.
3. Add a new tax tag
**Issue:**
The tax tags are added and might impact a tax report, when you should have received a user error.
**Cause:**
The `write` function calls the `_check_tax_lock_date` which in turn only checks the existing line instead of the values given in the `write` parameters. Since the line has no existing tax tags the check does not fail.
**Solution:**
Call the tax lock check both before and after writing the move line.
Task-5169152Landscape reports printed through a Virtual IoT Box will now keep their intended orientation instead of being cropped as portrait pages. This prevents wasted paper and ensures printed business documents match the on-screen report layout.
Original PR description
When printing a landscape report using a Virtual IoT Box, we end up printing a portrait page cropped. This commit adds the "pdf fit page" argument to ensure the page printed follows the report orientation. opw-5051809 Task: 5149706
The Australian TPAR report now exports correctly in both TPAR file and PDF formats. This prevents export failures caused by incorrectly formatted country names and missing report line information, helping users submit required tax reporting without manual workarounds.
Original PR description
Behavior before: Exporting the TPAR report using the TPAR option failed with a line length error because the SQL query returned the full JSON object for country names (e.g., {'en_US': 'Australia'})…
Behavior before:
Exporting the TPAR report using the TPAR option failed with a line length error because the SQL query returned the full JSON object for country names (e.g., {'en_US': 'Australia'}) instead of plain text, resulting in incorrect line lengths. Additionally, PDF export failed with a KeyError for the missing 'level' key, as dynamically generated report lines did not include a level field, which the QWeb template requires.
Behavior after:
SQL query uses the JSONB text extraction operator (->>) to retrieve only the country name string (e.g., 'Australia'), ensuring correct line lengths during export. All dynamic report lines are assigned 'level': 1 so that PDF export works correctly without errors.
Root cause:
Country names are stored as translatable JSONB fields, and the previous query did not extract the localized text, returning the full JSON structure. Dynamic report lines for partners did not include a level key by default, causing the PDF template rendering to fail.
Ticket [link](https://www.odoo.com/odoo/project.task/5148697)
opw-5148697