Tuesday, May 26, 2026
28 changes · saas-19.3
Resolved issues and error corrections
A recent update to Odoo's document signing process caused errors when downloading signed documents. This fix corrects a problem with how PDF compression was handled, specifically related to newer versions of the pypdf library. The change ensures documents download correctly, improving the user experience within the Sign app.
Original PR description
This [related PR] introduced a compression pass after calls to mergePage(). However in newer versions of pypdf (>=3.5.2), compress_content_streams() can only be called on pages of PdfWriter. An error would be raised when called on pages of a PdfReader. Steps to reproduce ----- 1. Run Odoo with pypdf>=3.5.2 2. Sign and download a document in the Sign app 3. Traceback occurs Fix ---- This commit moves the compression to the writer object, after the merged page has been added. Related pr: https://github.com/odoo/odoo/pull/261879 runbot-937761 Forward-Port-Of: odoo/enterprise#118271 Forward-Port-Of: odoo/enterprise#117756
This update corrects a bug where re-invoiced expenses on sales orders incorrectly displayed the total expense amount as the unit price. The fix ensures that the quantity of the expense is properly reflected on the sales order line, resolving a pricing discrepancy. This improves the accuracy of sales order reporting.
Original PR description
Currently, when re-invoicing an expense paid by company, the line added to the sale order will show a price unit equal to the whole expense amount. Steps to reproduce: - Create a new Expense Category with Re-Invoice Costs set to 'At cost' - Create a new Expense, set the new category, and set Paid By to 'Company' - Set Quantity to greater than 1, and Customer to Re-Invoice to any Sales Order - Confirm and Submit Journal Entry on the Expense record Issue: - On the linked Sales Order you will see the total of the expense is used as the unit price This occurs because we don't pass the quantity to the move line creation vals, which then default to 1. In turn, when the sale order line is added, the unit price will be based on the move line vals but the quantity will match the expense. opw-5883290 Forward-Port-Of: odoo/odoo#246816
This update fixes an issue where Time Off requests with hour durations were incorrectly displaying 12:00 AM instead of calculated hours. The fix ensures that 'request_hour_from' and 'request_hour_to' accurately reflect the requested time off duration, particularly when a default hour-based Time Off type is selected. This improves the accuracy of Time Off requests.
Original PR description
…to hours ## Issue: 'request_hour_from' and 'request_hour_to' should be computed using the default calendar attendance values, but instead they display 12:00 AM, meaning their values remain 0.0. ##…
…to hours ## Issue: 'request_hour_from' and 'request_hour_to' should be computed using the default calendar attendance values, but instead they display 12:00 AM, meaning their values remain 0.0. ## Steps to Reproduce: - Open the Time Off app. - Configure a Time Off Type with the Duration Type (request_unit) set to Hours. - Set this Time Off Type as the default one while creating a new Time Off. - Create a new Time Off request. - Observe that 'request_hour_from' and 'request_hour_to' are not computed and display 12:00 AM (0.0). ## Root Cause: While fixing the issue related to preserving leave hours when changing Time Off Types, a regression was introduced. Related PR: https://github.com/odoo/odoo/pull/227235 During the creation of a new Time Off with the duration type set to Hours by default, the field 'request_unit_hours' is already True. This prevents the computation of 'request_hour_from' and 'request_hour_to', resulting in both values remaining 0.0. ## Solution: Compute 'request_hour_from' and 'request_hour_to' when their values are still 0.0 (initial Time Off creation case), and skip recomputation only when switching between Time Off Types in order to preserve manually entered hours. Steps to reproduce : [Video](https://drive.google.com/file/d/1P2MFIj8ZxFtFxv2FlX4Zdq6P-5veTxUb/view?usp=sharing) OPW: 6209992 Forward-Port-Of: odoo/odoo#266104 Forward-Port-Of: odoo/odoo#264707
This update resolves an issue where cancelled food delivery orders continued to show as 'Draft' in the POS interface. The fix synchronizes the POS order state with the delivery state upon cancellation, ensuring that preparation displays are also updated correctly. This improves the accuracy of order status and prevents confusion for staff.
Original PR description
pos*: pos_urban_piper, pos_enterprise When a food delivery order is cancelled from the aggregator side, the PoS order remains active on the frontend instead of reflecting the cancelled state. Steps to reproduce: - Configure UrbanPiper with Atlas - Place an order via Atlas - Open the order from the notification bar - Cancel the order from Atlas Issues: - Cancelled orders continue to appear in `Draft` - Accepted/preparation orders are not cancelled on the preparation display Fix: - Synchronise the PoS order state with the delivery state on cancellation - Update preparation display orders when delivery orders are cancelled Task-6217704 Forward-Port-Of: odoo/enterprise#118288 Forward-Port-Of: odoo/enterprise#117374
This update resolves an issue where importing company data would incorrectly trigger the installation of language-specific (L10N) modules, leading to errors and data corruption. The fix ensures that L10N modules are only installed when explicitly requested, improving import stability and data integrity.
Original PR description
# How to reproduce - Start from a fresh database - Install the account module - Import companies with a data file. These companies need to have a country set and the data file needs to contain some…
# How to reproduce - Start from a fresh database - Install the account module - Import companies with a data file. These companies need to have a country set and the data file needs to contain some bad data - Click on the Test button # The problem An Odoo Server Error is displayed saying : "savepoint xxx does not exist", which prevents the import or hides other potential error. More importantly, the date is imported even though it was a test run. # Cause Importing companies with a country will import their respective l10n modules using `button_immediate_install()` : https://github.com/odoo/odoo/blob/6de867f1c92bacedc0574b63e9e6a2a57fe805dd/odoo/addons/base/models/res_company.py#L319-L322 https://github.com/odoo/odoo/blob/661ddbb7f12e32394a3c11b5a4cd2f38a9e156f5/odoo/addons/base/models/res_company.py#L237 This import calls `cr.commit` : https://github.com/odoo/odoo/blob/661ddbb7f12e32394a3c11b5a4cd2f38a9e156f5/odoo/addons/base/models/ir_module.py#L632-L634 The issue is that when importing a data file, we create savepoints : https://github.com/odoo/odoo/blob/661ddbb7f12e32394a3c11b5a4cd2f38a9e156f5/odoo/orm/models.py#L971-L974 And if an error arise during our import, we rollback to the appropriate save point. Sadly, commiting erases any existing save point, so a savepoint error is rased and the data is not rolled back. The problem stems from the fact that importing module is simply not transactionnal and `button_immediate_install()` is not expected to be called with a savepoint. This was already partly adressed by : https://github.com/odoo/odoo/commit/66dcee9aa70dc72a332fde64dbc802266bbe4a5a But it did not cover the file importing case opw-6174983 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265188
This update significantly speeds up the generation of Point of Sale reports by optimizing a key database query. Previously, the system searched through millions of account moves, which was slow. Now, the query is more efficient by targeting only account moves linked to specific payment journals, resulting in a much faster response time.
Original PR description
Currently the query to get the closing difference account move is done by searching for the reference of the move, which is not very efficient. This commit optimizes this query by adding the journal…
Currently the query to get the closing difference account move is done by searching for the reference of the move, which is not very efficient. This commit optimizes this query by adding the journal to the search criteria, which allows us to benefit from the index on the journal_id field. Here is an example of the before after on a database with 39 million account_move records. Meanwhile only 10-20K account_move are linked to specific journals used in POS payment methods. All measures are performed with a warmed up cache [Explain Before](https://explain.dalibo.com/plan/h8edf56c09d7dfd7) ### Benchmark: <table> <thead> <tr> <th># of am</th> <th>Before</th> <th>After</th> </tr> </thead> <tbody> <tr> <td>38982635</td> <td>~17s</td> <td>~22ms</td> </tr> </tbody> </table> [Explain After](https://explain.dalibo.com/plan/be2397f176a6b29d) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262148
This update resolves a bug that caused errors when confirming rental orders in versions 17 and 18, and a subsequent division-by-zero error in newer versions. The fix ensures that the system correctly handles rental orders with kits, preventing errors and improving order processing reliability.
Original PR description
**Steps to produce:** - Install `sale_mrp_renting`. - Enable `Rental Transfers` from settings. - Create a rental product. - Create two variants of the product. - Create a BoM for one variant and set…
**Steps to produce:** - Install `sale_mrp_renting`. - Enable `Rental Transfers` from settings. - Create a rental product. - Create two variants of the product. - Create a BoM for one variant and set its type to `Kit`. - Create a rental order using the other variant. - Try to confirm the order. **Issue:** In versions 17 and 18, a UserError is raised- ``` The unit of measure Units defined on the order line doesn't belong to the same category as the unit of measure False defined on the product. Please correct the unit of measure defined on the order line or on the product, they should belong to the same category. ``` From version 18.2 onward, a different error occurs ``` ZeroDivisionError: float division by zero ``` **Root cause:** In versions 17 and 18: At [1], since the BoM is created for a different variant , no BoM is found for the selected variant. As a result, when `_compute_quantity` is called at [2], the `bom.product_uom_id` is empty, which leads to the `UserError` from `_compute_quantity` method. In version 18.2+: At [1], as the BoM is empty. Then at [3], `_compute_kit_quantities` is called with an empty BoM, and at [4], this results in a division by zero error. **Solution:** Skip the computation when no BoM is found and directly return the quantity to avoid both the `UserError` and the `ZeroDivisionError`. [1]https://github.com/odoo/enterprise/blob/eaa70dcab2b49eadca1cf36008dd80cfccbb8e4e/sale_mrp_renting/models/sale_order_line.py#L13 [2]https://github.com/odoo/enterprise/blob/eaa70dcab2b49eadca1cf36008dd80cfccbb8e4e/sale_mrp_renting/models/sale_order_line.py#L20 [3]https://github.com/odoo/enterprise/blob/eaa70dcab2b49eadca1cf36008dd80cfccbb8e4e/sale_mrp_renting/models/sale_order_line.py#L21 [4] https://github.com/odoo/odoo/blob/91b09dbea5c8a306b5e9d2120466777f0248b360/addons/mrp/models/stock_move.py#L676 **opw-6082434** Forward-Port-Of: odoo/enterprise#118207 Forward-Port-Of: odoo/enterprise#114176
This update fixes a critical issue where canceled orders in the Point of Sale (POS) system weren't immediately reflected on the frontend. The change ensures that cancellations made in the backend are accurately displayed in the POS interface, improving order accuracy and reducing potential customer confusion. This update was triggered by a bug fix.
Original PR description
Step: --------- - Install point_of_sale. - Open a POS session with presets configured. - Add an order line and select the takeout order preset. - Cancel the order from the backend. Issue: --------- - The cancelled order is not reflected in the frontend. Cause: --------- - The frontend is not notified when the order is cancelled from the backend. Fix: --------- - Notify the frontend when a backend order is cancelled. Task-5406984 Forward-Port-Of: odoo/odoo#264791 Forward-Port-Of: odoo/odoo#240725
This update fixes an issue where the picking origin document incorrectly referenced the previous MO name after a manufacturing operation type was changed before confirmation. The fix ensures that the picking document accurately reflects the new MO name, improving inventory accuracy and preventing potential order fulfillment errors. This was triggered by a multi-step manufacturing route.
Original PR description
**Issue**: When the name of a MO changes before confirmation, the picking origin may remain incorrect after confirmation. **Steps to reproduce**: - Make sure that multi-step route is enabled in the…
**Issue**: When the name of a MO changes before confirmation, the picking origin may remain incorrect after confirmation. **Steps to reproduce**: - Make sure that multi-step route is enabled in the settings - Configure the manufacturing route as 2-step - Go to Inventory > Configuration > Warehouse Management > Operations Types - Clone the "Manufacturing" operation type and assign a different Sequence Prefix - Create and save a MO, without confirming it - Change and save the operation type to the cloned one (the MO name changes) - Confirm the MO -> The picking source document uses the previous MO name instead of the new one **Cause**: The source document of the picking (`origin`) comes from its move: https://github.com/odoo/odoo/blob/95c73aa4dd7433f394799fdaaad57a84d750ec5a/addons/stock/models/stock_move.py#L1526 The move origin comes from the procurement values: https://github.com/odoo/odoo/blob/95c73aa4dd7433f394799fdaaad57a84d750ec5a/addons/stock/models/stock_move.py#L1575C13-L1575C56 Which relies on `self.reference_ids[0].name`: https://github.com/odoo/odoo/blob/95c73aa4dd7433f394799fdaaad57a84d750ec5a/addons/stock/models/stock_move.py#L1639 which is never updated, causing the origin to keep the previous MO name. opw-5979778 Forward-Port-Of: odoo/odoo#255874
This update ensures that forced full packaging reservations are correctly applied, even when large quantities of stock are available. Previously, the system was incorrectly calculating reservations based on multiples of packaging units, leading to inaccurate stock levels. This fix now accurately reflects the intended behavior of reserving only full packaging units.
Original PR description
Issue ----- Forced full packaging reservation setting is ignored when there is a big quant in stock. Steps to reproduce ----- - Enable packagings - Create a product category "Super Category" -…
Issue
-----
Forced full packaging reservation setting is ignored when there is a big quant in stock.
Steps to reproduce
-----
- Enable packagings
- Create a product category "Super Category"
- Reserve Packagings: Reserve Only Full Packagings
- Create a stored product "AAA"
- Product Category: Super Category
- 50 units on hand
- Packaging: 6-Pack (6 units)
- Create a delivery for 15 units of AAA
> Reservation is made for 15 units
Cause
-----
The rounding to a multiple of the packaging quantity takes the stock quant into account. For our example case, we have 8 full 6-Packs on hand, so the `available_quantity` gets set to 48 when doing
https://github.com/odoo/odoo/blob/5e458236ca2ff2ab92c4893495e7a721be902c40/addons/stock/models/stock_quant.py#L923-L925
This leads to the reservation quantity being min(15, 48) = 15
https://github.com/odoo/odoo/blob/5e458236ca2ff2ab92c4893495e7a721be902c40/addons/stock/models/stock_quant.py#L927
-----
Ticket:
opw-5974333
Forward-Port-Of: odoo/odoo#263934
Forward-Port-Of: odoo/odoo#257342This update fixes inaccuracies in how the Mexican employment subsidy was calculated, specifically addressing issues with threshold prorating and cumulative monthly caps. The changes ensure employees receive the correct subsidy amounts based on updated government regulations, improving payroll accuracy and compliance.
Original PR description
The employment subsidy calculation was incorrect in two main scenarios: ### 1. Incorrect threshold prorating: The system was comparing the salary against the full monthly limit even for partial…
The employment subsidy calculation was incorrect in two main scenarios:
### 1. Incorrect threshold prorating:
The system was comparing the salary against the full monthly limit even for partial periods (weekly or bi-weekly). This resulted in employees wrongly receiving the subsidy when their proportional salary actually exceeded the limit.
Example: In 2026, the 14-day threshold should be 5,292.67 (11,492.66 / 30.4 * 14). Currently, an employee earning 10,000.00 in those 14 days still gets the subsidy because it's being compared against the full 11,492.66.
### 2. Cumulative monthly cap:
When multiple payslips occur in the same month, the total subsidy sometimes exceeds the statutory monthly maximum (536.22 for 2026) because the cap wasn't enforced across all slips.
Example: The 2026 maximum monthly subsidy is 536.22. In a month with three partial payslips:
- Mar 1st - Mar 14th: The system grants 246.68.
- Mar 15th - Mar 28th: The system grants 246.68.
- Mar 29th - Apr 11th: For the 3 days belonging to March, the system grants an additional 52.86.
Total subsidy for March reaches 546.22, exceeding the legal cap.
### Changes included in this PR:
- Updated `l10n_mx_rule_parameter_uma` to include monthly and annual values. This prevents rounding discrepancies.
Example: the 2026 annual UMA published is 42,794.64. In a rule the calculation is: l10n_mx_uma * 30.4 * 12 = 117.31 * 30.4 * 12 = 42,794.68 resulting in a ~0.04 difference.
- Create a new rule parameter `l10n_mx_rule_parameter_subsidy_salary_limit` to have the subsidy eligible threshold. Starting in 2026, the government's rounding changed from zero decimals(e.g., 9,081.00 in 2024, 10,171.00 in 2025) to two decimals (11,492.66). Storing these as explicit parameters avoids the precision errors.
- Added comprehensive unit tests covering:
- Complete periods: validates standard payslips aligned with the month calendar (bi-monthly, monthly, bi-weekly).
- Overlapping periods: validates split-month scenarios (14-day, 10-day, weekly) where periods cross month boundaries:
Example of self._overlapping_period("weekly", 7, 2646.33, (35.24, 88.10), (3, 123.34), (77.53, 35.24))
This test covers 5 weekly payslips with the following subsidy
distribution:
- Tuple `first_payslip` => (35.24, 88.10) means that:
First payslip (Apr 29 - May 5), the subsidy is 35.24 for April and 88.10 for May.
- Tuple `mid_payslips` => (3, 123.34) means that:
For the next 3 payslips fully in May, the subsidy is 123.34 each.
Payslip 2 (May 6 - May 12): Subsidy for May = 123.34
Payslip 3 (May 13 - May 19): Subsidy for May = 123.34
Payslip 4 (May 20 - May 26): Subsidy for May = 123.34
- Tuple `last_payslip` => (77.53, 35.24) means that:
Last payslip (May 27 - June 2), the subsidy is 77.53 for May and 35.24 for June.
- Across years: subsidy amounts and limits are updated annually.
Therefore, if a period overlaps two years, a salary amount might be eligible for a subsidy in January but not in the previous December, and the paid subsidy is increased in January due to the new limits.
- Cleaned up redundant tests (test_regular_payslip_subsidy) and adjusted decimal precision.
- For split-month `schedule_pay` periods, the first payslip might generate a subsidy. However, in subsequent payslips, due to commissions or a wage increase, the employee may exceed the monthly subsidy salary limit.
In those payslips, a warning is shown to notify the user that a manual adjustment is required.
Created tests to validate these cases.
target: 19.0
task-5419659
Forward-Port-Of: odoo/enterprise#116779
Forward-Port-Of: odoo/enterprise#107601This update fixes an issue where packaging unit information was hidden on delivery slips after a transfer was validated for products tracked by serial/lot. The change ensures that the correct packaging unit and quantity are consistently displayed, providing more accurate reporting for inventory movements. This improves visibility and accuracy in stock management.
Original PR description
Issue before this commit: ========================= For products tracked by serial/lot with packaging units, the delivery slip correctly shows the packaging unit and quantity before validating the…
Issue before this commit: ========================= For products tracked by serial/lot with packaging units, the delivery slip correctly shows the packaging unit and quantity before validating the transfer. However, after validating the transfer, the packaging unit and its corresponding quantity are no longer displayed in the delivery slip report. Steps to Reproduce: ========================= 1. Install stock and sale_management modules. 2. Enable Units of Measure & Packagings and Display Lots & Serial Numbers on Delivery Slips from settings. 3. Create a product with tracking by lot/serial number and configure a packaging unit. 4. Create a SO using this product with a packaging unit and confirm it. 5. Open the related transfer and print the delivery slip before and after validation. Cause of the Issue: ========================= The delivery slip report template (stock_report_delivery_has_serial_move_line) does not display packaging unit information after validation for move lines when the packaging unit differs from the product unit of measure. With This Commit: ========================= This commit ensures that packaging units and their corresponding quantities are displayed on the delivery slip after validation when the packaging unit differs from the product unit of measure. Steps To Reporduce: [Video Link](https://drive.google.com/file/d/10DmFKW1Y_Tm-AyKzPrqtFMY8orBkKbIm/view?usp=sharing) opw-6142052 Forward-Port-Of: odoo/odoo#266028 Forward-Port-Of: odoo/odoo#265206
This update fixes an issue where pension fund taxes weren't being correctly applied when importing Italian electronic vendor bills. The change ensures that the system now accurately processes invoices generated by third-party software, even if they don't include all the expected XML tags, guaranteeing accurate tax calculations for Italian businesses.
Original PR description
### Issue before this commit: When importing an Italian electronic vendor bill using the AssoSoftware standard, pension fund taxes (Cassa Previdenziale) are not applied to the invoice lines. ###…
### Issue before this commit: When importing an Italian electronic vendor bill using the AssoSoftware standard, pension fund taxes (Cassa Previdenziale) are not applied to the invoice lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it_edi_witholding 2. Change VAT number of IT company with the one in the xml 3. Go to Taxes > 4%F.Pens. > Advanced Options and change Pension Fund Type with TC02 4. Import xml of the ticket in vendor bills 5. P.Fund tax is not assigned ### Cause of the issue: The issue is caused by the following line: https://github.com/odoo/odoo/blob/669b9b84f4d5c8765dc4b451d5da6a95dbb9ded8/addons/l10n_it_edi_withholding/models/account_move.py#L247 Currently, the parser strictly expects the optional <RiferimentoTesto> tag alongside <TipoDato>AswCassPre</TipoDato>. However, several third-party software providers generate valid XML files containing only the AswCassPre block without any optional child tags. ### Reason to introduce the fix: Ensure that the pension fund tax mapped to the line's VAT rate is correctly applied whenever the AswCassPre data type is present, even if the optional reference tags are omitted. opw-6189225 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265914 Forward-Port-Of: odoo/odoo#264083
This update corrects a bug where the Gantt view incorrectly displayed working hours for flexible employees on public holidays. The fix ensures that unavailable time is accurately reflected, preventing employees from scheduling work during holiday periods. The issue stemmed from timezone discrepancies during the calculation of employee availability.
Original PR description
[FIX] hr_attendance_gantt: fix gantt view with public holidays Bug reproduction: 1 - Select flex schedule employee (or change its schedule to 40h flex one) and make its contract before 01/01/2026 2 -…
[FIX] hr_attendance_gantt: fix gantt view with public holidays
Bug reproduction:
1 - Select flex schedule employee (or change its schedule to 40h flex one) and make its contract before 01/01/2026
2 - Create a new public holiday on 01/01/2026 (from 00.00 to 23.59 or 23.55 (depends on version, it does not matter))
3 - in attendance app the cell from 00.00 to 01.00 seems white for that day and for selected employee (this cell seems like not holiday and employee can work)
Bug cause:
1 - After a long traceback, _gantt_unavailability in hr_attendance_gantt/HrAttendance, if an employee is flexible then unavailable_intervals is calculated with the Brussel time zone
2 - All other unavailable intervals are converted to the UTC in the function of _gantt_unavailability except in the final lines of the function.
3 - When the employee is flexible and since the conversion is not done in the final lines, it remains 1 hour more (UTC+1), it is from 1 am to 1 am of next day instead of 0 am to 23.59.
Bug solution:
1 - I converted the timezone to UTC to solve the problem.
task - 6067070
Forward-Port-Of: odoo/enterprise#112493This update optimizes a key stock query that previously performed very slowly due to complex string comparisons. By replacing these comparisons with a more efficient method of checking location ancestry, the query now runs significantly faster, especially when dealing with large lists of locations. This improves overall system responsiveness and reduces potential delays in stock management operations.
Original PR description
### Description of the issue/feature this PR addresses: Some stock queries determine whether a location belongs to the subtree of a set of locations by checking the parent_path prefix against…
### Description of the issue/feature this PR addresses:
Some stock queries determine whether a location belongs to the subtree of a set of locations by checking the parent_path prefix against candidate parent locations. This is done using a correlated EXISTS subquery with a LIKE parent.parent_path || '%' condition.
When the list of candidate locations becomes large (for example tens or hundreds of thousands of ids), this approach causes extremely poor performance because the database must repeatedly compare hierarchical path strings for every candidate row.
This PR improves the performance of this ancestry check by replacing the string prefix comparison with a direct check on the ancestor ids contained in parent_path.
### Current behavior before PR:
The query determines whether a location belongs to the subtree of one of the provided locations using:
location.parent_path LIKE parent.parent_path || '%'
For each row, PostgreSQL must evaluate a correlated subquery against all candidate parent locations. Because this relies on string prefix comparisons on parent_path, when the location list is large, this results in extremely slow queries.
### Desired behavior after PR is merged:
Instead of performing string prefix comparisons, the query extracts the ancestor ids directly from parent_path.
The path is:
1. Trimmed to remove leading and trailing /
2. Split into an array of ancestor ids
3. Expanded using unnest
4. Checked for intersection with the provided location ids
This converts the ancestry check from repeated string comparisons into a simple integer membership check.
### Benchmarks
Comparing performance of old subquery:
```
SELECT stock_location_inner.id
FROM stock_location AS stock_location_inner
WHERE EXISTS (
SELECT 1
FROM stock_location parent
WHERE parent.id IN (long list)
AND stock_location_inner.parent_path LIKE parent.parent_path || '%%'
);
```
to new one:
```
SELECT stock_location_inner.id
FROM stock_location AS stock_location_inner
WHERE EXISTS (
SELECT 1
FROM unnest(
string_to_array(trim(both '/' FROM stock_location_inner.parent_path), '/')::int[]
) AS path_id(id)
WHERE path_id.id IN (long list)
);
```
Depending on the number of elements in 'long list'
| # of elements | Before | After |
| --- |---|---|
| 130,000 | 21min | 0.8sec |
| 10,000 | 95sec | 0.5sec |
| 1,000 | 10.5sec | 0.5sec |
In practice, on the reference ticket this causes the "Validate" button on a stock picking to go from timing out to taking 8 seconds.
### Reference
opw-5932436
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#255399
Forward-Port-Of: odoo/odoo#254245This update fixes an issue where employees with time off were incorrectly checked out after their scheduled work hours. The change ensures that the system accurately calculates expected attendance based on employee contracts and time off, preventing over-reporting of hours worked. This improves the accuracy of time tracking and payroll.
Original PR description
# Steps to reproduce 1. Set the Working schedule 40h/week 2. Employee takes 2 hours off from 15:00 to 17:00 and enable automatic check-out 3. Odoo will automatically checks out at 17:06 (scheduled end + tolerance) # Issue - This leads to 2h06 of extra hours being incorrectly recorded. # Fix - Use employee._get_expected_attendances instead, so contract-aware calendar resolution, leaves, and break time handling stay centralized in HR. task-5052044 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#235442
This update resolves an error occurring when sending purchase bills with agricultural tax (ClaveRegimenIvaOpTrascendencia) through the TicketBAI system in Spain. The issue stemmed from an incorrect value being submitted, preventing proper invoice processing. This fix ensures accurate transmission of tax information.
Original PR description
…hase bills **STEP TO REPRODUCE** 1. Create a bill with a invoice line with a regimen agricultura tax. 2. send the bill using TicketBAI. 3. You will get the following error: Error:cvc-enumeration-valid: Value '19' is not facet-valid with respect to enumeration '[01, 02, 03, 04, 05, 06, 07, 08, 09, 12, 13]'. It must be a value from the enumeration. opw-6200686 Forward-Port-Of: odoo/odoo#265785 Forward-Port-Of: odoo/odoo#264037
This update resolves an issue where users on Android 14 couldn't access their device's camera when uploading images through the Odoo web interface. The fix adds support for camera access, ensuring users can select photos directly from their device. This improves usability for Android users.
Original PR description
Since Android 14 we don't have option to take a photo on clicking on file input in Chrome.
This for example will allow only images but no option "Camera"
```html
<input type="file" accept="image/*/>
```
A workaround is to use a dummy mimetype (`*/*`), example `dummy/allowAndroidCamera` The fix will be applied on image widget in addition to the original `acceptedFileExtensions` to not override the existing `accept` attribute
You can test the different behaviour here: https://jsfiddle.net/n0vs6h3b/
Linked url
https://blog.addpipe.com/html-file-input-accept-video-camera-option-is-missing-android-14-15/ https://stackoverflow.com/questions/77876374/html-input-type-file-not-working-to-pull-up-camera-for-pixel-android-14-comb/79163998#79163998 https://issues.chromium.org/issues/40937303
opw-6040375
Forward-Port-Of: odoo/odoo#265944
Forward-Port-Of: odoo/odoo#265750This update fixes an issue where applying a combo to an order that had already been processed would cause the original order items to reappear after a page refresh. The fix ensures that the order is synchronized with the backend after a combo is applied, providing a consistent and accurate view for the user.
Original PR description
Steps to reproduce: - Make an order that could be a combo - Send the order to preparation - Apply the combo - Refresh page => A new combo appears and the original orderlines are still there. Issue: When applying a combo to an order that has already been sent to the backend it is not synched with the backend so when you refresh the original orderlines are fetched from the backend. Fix: If the orderlines have been sent to the backend sync the order after applying the combo. 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 Forward-Port-Of: odoo/odoo#261294
This update corrects a previous issue where product manufacturing quantities were incorrectly using planned amounts instead of actual production. Now, Odoo accurately reflects the real quantity of products that have been made, leading to more precise inventory management and reporting. This ensures better data for decision-making.
Original PR description
* Before: the manufactured quantity on product use the planned quantity * After: Use actual produced quantity 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 Forward-Port-Of: odoo/odoo#265550 Forward-Port-Of: odoo/odoo#261438
This update fixes an issue where the search dropdown on the /shop page was partially hidden behind snippet blocks. The fix ensures the full search results are displayed correctly, improving the user experience for browsing products. This was achieved by adjusting how the website handles overlapping content.
Original PR description
On /shop, when a snippet block sits above the searchbar, the search dropdown was rendered partially hidden behind that block (cropped/unreadable items). Steps to reproduce: =================== 1. Go…
On /shop, when a snippet block sits above the searchbar, the search dropdown was rendered partially hidden behind that block (cropped/unreadable items). Steps to reproduce: =================== 1. Go to /shop. 2. Add a snippet block above the searchbar. 3. Type in the searchbar. => Observed: search results appear cropped, with upper items hidden behind the snippet block above. Root cause: =========== the products grid column (`#products_grid`) has `overflow: auto`, https://github.com/odoo/odoo/blob/d9bb1c1dc90f97b63b87ad762fc4ab36abf7e05f/addons/website_sale/static/src/scss/website_sale.scss#L442 which clips any absolutely-positioned descendant that extends past its bounds. The dropdown's containing block is the searchbar `<form>` (position: relative), which lives inside that column. When the dropdown grew (or flipped to dropup) and extended outside the column, the part outside was clipped, and any positioned snippet siblings above the column painted over the clipped area. Fix: ====== while the dropdown is mounted, lift the `overflow: auto` on its ancestor `div.col` so the menu can extend past the column and paint on top of other content. Done from JS so no SCSS rule has to target the searchbar-specific column. opw-6216317 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265982 Forward-Port-Of: odoo/odoo#265558
This update fixes a bug where users could order unlimited quantities of rental products. The change limits the available quantity to the minimum rental availability, ensuring accurate resource allocation and preventing overbooking. This improves the reliability of our rental service.
Original PR description
It is possible to order as many products as we want of a rental product that synchronizes shifts depending on a specific service Steps to reproduce: 1. Install website_sale_renting_planning module 2.…
It is possible to order as many products as we want of a rental product that synchronizes shifts depending on a specific service Steps to reproduce: 1. Install website_sale_renting_planning module 2. Go to Rental > Products and create a new product "test" with Sales enabled, Product Type "Service", Plan Services enabled as "Developer", in the Sales tab, enable Is Published and in the Rental prices tab, create a pricing for Daily period 3. In the General Information tab, click on the internal link to "Developer" 4. Enable Sync Shifts and Rental Orders 5. Go to the eCommerce website and search for product "test" 6. You can add as many quantity of the product to your cart Issue: We don't limit the maximum quantity of the product Solution: Look through the renting availabilities of the product and set the maximum quantity to the minimum of the availabilities relevant to the renting dates selected opw-6009928 Forward-Port-Of: odoo/enterprise#113525 Forward-Port-Of: odoo/enterprise#111793
This update resolves an issue where the timesheet timer wouldn't function when accessed from a subtask. The fix ensures the timer correctly opens and pre-fills with the subtask's project details, preventing a 'missing record' error. This improves usability for users managing tasks and subtasks.
Original PR description
**Problem:** Clicking the timesheet timer in the systray while viewing a subtask raises a MissingError, preventing the user from starting the timer. **Steps to reproduce:** 1. Open a project task…
**Problem:** Clicking the timesheet timer in the systray while viewing a subtask raises a MissingError, preventing the user from starting the timer. **Steps to reproduce:** 1. Open a project task that has subtasks 2. Click the subtasks smart button and open a subtask 3. Click the timesheet timer icon in the systray 4. Observe the "missing record" error **Current behavior:** The systray RPC fails with MissingError. **Expected behavior:** The timer opens, with the subtask's project and task prefilled. **Cause of the issue:** The frontend sends `currentState.active_id` regardless of the model it refers to. When the user navigates to a subtask via the smart button, `active_id` is the parent task's id. The systray controller then does `request.env['project.project'].browse(active_id)`, which returns a truthy recordset for an id that does not exist in `project_project`. Reading `.allow_timesheets` on that recordset triggers the DB fetch and raises MissingError. The same pattern exists in the `helpdesk_timesheet` override for both the `project.task` and `helpdesk.ticket` branches. **Fix:** Adding `.exists()` after the browse validates the recordset before any field access, so a stray `active_id` falls through to the task's own project (or ticket's project) instead of crashing. opw-6169548 Forward-Port-Of: odoo/enterprise#117039
This update corrects a bug where certain quality control test types were incorrectly visible during work order creation. The change ensures these test types are only accessible for manufacturing operations, improving data accuracy and preventing misconfiguration. This was caused by an optimization in Odoo's domain filtering.
Original PR description
### Issue: The `Print Label`, `Register Production`, `Register By-products`and `Register Consumed Materials` are all available in the test types at control point creation. ### Expected behavior:…
### Issue:
The `Print Label`, `Register Production`, `Register By-products`and `Register Consumed Materials` are all available in the test types at control point creation.
### Expected behavior:
These test types are only meant for manufacturing operations and are supposed to be hidden by the field domain:
https://github.com/odoo/enterprise/blob/f56aa85b4ad32c5d9ad5593df1366d72e88da0e4/mrp_workorder/models/quality.py#L102-L104 https://github.com/odoo/enterprise/blob/00d6cccd75c402378698a6fd11ee2692f2361c7f/mrp_workorder/models/quality.py#L20-L24
### Cause of the issue:
Since saas-18.1: 5ef007a2116e528b796ebe80fb291ba5f1a94c8f domains are optimised into equivalents SQL clause with better sql performances. This optimization results in the following match for boolean fields:
`('field', '=', True)` -> `('field', 'in', OrderedSet([True]))`
`('field', '=', False)` -> `('field', ' not in', OrderedSet([True]))`
Because of these:
https://github.com/odoo/odoo/blob/82b16e8feb3d60a9a3855e3adb3164ae5a6c041d/odoo/orm/domains.py#L1058-L1079 https://github.com/odoo/odoo/blob/82b16e8feb3d60a9a3855e3adb3164ae5a6c041d/odoo/orm/domains.py#L1215-L1236
Now the issue is that the specific `search_method` of the `allow_registration` field is then called with this optimized domain: https://github.com/odoo/odoo/blob/82b16e8feb3d60a9a3855e3adb3164ae5a6c041d/odoo/orm/domains.py#L860-L866 https://github.com/odoo/enterprise/blob/00d6cccd75c402378698a6fd11ee2692f2361c7f/mrp_workorder/models/quality.py#L20-L24
And since `value` is defined as a non empty ordered set in both cases it the search method returns a True leaf as search domain.
opw-5915197
Forward-Port-Of: odoo/enterprise#118073
Forward-Port-Of: odoo/enterprise#117068This update fixes an error in how overtime hours are calculated for employees with flexible work schedules. Previously, the system incorrectly generated extra hours, now it accurately reflects the employee's scheduled hours and overtime rules. This ensures accurate overtime payments for flexible staff.
Original PR description
__ ## Short functional explanation of the error When setting attendances on several consecutive days for a flexible employee, with an overtime ruleset containing a single rule. This rule being based…
__ ## Short functional explanation of the error When setting attendances on several consecutive days for a flexible employee, with an overtime ruleset containing a single rule. This rule being based on week and quantity. When regenerating overtimes for this ruleset, the overtime hours generated isn't correct. ## Reproduction Steps 1. Create an employee. In the Payroll tab, set a start date for their contract. Set Work Entry Source as Attendances. Set their Working Hours as a flexible schedule. Set their weekly hours at 40. 2. Create an Overtime Ruleset. Add a single rule, based on Quantity, if the worked hours on a `Week` differs `from the amount defined on the contract`. Check Pay Extra Hours and leave the Work Entry Type to use as Overtime Hours. 3. Go back to the employee. In Settings, set the Overtime Ruleset field as the new Overtime Ruleset you just created. 4. Create 5 attendances, each from 8 am to 6 pm, from Monday to Friday. 5. Go to the Overtime Ruleset you just created and click on Regenerate Overtimes. 6. Go back to Attendances. Search for your employee, and click on the list view. ### Expected behavior The employee's schedule is 40 hours per week. They worked 50 hours. 10 hours should be considered as Worked Extra Hours. ### Unexpected behavior 18 hours are considered as extra hours. ## Origin of the issue To compute the expected duration of the day, we run: https://github.com/odoo/odoo/blob/7fc5edc29f854d619dbcb5fcc3503fb18ca05335/addons/hr_attendance/models/hr_attendance_overtime_rule.py#L303-L304 where `schedule['work']` will contain intervals on 5 consecutive days, from 8 am to 4 pm. However, the last day of the employee's attendances isn't contained in these intervals. As a result, `period_schedule` will contain 4 days (the common days between the employee's Attendance days and `schedule['work']` ) and thus, `expected_duration` will be set at 36 hours instead of 40. In the case where overtimes are computed based on hours from the contract, for flexible employees, the expected hours are the ones indicated on their schedule. __ opw-6131543 Forward-Port-Of: odoo/odoo#265120 Forward-Port-Of: odoo/odoo#263335
This update resolves a problem where Xrechnung invoices generated in Odoo were failing validation checks used by some German clients. The issue stemmed from incorrect PDF formatting, preventing the invoices from meeting required standards. This fix ensures Odoo invoices comply with German client validation requirements.
Original PR description
**PROBLEM** xrechnung pdf invoices are not compliant with some validators used german clients. **STEP TO REPRODUCE** 1. Create an invoice for a german customer. 2. Set the edi format on the customer as Xrechnung. 3. Download the invoice pdf, and verify it on https://www.portinvoice.com/ 4. Notice the pdf is not valid. To verify my fix works, you need to have the fontTools python package installed (for pdfa conversion). opw-6030481 Forward-Port-Of: odoo/odoo#259318
This update resolves an issue where Italian EDI bank account imports weren't automatically creating new bank accounts. The fix ensures that a bank account is created, assigned to the correct customer, and initially marked as untrusted, streamlining the accounting process. This improvement prevents manual account creation and reduces potential errors.
Original PR description
The Italian EDI import didn't create new bank account by itself. IBAN info was just logged in the chatter, leaving it up for the accountant to create the bank account record. The bank account should be created and assigned to the corresponding commercial partner and set to not trusted yet. Enterprise PR: odoo/enterprise#112794 Task [link](https://www.odoo.com/odoo/project.task/6046189) task-6046189 Forward-Port-Of: odoo/odoo#264857 Forward-Port-Of: odoo/odoo#254505
This update corrects a discrepancy in how purchase order move lines handle sub-locations. Previously, move lines defaulted to the main warehouse, preventing accurate forecasted quantities for receiving into specific sub-locations. Now, the system prioritizes the intended sub-location, ensuring accurate quantity tracking and forecasting.
Original PR description
### **Description of the issue/feature this PR addresses:** **Issue:** In Odoo 18/19, purchase move lines default to the WH's main stock location (`lot_stock_id`) as the `location_final_id`. However,…
### **Description of the issue/feature this PR addresses:** **Issue:** In Odoo 18/19, purchase move lines default to the WH's main stock location (`lot_stock_id`) as the `location_final_id`. However, when a user configures a sub-location on the Receipt Operation Type, the picking destination is correct, but the move lines are defaulted to the main warehouse. This mismatch causes the Forecasted Quantity to not increment for the intended sub-location **Solution:** Prioritize the `default_location_dest_id` before falling back to the default stock location opw-6032018 ### **Current behavior before PR:** When confirming a PO, the `location_final_id` on stock moves defaults to the `lot_stock_id`, regardless of the specific destination set on the Operation Type. This causes a mismatch in 1-step receiving flows where a sub-location (e.g., WH/Stock/Test) is intended, since the move lines revert to the root warehouse location (WH/Stock). Thus, the forecasted quantity for the specific sub-location doesn't increment as expected. ### **Desired behavior after PR is merged:** The `_get_final_location_record` method will now evaluate if the Operation Type's `default_location_dest_id` is a child of the warehouse's main stock. If it is, the sub-location is used as the `location_final_id` for the moves and move lines. This ensures that the forecasted quantity reflects the intended destination upon PO confirmation while still maintaining the fallback to the warehouse root for standard multi-step routes. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259233 Forward-Port-Of: odoo/odoo#254527