Wednesday, June 10, 2026
23 changes · saas-18.3
Resolved issues and error corrections
This update resolves a bug where importing XML bills with identical filenames would create multiple vendor bills. The fix ensures attachments are correctly linked to the appropriate accounting records, preventing duplicate bill creation. This improves data accuracy and simplifies invoice processing.
Original PR description
Fixup of https://github.com/odoo-dev/odoo/commit/3fc85b6ed7936956abbaf8e8364bb2b288cbe289 Issue 1 - Import XML bill into documents app - Create vendor bill from the document Issue: Only the main attachment would be found in the created bill opw-6267888 Issue 2 - From the accounting app import XML bill containing two identically named documents Issue: Two bills were created opw-6231265 Forward-Port-Of: odoo/odoo#268850 Forward-Port-Of: odoo/odoo#268310
This update prevents placeholder images from being sent during menu synchronization, ensuring that only actual product images are transmitted. This improves the efficiency of data transfer and reduces unnecessary data usage, leading to a smoother user experience for customers viewing product menus.
Original PR description
This commit prevents placeholder images from being included in the menu sync payload and only sends `img_url` when an actual image is configured on the product or category. Task-6251430 Forward-Port-Of: odoo/enterprise#119720 Forward-Port-Of: odoo/enterprise#119482
This update fixes an issue where adding a recurring product to a confirmed sales order without a linked subscription plan would cause an error. The change prevents this by validating the product setup, ensuring recurring products are always associated with a subscription, and providing a clear error message to the user.
Original PR description
Steps to reproduce: - Go to Sales → Products. - Create a Service product and enable the Recurring option. - Open an already confirmed Sales Order that does not contain any recurring products. - Add the newly created recurring product to the confirmed order. - Click Save. - Observe that a traceback occurs. Cause: - When adding a recurring product without a subscription plan to a confirmed Sale Order, _timesheet_create_task() attempts to compute a start date using order.next_invoice_date, which is not set. - This leads to a TypeError when `order.next_invoice_date` receives `False`. Solution: - Add a validation to prevent adding recurring products without a subscription plan and raise a proper `UserError` instead of allowing the code to reach task generation logic. task-5932700 Forward-Port-Of: odoo/enterprise#119847 Forward-Port-Of: odoo/enterprise#107691
This update fixes an error in the Colombian DIAN invoice processing flow. Previously, the system incorrectly flagged invoices due after 5 PM Colombia time as invalid due to a timezone mismatch. The fix ensures invoices are validated against the correct Bogota local time, resolving the issue and allowing proper DIAN document submission.
Original PR description
**Steps to reproduce:** * Install `l10n_co_edi` module with DEMO DIAN mode enabled. * Go to Accounting > Vendor > Bills and create a new bill. * Select any Colombian partner different from…
**Steps to reproduce:** * Install `l10n_co_edi` module with DEMO DIAN mode enabled. * Go to Accounting > Vendor > Bills and create a new bill. * Select any Colombian partner different from `Consumidor Final`. * Set the invoice date to 6 days in the past. * Select the DIAN Support Documents journal and a product with UNSPSC category. * Confirm the bill and click `Send Support Document to DIAN` after 5 PM Colombia time. **Observed behavior:** * An error is raised stating the issue date cannot be older than 6 days or more than 6 days in the future, even though the invoice date is within the allowed window in Colombia local time. **Cause:** * The date window validation in `_check_move_configuration` used `fields.Datetime.now()` which returns UTC time. Since Colombia is UTC-5, after 5 PM local time the UTC clock has already rolled over to the next calendar day, making a 6-day-old invoice appear 7 days old and failing the validation incorrectly. **Fix:** * Convert the current UTC datetime to the `America/Bogota` timezone and extract its local date before computing the allowed date window. * Compare directly against `move.invoice_date` (a `date` field) instead of using `fields.Datetime.to_datetime()`, keeping the comparison consistent as `date` vs `date`. opw-6011502 Forward-Port-Of: odoo/enterprise#119794 Forward-Port-Of: odoo/enterprise#115256
This update resolves an error that occurred when sending invoices with Danish VAT numbers via Peppol. Now, customers in Denmark can use VAT numbers without the 'DK' prefix, and the system will correctly generate the Peppol endpoint with the required prefix. This ensures invoices are properly formatted and successfully transmitted.
Original PR description
Current behavior before PR: - Currently, when we include `DK` country prefix in the VAT number, it automatically computes the peppol endpoint with the `DK` prefix for customer from Denmark. - However, there are cases where the VAT number may not include `DK` country prefix, while the corresponding peppol endpoint still does. - In such situations, when sending an invoice via Peppol, the following error occurs: "Errors occurred while creating the EDI document (format: UBL BIS Billing 3.0.12): The VAT of the customer should be prefixed with its country code." Desired behavior after PR is merged: - Now customer from Denmark can have vat without country prefix `DK` and peppol endpoint with prefix `DK` and can send invoice via peppol. task-6119563 Forward-Port-Of: odoo/odoo#263262
This update corrects a missing reference field on Fedex shipping labels. The label now includes a 'CustomerReference' field, as required by the Fedex API, ensuring accurate tracking and documentation of stock transfers. This resolves an issue where the reference was absent, potentially causing delays or discrepancies in shipping processes.
Original PR description
Backport of bb4f8bf Original PR #116870 Forward-Port-Of: odoo/enterprise#118967 Forward-Port-Of: odoo/enterprise#117873
This update fixes an issue where SEPA QR codes generated for vendor payments occasionally displayed incorrect decimal precision due to floating-point calculations. The change ensures the QR code accurately reflects the intended payment amount, resolving potential discrepancies and improving payment accuracy. This impacts the generation of QR codes for vendor bills.
Original PR description
**Description of the issue/feature this PR addresses:** When generating a SEPA QR code for a vendor bill payment, the embedded amount could occasionally contain excess decimal places instead of…
**Description of the issue/feature this PR addresses:** When generating a SEPA QR code for a vendor bill payment, the embedded amount could occasionally contain excess decimal places instead of respecting the currency's expected precision. This occurs because the `amount` variable in `_get_qr_vals` was being converted directly using `str(amount)`. Due to Python's floating-point arithmetic, the float value in memory can contain decimal drift. Directly casting it to a string exposes this drift in the payload. This commit resolves the issue by replacing `str(amount)` with `float_repr(amount, currency.decimal_places)`. This safely bypasses the float representation issue, ensuring the string strictly respects the currency's configured decimal precision before being injected into the QR code. opw-5504258 **Steps to reproduce:** - Select company “My Belgian Company” - Create a 23% purchase tax - Create vendor bill - Select Vendor “BE Company CoA” - Choose any single product, change price to 37.18 and choose the 23% tax. The Untaxed Amount should be 37.18, VAT tax should be 8.55, and Total should be 45.73 - Confirm > Register Payment > scan QR code. EUR45.730000000000004 should show **Current behavior before PR:** - When generating a SEPA QR code for a payment, the embedded amount can contain excess decimal places due to floating-point drift. **Desired behavior after PR is merged:** - The SEPA QR code is generated with the correct number of decimal places. Forward-Port-Of: odoo/odoo#267293
A recent update was causing the Asset Depreciation Schedule report to crash when dealing with a large number of assets grouped together. This fix ensures the report handles missing data correctly, preventing errors and allowing users to accurately analyze their assets even with extensive groupings. This resolves a critical issue impacting report usability for our customers.
Original PR description
#### Description of the issue/feature this PR addresses: Opening the Asset Depreciation Schedule report with a period comparison enabled crashes with KeyError: 'no_format' when prefix grouping is…
#### Description of the issue/feature this PR addresses:
Opening the Asset Depreciation Schedule report with a period comparison enabled crashes with KeyError: 'no_format' when prefix grouping is active (large number of assets in one account group). The report becomes unusable for affected customers.
#### Current behavior before PR:
_regroup_lines_by_name_prefix sums each subline column by indexing prefix_subline['columns'][i]['no_format'] directly. Empty columns are built as {} by _build_column_dict (both col_value and col_data are None), so they have no 'no_format' key. With a comparison period enabled, an asset that has no value in the comparison period produces an empty column for that period; once prefix grouping fires (len(lines) >= prefix_groups_threshold, default 4000), the direct lookup hits that empty dict and raises KeyError: 'no_format'.
#### Desired behavior after PR is merged:
The prefix group total treats a missing 'no_format' as 0, matching the sibling caller in account_asset/models/account_assets_report.py that already guards with .get('no_format', 0). The report builds without crashing and the empty comparison column contributes 0 to the prefix group total.
opw-6225639
Forward-Port-Of: odoo/enterprise#119088This update fixes a display issue where time off allocation titles showed excessively long decimal numbers. The change rounds the calculated duration to two decimal places, presenting a cleaner and more user-friendly view of the requested time off. This ensures accurate and easily understandable information for employees and managers.
Original PR description
Steps to reproduce: ------------------- 1. Install Time Off 2. Create an employee with a 38-hour working schedule (7.6h/day) 3. Create a time off type with request unit set to "Hours" 4. Create an…
Steps to reproduce: ------------------- 1. Install Time Off 2. Create an employee with a 38-hour working schedule (7.6h/day) 3. Create a time off type with request unit set to "Hours" 4. Create an allocation for this employee with a duration of 8 hours 5. Observe the allocation title displaying a long decimal value. (e.g., 7.999999999999999) Issue: ------ The `number_of_days` is calculated in `_compute_number_of_days` using: https://github.com/odoo/odoo/blob/ca01e606928a7704c6b2e4f430710f895be2653d/addons/hr_holidays/models/hr_leave_allocation.py#L261-L262 For an 8-hour request on a 7.6h/day schedule, this results in ~1.052631579 days. In `_get_title`, this value is multiplied back to show hours: https://github.com/odoo/odoo/blob/ca01e606928a7704c6b2e4f430710f895be2653d/addons/hr_holidays/models/hr_leave_allocation.py#L151 This multiplication leads to the long decimal values being displayed in the title. Solution: --------- Round the computed duration to two decimal places using `float_round`. **NOTE:** This issue is already fixed in saas-19.1 (commit 01d86a7). However, **no change** is required in the multi-allocation wizard, as the duration there directly uses user input and is not computed from working hours. opw-6091424 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260140
This update fixes a bug where untaxed invoice lines were incorrectly inheriting datev codes from previous lines in the general ledger export. This ensured accurate datev reporting for German companies, preventing potential discrepancies in financial reports. The fix corrects the CSV file generated for Datev, ensuring proper accounting line identification.
Original PR description
**PROBLEM** Untaxed move lines would take the datev code of the previous line instead of having no datev code like they should. **STEP TO REPRODUCE** 1. On a german company, create an invoice with a line with tax 19% I, and a line that is untaxed (with a non-null price). 2. On the general ledger, generate the datev zip. 3. Unzip, and open the account entries csv, and notice the 2nd line of the invoice as the datev code set to something instead of it being empty (column BU-Schlüssel). opw-6141003 Forward-Port-Of: odoo/enterprise#118486
This update resolves an error that occurred when confirming DHL deliveries. The system now automatically sets a future delivery date (one hour ahead) to avoid the 'date must be in the future' error, ensuring successful order confirmations.
Original PR description
When confirming the delivery of an order using DHL shipping method we get an error that the date must be in the future. This happens when the scheduled date was not set, or set for a time in the past. This commit automatically sets the time to 1 hour in the future and bypasses the user error. opw-6148927 Forward-Port-Of: odoo/enterprise#116211
A bug was causing grouped payments to incorrectly link existing invoices to new, unrelated invoices. This update fixes the issue by ensuring payments are properly associated with the intended invoices, preventing data duplication and improving payment reconciliation accuracy. This resolves a problem where payments were spreading across multiple invoices.
Original PR description
Steps to reproduce --- 1. Register a grouped customer payment over several invoices, leaving one of them only partially paid. 2. Register a second grouped payment over two invoices: the partially…
Steps to reproduce --- 1. Register a grouped customer payment over several invoices, leaving one of them only partially paid. 2. Register a second grouped payment over two invoices: the partially paid one and a brand new invoice. 3. Open the first payment, its "Reconciled Invoices" smart button now lists the new invoice from the second payment, which it never paid. Issue --- The smart button is built from the stored `invoice_ids` many2many, which shares its relation table with `account.move.matched_payment_ids`. After reconciling, the register wizard links the payment to its invoices with `lines.move_id.matched_payment_ids += payment` at https://github.com/odoo/odoo/blob/f726393267a28cedd5febd2106de17ae3838f3ff/addons/account/wizard/account_payment_register.py#L1212. When the payment groups several invoices, `lines.move_id` is a multi-record recordset. Reading `matched_payment_ids` on it returns the union of the payments already linked to all those invoices, and `+=` writes that union back to every invoice as a `(6, 0, ...)` replace command. So an invoice already paid by an earlier payment spreads that earlier payment onto every other invoice grouped in the new one, including brand new invoices, which then wrongly appear on the earlier payment. opw-6188013 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267968
This update significantly improves the speed of syncing participants to marketing campaigns. By optimizing the underlying code, the process now takes just a fraction of the previous time – reducing it from over 51 seconds to less than a second. This change enhances the performance of our marketing automation tools, especially when managing large campaigns.
Original PR description
Replace search_read with search_fetch to avoid unnecessary _read_format call in backend context. Use OrderedSet instead of a custom _uniquify_list helper to get O(1) membership tests when computing records to add or remove from campaigns. Benchmark on a campaign with 115k participants: | Before PR | After PR | |:---------:|:--------:| | 51.71s | 0.652s | opw-6055334 Forward-Port-Of: odoo/enterprise#119589 Forward-Port-Of: odoo/enterprise#117656
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must precede the end time, ensuring correct shift template creation. This improves user experience and reduces confusion.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
This update resolves a technical issue where the journal report's multi-country tax grids were incorrectly displaying country information when multiple countries were selected. The fix ensures that all countries are accurately represented in the report, improving the accuracy of financial reporting across various regions.
Original PR description
When more than 2 country are used in the taxes, the colspan of the header is wrong. When more than 2 country are used in tax grids, the country isn't displayed anymore. Forward-Port-Of: odoo/enterprise#119348
This update clarifies the invoice print process by making the print button secondary to the send action. Previously, invoices were incorrectly labeled as 'proforma,' which is handled separately. This change ensures invoices are consistently displayed and simplifies the invoicing workflow.
Original PR description
Revert 3ef2c09 which incorrectly added a proforma label when printing posted invoices that had not yet been sent, proforma invoices have an entire feature in the sales app, so an invoice in invoicing should just be an invoice in all cases. --- The Print button on posted invoices was visually styled as a primary action. Make it secondary so the Send action keeps the main visual emphasis, while Print remains available with the same behavior. task-6269645 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268552
This update resolves an issue where a specific configuration in the French VAT reporting module incorrectly generated an error. When the street address was short and 'street 2' was not used, the system produced invalid XML. This fix ensures accurate report generation and avoids potential disruptions to the reporting process.
Original PR description
When the street field is shorter than 30 char and street 2 is false, we end up with " False" in the xml, which will return an error in aspone. no task id Forward-Port-Of: odoo/enterprise#119718
This update fixes an issue where Unicode slugs were incorrectly combining characters instead of using separators. Previously, `/` characters were silently removed, resulting in incorrect URL formatting. Now, slugs will correctly use hyphens to separate words, ensuring consistent and accurate URL generation.
Original PR description
After Unicode slug support was introduced in https://github.com/odoo/odoo/commit/926e45aa93ffc3f74fe9bf4ae8f06642976c2ae5, `/`
characters started being silently removed instead of treated as
slug boundaries.
As a result:
"foo/bar" -> "foobar"
while it should instead generate:
"foo/bar" -> "foo-bar"
This restores the previous behavior by treating each non word character
as separators normalized to `-`.
task-6219984This update fixes a problem preventing Odoo logins via turnstile in Safari's private browsing mode. Safari's tracking protection settings were interfering with the form submission process. The fix adjusts how the turnstile challenge is handled to ensure successful logins in this scenario.
Original PR description
Scenario: - set up turnstile - with recent safari mac os or ios (reproduced from 26.2) go to /web/login page in a private window - enter login and password and pass the turnstile challenge - click on…
Scenario: - set up turnstile - with recent safari mac os or ios (reproduced from 26.2) go to /web/login page in a private window - enter login and password and pass the turnstile challenge - click on Log in Result: nothing happens and there is an error in the console "An invalid form control with name='' is not focusable." Cause: By default Safari has the Settings > Advanced > "Use advanced tracking and fingerprinting protection" set to "in Private Browsing". If this options is enabled in private browser or in all browsing, you can't login to Odoo with turnstile because safari is preventing the update of the element that is preventing to send the form: <input style="display: none;" class="turnstile_captcha_valid" required> When turnstile challenge succeeds, a value should be set to this input that will unlock the form, the .value property is updated but the browser Shadow Content is not (and if we remove display:none, the input is empty). Fix: I've not been able to reproduce the issue without turnstile using same situation and iframe. We don't know Safari heuristic but the unlocking is working if: - we use setProperty instead of .value - we unset required - we remove the input - we display the turnstile_captcha_valid input before challenge This fix replaces setting .value by setProperty, and add a failsafe of unsetting required. opw-5917286 fixes #247536 Forward-Port-Of: odoo/odoo#253367
This update ensures that tax details are now included in test orders sent to UrbanPiper. Previously, test orders lacked this crucial information, leading to potential issues with the integration. This change corrects a technical detail to guarantee consistent data transmission and improve the reliability of our testing process.
Original PR description
Commit 1: ======== Before this commit: =================== - Test orders sent to UrbanPiper did not include tax details for order items. After this commit: ================== - Tax details are now included in the order item payload of test orders. Task-6013007 --- Commit 2: ======== Cause: ====== In the `without demo` environment, the discount product does not have any `taxes_id`, causing the test assertion to fail. Fix: ==== Set a tax on the discount product in the test to ensure the same behavior in both `with demo` and `without demo` environments. Error-241138 Forward-Port-Of: odoo/enterprise#109958
This update prevents users from directly creating employee, cost, or mandatory benefits records through the Benefits form. This change ensures data consistency and accuracy by requiring these records to be created through the standard workflow, reducing potential errors and improving data management within the HR contract module.
Original PR description
This commit prevents creating new employee, cost or mandatory benefits records directly from the Benefits form by setting these fields' `'no_create'` to `True`. task-5156844 Forward-Port-Of: odoo/enterprise#96770
This update simplifies invoice sending by ensuring the 'By Peppol' method is only automatically enabled for customers in designated countries (GR, IT, PL, PO, RO). This reduces user confusion and streamlines the invoicing process for businesses operating in these regions.
Original PR description
Current behavior before PR: - If the customer has a valid Peppol endpoint, the 'By Peppol' invoice sending method is selected by default. - For countries like 'GR,' 'IT,' 'PL,' 'PO,' and 'RO,' peppol is not mandatory or not used for sending invoice. It brings noise and it bothers the users. Desired behavior after PR is merged: - The 'By Peppol' invoice sending method is set to true by default only for customers from PEPPOL_DEFAULT_COUNTRIES. Changes Implemented: - Moved the countries 'GR', 'IT, 'PL', 'PO', and 'RO' from PEPPOL_DEFAULT_COUNTRIES to PEPPOL_LIST. - Added condition to set 'By Peppol' invoice sending method to true when customer is from PEPPOL_DEFAULT_COUNTRIES. task-6072935 Forward-Port-Of: odoo/odoo#269106 Forward-Port-Of: odoo/odoo#262402
This update fixes a security vulnerability where users could view financial budgets belonging to other companies. The change adds a security rule to restrict access to budgets based on the company a user is connected to, ensuring data privacy and compliance. This prevents unauthorized access to sensitive financial information.
Original PR description
**Steps to reproduce:** - Install the `account_reports` module. - Create a new company. - Navigate to Accounting > Configuration > Financial Budgets. - Create a new budget record. - Switch to another company. - Open the list view of Financial Budgets. **Observation:** The budget record created in another company is still visible. **Root Cause:** The model `account.report.budget` does not have any record rule restricting access based on company. As a result, users can see financial budgets belonging to other companies even if they are not connected to them. **Fix:** This commit allows users to hide financial budgets from companies they are not connected to by adding a record rule on `account.report.budget` opw-6083892 Forward-Port-Of: odoo/enterprise#114771