Wednesday, June 17, 2026
16 changes · saas-19.3
Enhancements to existing features
This update ensures Odoo automatically syncs product tags with UrbanPiper, resolving an issue where a single, hardcoded tag was used. Now, tags are dynamically managed based on user tax configurations and aggregator needs, allowing UrbanPiper to receive the most relevant information for accurate pricing and reporting.
Original PR description
Before this commit: ------------------------------------------ - The UrbanPiper payload used a hardcoded tag when the tax percentage was not 5%. - There was no mechanism to add additional tags based on providers, even though UrbanPiper supports multiple tags. After this commit: ------------------------------------------ - Tags are now dynamically handled using the Tag field in the product. - Users can define tags according to their tax configurations and aggregator requirements. - UrbanPiper only accepts relevant tags (default or provider-specific). task - 5154061 Forward-Port-Of: odoo/enterprise#112550 Forward-Port-Of: odoo/enterprise#96742
This update enhances the payment confirmation screen in Point of Sale (POS) and Self-Order to provide clearer feedback to customers. It now displays a 'Processing...' message during payment finalization, a visual success checkmark, and the amount paid upon completion, improving the user experience and confidence during transactions.
Original PR description
In this commit : - Show "Processing..." text while payment finalization is running - Show animated success checkmark and "Amount Paid" once processing completes - Remove warning notification when clicking during processing - Extract shared checkmark animation into reusable template - Update tour tests to verify the success state Task:6246377 Forward-Port-Of: odoo/odoo#269868 Forward-Port-Of: odoo/odoo#267635
Resolved issues and error corrections
This update resolves an error that prevented Manufacturing Administrators from canceling Manufacturing Orders (MOs) when they lacked accounting permissions. The fix adds sudo privileges to allow cancellation, streamlining the process for administrators without requiring full accounting access. This ensures efficient workflow for managing MOs.
Original PR description
Currently, when a user without accounting permissions attempts to cancel a Manufacturing Order (MO), an Access Error is raised. ## Steps to produce: - Install Manufacturing and Accounting with demo…
Currently, when a user without accounting permissions attempts to cancel a Manufacturing Order (MO), an Access Error is raised. ## Steps to produce: - Install Manufacturing and Accounting with demo data. - Users > Marc Demo > Remove Accounting Permissions and give Admin permissions for Manufacturing - Login as Marc Demo - Create an MO for` [D_0045_G] Stool (Green) `and try to cancel it. ## Observed Behavior: Failed to read field mrp.workorder.employee_analytic_account_line_ids ## Root cause: After PR [1], version 19.0 introduced access checks when reading many2many fields. As a result, if a user lacks read access to a model field, an access error is raised. During cancellation, `action_cancel` [2] is called, and the error occurs when unlinking, since the user does not have read access to the account.analytic.line records the system throws an access error. **Why does this error not occur in 19.3+?** Commit [3] added `sudo` to allow cancellation of workorder [2]: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/mrp_workorder_hr_account/models/mrp_workorder.py#L24-L26 ## Solution: Manufacturing Administrators often need to cancel MOs and WOs, but granting them accounting rights solely for this purpose is not always necessary. A practical solution is to allow MO cancellation through sudo privileges, which can be achieved by backporting [3]. [1]: https://github.com/odoo/odoo/pull/217277 [3]: https://github.com/odoo/enterprise/commit/31cf5f014c48b97158042e64ad0b8e9827a6c0d5 Related Community PR: https://github.com/odoo/odoo/pull/264925 opw-6204049 Forward-Port-Of: odoo/enterprise#118950
This update resolves an issue where Intrastat CSV exports were failing due to incorrect formatting of numerical data. The fix ensures that data is properly converted to numeric values before calculations, preventing errors and improving the reliability of export reports. This ensures accurate reporting for Dutch Intrastat data.
Original PR description
During Intrastat CSV export, fields `supplementary_units` formatted using [formatLang](https://github.com/odoo/enterprise/pull/81711/changes), which converts numeric values into strings (e.g.,…
During Intrastat CSV export, fields `supplementary_units` formatted using [formatLang](https://github.com/odoo/enterprise/pull/81711/changes), which converts numeric values into strings (e.g., '84,0'). These string values are later reused in computations, leading to errors like:
```.py
File "/home/odoo/src/enterprise/19.0/l10n_nl_intrastat/models/account_intrastat_report.py", line 163, in l10n_nl_export_to_csv
supp_unit = str(round(res['supplementary_units'])).zfill(10) if res['supplementary_units'] else '0000000000'
TypeError: type str doesn't define __round__ method
```
https://github.com/odoo/enterprise/blob/2bfe0f32c0cec426fc7345ef716395146cc569ca/l10n_nl_intrastat/models/account_intrastat_report.py#L164 This occurs because the export logic expects numeric values, but receives localized strings or None.
Cause:
`formatLang` is applied at the report data level, converting floats into locale-formatted strings. These values are then used directly in arithmetic operations without normalization.
Fix:
Normalize values before computation by:
- Converting input to string
- Replacing locale-specific decimal separators (',' -> '.')
- Casting to float
- Falling back to 0 when value is None or empty
opw-6182286
Forward-Port-Of: odoo/enterprise#116166This update fixes an error in the 401K matching calculation for hourly employees. Previously, when an employee's fixed wage was set to zero, the employer's matching contribution was incorrectly calculated as zero. The fix now accurately calculates the matching contribution based on the employee's actual gross pay, ensuring correct contributions regardless of employment type.
Original PR description
*= test_l10n_us_hr_payroll_account The employer matching cap for pre-retirement plans (401KMATCHING) evaluates to zero for hourly wage employees if wage is set to zero. ### **Steps to Reproduce:** 1)…
*= test_l10n_us_hr_payroll_account The employer matching cap for pre-retirement plans (401KMATCHING) evaluates to zero for hourly wage employees if wage is set to zero. ### **Steps to Reproduce:** 1) Install l10n_us_hr_payroll. 2) Create an employee with an hourly wage and set the fixed wage to 0. 3) Configure the retirement plan parameters as follows: - 401(k) = 3% - Matching Amount = 100% - Matching Yearly Cap = 100% 4) Generate a payslip for this employee and compute the sheet. ### **Observed Behavior:** The "Benefits Matching to Retirement Plans" line computes as zero for the hourly employee. ### **Expected Behavior:** The employer matching contribution should dynamically scale based on the actual gross pay period earnings instead of evaluating to zero. ### **Root Cause:** The calculation of `partial_cap` uses `version.wage` directly at [1]. For hourly employees, the fixed 'wage' field defaults to zero, causing the entire multiplication to cancel out. [1]- https://github.com/odoo/enterprise/blob/4c540f450d4de8b59b871662123f85ed54cca2a9/l10n_us_hr_payroll/data/hr_salary_rule_data.xml#L167 ### **Fix:** This commit computes the retirement matching eligibility cap from `gross annualized wages` and applies the employer matching percentage on the eligible contribution amount. This ensures retirement matching is calculated consistently regardless of the employee's contract type. **opw-6181024** Forward-Port-Of: odoo/enterprise#120570 Forward-Port-Of: odoo/enterprise#119370
This update fixes a bug where overtime wasn't being calculated correctly for attendance shifts that spanned multiple days, specifically on the last day of a weekend. The issue stemmed from a flaw in how the system generated date ranges for overtime rules. This change ensures accurate overtime payments for all shift types.
Original PR description
Steps to reproduce: ---------------------------------------- - Create two rules in an overtime ruleset: - Non-working hours rule: - Timing - Outside of a specific schedule - Select a schedule working…
Steps to reproduce:
----------------------------------------
- Create two rules in an overtime ruleset:
- Non-working hours rule:
- Timing
- Outside of a specific schedule
- Select a schedule working Monday to Friday
- Weekend rule:
- Timing
- On any non-working day
- Give this ruleset to an employee
- Create an attendance for this employee
- from 21pm on Friday
- to 4am on Saturday, the next day
- Check the overtime lines of the attendance
- There is only one overtime line for the first rule
Cause:
----------------------------------------
In the overtime refactor 49952e57ab2e8af908112fa77acd22a5e26fa627 the method `_get_dates()` was introduced to get the dates which an attendance overlap.
It uses `rrule()` to create a list of datetime:
`list(rrule(DAILY, dtstart=localized_start, until=localized_end))`
But `rrule` is returning a new date every 24 hours after the time given in `dtstart`. In our example only the datetime onat 21pm on Friday is returned. If it was ending after 21pm on Friday this time would also be returned.
These dates are given as `min_check_in` and `max_check_out`. So later these dates are used to calculate the non-working days:
https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/hr_attendance/models/hr_attendance_overtime_rule.py#L441-L448
Only Friday is returned, so the second rule is ignored.
Solution:
----------------------------------------
We use `date()` when calling `rrule()` so the hours are ignored.
This has no impact as `min_check_in` and `max_check_out` are always used later with `datetime.combine(min_check_in, datetime.min.time())`.
opw-6159674
Forward-Port-Of: odoo/odoo#267202This update resolves a bug that occurred when propagating delivery carriers from sale orders to purchase order receipts. Specifically, the system incorrectly expected a single carrier ID when multiple carriers were used for related sale orders. This fix ensures that the receipt correctly identifies the carrier, preventing errors and improving order fulfillment accuracy.
Original PR description
Steps to reproduce 1. Set warehouse to 2-step incoming (Input → Stock) 2. Enable "Propagation of carrier" on the push rule (Input → Stock) 3. On the vendor, set "Purchase Orders Grouping" to "Always"…
Steps to reproduce 1. Set warehouse to 2-step incoming (Input → Stock) 2. Enable "Propagation of carrier" on the push rule (Input → Stock) 3. On the vendor, set "Purchase Orders Grouping" to "Always" 4. Create a storable product with the Buy route and that vendor 5. Create two sale orders for that product, each with a different delivery carrier 6. Confirm both sale orders → a single merged purchase order is created 7. Confirm the purchase order → a receipt (Vendors → Input) is created 8. Validate the receipt → ValueError: Expected singleton: delivery.carrier(1, 3) Issue In `_get_new_picking_values`, when the push rule fires to create the internal transfer (Input → Stock), the carrier is fetched from the referenced sale orders: carrier_id = self.reference_ids.sale_ids.carrier_id.id https://github.com/odoo/odoo/blob/5fb0c1f1460949043aa23ddbed09bdbfdc4a8482/addons/stock_delivery/models/stock_move.py#L45 Because both sale orders share the same merged receipt, the receipt move references both. When those SOs have different carriers, `self.reference_ids.sale_ids.carrier_id` returns a multi-record recordset and calling `.id` raises `ValueError: Expected singleton: delivery.carrier(1, 3)`. opw-6126760 Forward-Port-Of: odoo/odoo#270168 Forward-Port-Of: odoo/odoo#262671
This update resolves an issue preventing printing receipts from the Odoo Mobile App for paid orders. The fix allows the app to correctly utilize printing mechanisms previously available on desktop and web versions. This ensures consistent receipt printing across all Odoo Mobile App users.
Original PR description
**Steps to reproduce:** - Go on the Odoo App, start the PoS - Go to orders, and go to paid ones - Click on review - Click on Print Receipt - It doesn't do anything but it prints correctly on browser or desktop **Why the fix:** This is a partial backport of 41e4549 that fixes the app to allow the way we created IFRAMES in PoS since 19.2, allowing us to print on the app again. Community PR: https://github.com/odoo/odoo/pull/265024 opw-6186261 Forward-Port-Of: odoo/enterprise#120043
This update resolves a bug preventing the car simulation information and button from appearing correctly for Belgian employees with car orders. The fix addresses a race condition in the salary calculation process, ensuring the car details and simulation functionality are displayed reliably upon initial setup.
Original PR description
- Step to reproduce: open the salary configurator for a belgian employee with only a car to order linked to its version. Car info and simulation button are not appearing and the page reactivity is broken
- Cause:
- Broken page reactivity is due to a promise that never resolve in willStart super call because of race condition caused by overlapping calls to a debounced function
- Car model description is computed and displayed only when a new value is passed
- Simulation button is rendered only on select value change
- Solution:
- Execute `updateGross()` and `setUpBenefits()` sequentially in parent willStart to prevent overlapping salary recomputations during startup
- Implementing a condition that handle the case of the new car value being already set in the description computation function
- Triggering the new car change function in willStart so that the simulation button is rendered on page load
Task: 6241194
Forward-Port-Of: odoo/enterprise#118647This update resolves an error that occurred when generating payment reports for Swiss companies. The issue arose when the required module was missing, causing a system error. This fix ensures that users can consistently create payment reports for Swiss payrolls.
Original PR description
*=l10n_ch_hr_payroll,hr_payroll_account_iso20022 When clicking the create payment report button on a payslip for a Swiss company, a traceback occurs if the ``hr_payroll_account_iso20022`` module is…
*=l10n_ch_hr_payroll,hr_payroll_account_iso20022 When clicking the create payment report button on a payslip for a Swiss company, a traceback occurs if the ``hr_payroll_account_iso20022`` module is not installed. Steps to reproduce the error: - Install ``l10n_ch_hr_payroll`` module - Switch to CH Company - Create an Employee and running contract for it - Go to Payroll > Payslip > All payslips > Create a new payslip > Set the employee > Confirm > Create payment report Traceback: ```py ValueError: Wrong value for hr.payroll.payment.report.wizard.export_format: 'iso20022_ch' ``` https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_ch_hr_payroll/models/hr_payslip.py#L383 https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_ch_hr_payroll/models/hr_payslip_run.py#L13 Here, ``iso20022_ch`` is passed as ``export_format``, However, ``iso20022_ch`` is added to the selection field in the ``hr_payroll_account_iso20022`` module at [1]. When that module is not installed, the selection value does not exist, leading to the above error. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/hr_payroll_account_iso20022/wizard/hr_payroll_payment_report_wizard.py#L11 sentry-7391832811 Forward-Port-Of: odoo/enterprise#120699 Forward-Port-Of: odoo/enterprise#113277
This update fixes a potential issue where errors during payment processing would display a traceback to users. Now, errors are handled silently, ensuring a smoother experience for users who have already initiated a 'force done' payment. Additionally, a timeout has been added to Cashdro requests to quickly identify and address problems caused by incorrect IP addresses.
Original PR description
In odoo/odoo#268496, a fallback was added to automatically cancel the payment when forcing it, to avoid the cash machine getting stuck with a payment in progress. However, if an error occurs with this cancel request, it causes a traceback to appear. In this commit, we now catch the error from the cancellation, and don't show it to the user at all since they have already force completed the payment. We also add a timeout to Cashdro requests to fail faster when using a wrong IP (e.g. 1.2.3.4). task-6307491 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270339
This update corrects a bug where submitting the Contact Us form incorrectly updated both the new task and existing tasks with the wrong customer information. The fix ensures that task customer information is correctly linked to the project, preventing unintended partner updates and maintaining data accuracy.
Original PR description
Steps to reproduce: -------------------------------------------- 1. Install `website_project` module 2. Create a new project 3. Add a customer to the project 4. Go to customer > add email and phone…
Steps to reproduce:
--------------------------------------------
1. Install `website_project` module
2. Create a new project
3. Add a customer to the project
4. Go to customer > add email and phone
5. Create a new task in that project:
* Observe that the customer is the same as the project
6. Go to Website > Contact Us > Edit > Click on submit button
7. Set action to 'Create a Task' and select the created project in 'Project'
8. Click on Save and Open the URL in Incognito Mode
9. Go to the Contact Us page > Fill in the details > Submit
10. Comeback to our window and open tasks of the created project
Observation:
--------------------------------------------
1. A new task is created using the customer details entered in the form.
2. The existing task’s customer and the project’s customer are also incorrectly updated to this new customer.
Issue:
--------------------------------------------
The bug is in the `extract_data` method of the website form controller for projects.
A non-logged-in user submits the Contact Us form with name and an email that doesn't match any existing partner. The old code's `else` branch would set `partner_name` in the task record values without setting a `partner_id` https://github.com/odoo/odoo/blob/cd080047578b9992811608a5af73a982a414da39/addons/website_project/controllers/main.py#L65-L66
During task creation, the computed field `_compute_partner_id` automatically sets `partner_id` to the project's partner
https://github.com/odoo/odoo/blob/cd080047578b9992811608a5af73a982a414da39/addons/project/models/project_task.py#L1440-L1441
`partner_name` is defined as
https://github.com/odoo/odoo/blob/cd080047578b9992811608a5af73a982a414da39/addons/website_project/models/project_task.py#L12
In Odoo, a related field is essentially a shortcut to a field on a linked record The key attribute here is `readonly=False`. This tells Odoo:
* On read: Get the value from `self.partner_id.name`
* On write: Propagate the write back to `self.partner_id.name` (this is the inverse). So writing `task.partner_name = 'TEST'` is equivalent to writing `task.partner_id.name = 'TEST'`. It modifies the partner record itself, not just the task.
So, the partner record itself was renamed. Every record that references a partner now sees the new name
Solution:
--------------------------------------------
The fix passes `False` to `partner_id`, this way:
* The existing partner is untouched
* All other tasks and the sales order keep their correct customer
opw-6206080
Forward-Port-Of: odoo/odoo#270157
Forward-Port-Of: odoo/odoo#264738This update significantly speeds up inventory adjustments when processing large delivery orders with reserved packages. Previously, adjustments were slow and could freeze the user interface. Now, inventory changes are processed much faster and more reliably, improving warehouse efficiency and user experience.
Original PR description
Behavior before: Adjusting physical inventory quantities for reserved packages takes time when linked to large delivery orders (e.g., 400+ lines). The user interface freezes, causing a poor warehouse…
Behavior before: Adjusting physical inventory quantities for reserved packages takes time when linked to large delivery orders (e.g., 400+ lines). The user interface freezes, causing a poor warehouse user experience during stock counts. Behavior after: Inventory adjustments on reserved packages process faster. The UI remains responsive, and package records are updated instantly without performance degradation. Root Cause: When an inventory adjustment triggers '_free_reservation', it processes move lines sequentially. Inside this loop, Odoo recursively runs '_check_entire_pack()', forcing a full database evaluation of all 400+ delivery lines for every single line adjusted. This results in heavy, redundant processing. Fix: Used a context flag `bypass_entire_pack=True` to silence the '_check_entire_pack()' validation while looping through individual line adjustments. Once the loop completes, the package validation is called exactly once in batch for all affected pickings, preserving data integrity while eliminating redundant database queries. Steps to Reproduce: 1. Have a product tracked by Lot and Package. 2. Have an open delivery order in Ready state (stock reserved) containing 400 or more lines of this product, one package per line. 3. Go to Inventory → Physical Inventory. 4. Set the counted quantity of any reserved bag to 0. 5. Click Apply. 6. Observe that the system takes time to process this single change. 7. Unreserve the delivery order. 8. Perform the same steps as mentioned above. 9. Inventory adjustment is much faster. opw-6234885 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270228
This update resolves an issue where automatic payment terminal integration prevented users from correctly splitting bills. Now, users can manually set the payment amount or use the original 'Send' button, ensuring accurate handling of all payment types within Point of Sale.
Original PR description
Using payment terminals, we automatically send the transaction to the terminal to avoid a click on "Send", but this prevents from setting an amount to send for split bills. We now let the user set an amount, or directly click on "Send". see odoo/enterprise#120672 task-6303855 Forward-Port-Of: odoo/odoo#270240
A recent issue causing the Documents view to crash when accessed through an activity has been resolved. This was due to a timing problem with how the system processed data, leading to an error when trying to set the 'COMPANY' field. This update ensures the Documents view functions reliably.
Original PR description
### Description When navigating to Documents via an activity, the list view crashes with a TypeError on setting 'COMPANY'. ### Root Cause An asynchronous race condition occurs between parent and child `onWillStart` hooks. The child finishes an await before the parent's hook runs `expandDefaultValue()`. Thus, `this.state.expanded[sectionId]` is undefined when the child tries to write to its nested keys. ### Solution Await `sectionsPromise` first in the child hook. opw-6276003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#120713 Forward-Port-Of: odoo/enterprise#119634
This update fixes an issue where Peppol invoices generated for certain German companies were missing the correct buyer reference information. The change ensures that the configured Leitweg-ID is properly included in the XML invoice data, guaranteeing compliance with Peppol standards. This improves the accuracy of invoice data exchange.
Original PR description
**Steps to reproduce:** - Install the `l10n_de` module and switch to a `DE Company`. - Enable `Peppol` in the Invoicing app settings. - Open the `DE Company` customer record. - In the `Invoicing`…
**Steps to reproduce:** - Install the `l10n_de` module and switch to a `DE Company`. - Enable `Peppol` in the Invoicing app settings. - Open the `DE Company` customer record. - In the `Invoicing` tab, change the Peppol ID code from `Germany VAT` to `Germany Leitweg-ID` and set a code (e.g., `13075957-K000-52`). - In the `Contacts & Addresses` tab, create an invoice-type contact named `test`. - Create a new invoice using the `test` contact. - Send the invoice via Peppol. - Download the generated `XML` and inspect the `BuyerReference` field. **Observation:** The `<cbc:BuyerReference>` field is set to `N/A` instead of the configured `Leitweg-ID`. **Root Cause:** At [1], the `BuyerReference` node is populated using `vals['customer']`. For invoices addressed to an invoice-type contact, the contact itself does not contain the Peppol configuration, which is stored on the commercial partner. As a result, the code fails to retrieve the customer's `Leitweg-ID` and leaves the `BuyerReference` field empty. **Fix:** This commit ensures that the configured Leitweg-ID is correctly added to the `BuyerReference` field for child contact. [1]: https://github.com/odoo/odoo/blob/281658e86971687656f3235ac1ff8afcb52f2908/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_xrechnung.py#L87-L97 opw-6269478 Forward-Port-Of: odoo/odoo#270459 Forward-Port-Of: odoo/odoo#269818