Tuesday, June 16, 2026
20 changes · saas-19.2
Enhancements to existing features
This update enhances the synchronization of financial transactions with Fiskaly for both retail and restaurant orders. It streamlines the process by sending complete transaction data only upon order validation, improving efficiency and accuracy. This change ensures smoother integration with Fiskaly's systems.
Original PR description
In this commit: ------------------ - Maintain separate Fiskaly transaction flows for retail (short tx) and restaurant (long tx) orders as discussed with the Fiskaly team. - `Initialize order…
In this commit: ------------------ - Maintain separate Fiskaly transaction flows for retail (short tx) and restaurant (long tx) orders as discussed with the Fiskaly team. - `Initialize order transactions` with an empty payload when the `first product` is added. - Start `receipt transactions` with an empty payload when the `first payment line` is added. - For retail flows, no intermediate order updates are sent to Fiskaly before finalization. - For restaurant flows, create additional transaction updates during kitchen synchronization. Ensure already synchronized products are not resent, and only newly added or updated quantities are included in the payload. - `Finalize order and receipt transactions` with complete order lines and payment details when we validate the order. task: 6208963 Reference: <img width="1863" height="1285" alt="de_tss_flow" src="https://github.com/user-attachments/assets/9140788e-7948-4a08-9f11-27197b22ca8b" /> Forward-Port-Of: odoo/enterprise#120218 Forward-Port-Of: odoo/enterprise#117526
This update enhances the payment confirmation screen in the Point of Sale (POS) system. Now, customers see a 'Processing...' indicator during payment finalization and a visual checkmark with the amount paid upon successful completion. This provides clearer feedback and a more polished user experience.
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#269428 Forward-Port-Of: odoo/odoo#267635
Resolved issues and error corrections
This update resolves an issue where the car simulation wasn't appearing for Belgian employees with a car order. The fix ensures the car information and simulation button are correctly displayed by addressing a race condition in the salary calculation process. This improves the user experience for employees using the salary configuration tool.
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 fixes an issue where the reconciliation dialog in the Enterprise accounting module only displayed posted journal items. By removing a default filter, the dialog now shows all matching items – both draft and posted – providing a more complete and accurate reconciliation view. This improves the user's ability to resolve discrepancies.
Original PR description
The reconcile badge counts draft and posted journal items, but the matching dialog forces a posted filter by default, this makes the dialog show fewer lines than count as it discards the draft ones. Remove the default posted search filter so the dialog displays all matching items. task-6234801 Forward-Port-Of: odoo/enterprise#118146
This update resolves an issue where stock relocation incorrectly swapped the order of reservations for deliveries. After moving stock internally, reservations were being reassigned in the wrong order, leading to incorrect quantities. This fix ensures that reservations are maintained in the correct priority after stock relocation, preventing delivery discrepancies.
Original PR description
Version: ---------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Enable `Storage Locations` from Inventory settings - Create a tracked storable product with on-hand 8…
Version: ---------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Enable `Storage Locations` from Inventory settings - Create a tracked storable product with on-hand 8 units in `Shelf 1` - Create Delivery 1 for 5 units and click `Mark as To Do` - Create Delivery 2 for 5 units and click `Mark as To Do` - Verify reservations: - Delivery 1 reserves 5 units - Delivery 2 reserves remaining 3 units - Relocate all 8 units from `Shelf 1` to `Shelf 2` using the `Relocate` action from `stock quant` - Reopen both deliveries Issue: ------ After relocating stock between internal locations, reservations are reassigned in the wrong order: - Delivery 2 becomes fully reserved with 5 units - Delivery 1 is reduced to 3 reserved units This incorrectly swaps the original reservation priority between deliveries. Cause: ------ The relocation wizard starts from: `stock.quant.relocate.action_relocate_quants()` which calls `move_quants()`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/wizard/stock_quant_relocate.py#L70 `move_quants()` validates an internal stock move through `_action_done()`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_quant.py#L1572 During validation, `_synchronize_quant()` moves the stock quantity from `Shelf 1` to `Shelf 2`. However, the already reserved delivery move lines still reference `Shelf 1`. This temporarily makes the source quant negative (`available_qty < 0`), triggering `_free_reservation()`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_move_line.py#L695-L700 Inside `_free_reservation()`, move lines are ordered using `current_picking_first`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_move_line.py#L816-L821 Since both deliveries share the same scheduled date, the fallback ordering uses `-cand.id`, causing Delivery 2 (higher id) to be processed before Delivery 1 (lower id). The reservation cleanup therefore happens in this order: - Remove Delivery 2 reservation (3 qty) - Remove Delivery 1 reservation (5 qty) The corresponding moves are then added to `move_to_reassign` in the same order: `[Delivery 2, Delivery 1]` https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_move_line.py#L849 Later, `move_to_reassign._action_assign()` processes the moves in recordset order: - Delivery 2 reserves 5 units first - Delivery 1 only gets the remaining 3 units As a result, reservation priority is unintentionally reversed after relocation. Fix: ---- Before calling `_action_assign()`, reverse `move_to_reassign` This ensures reassignment preserves the original reservation order: - Delivery 1 is reassigned first and recovers 5 units - Delivery 2 receives the remaining 3 units The reservation state therefore remains consistent before and after internal stock relocation. --- opw-6218256 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269973 Forward-Port-Of: odoo/odoo#265169
This update optimizes the process of validating purchase orders by preventing unnecessary calculations of location weights. By reordering checks, the system avoids computing weights when other conditions already rule out a location, leading to significantly faster validation times, especially with large numbers of locations. This improves overall system performance and responsiveness.
Original PR description
When checking if a stock.move.line can use a location as destination with the method `_check_can_be_used()`, we start by checking if the incoming products can be stored without exceeding the maximal…
When checking if a stock.move.line can use a location as destination with the method `_check_can_be_used()`, we start by checking if the incoming products can be stored without exceeding the maximal weight of the location. This needs to call the `_get_weight()` method to compute the forecasted weight for the location. This method relies on heavy computations and can become a bottleneck when we need to loop over a high number of locations. In some cases, we can rule out the location based on less expensive conditions that are verified after the weight one. We propose to invert the conditions check order to avoid computing the location weight when other conditions are not met. Steps to reproduce --------------- - Install stock and purchase modules; - Enable storage locations and categories in the settings; - Create a storage category: allow_new_product = same, max_weight=10.0 kg; - Create N locations using this category, parent_id=WH/stock; - Create a putaway rule to each location from WH/stock, for the new storage category and using a product A with a weight of 2 kg; - Create a stock.quant per location to store a product B, weight=2kg; - Create a purchase order with X lines for 1 unit of product A; - Validate the purchase order. The validation should take several seconds to execute as every locations will be rejected due to the storage category, but it will call _get_weight() first. Benchmark --------------- This improvement is very data specific and will be most useful when a lot of locations are using a storage category of type "empty" or "same". In addition, it also relies on the order in which we are treating the locations, if the acceptable locations are the first to be received in the method, it won't need to loop over all of them. The following benchmark was established in a production database in which every 6068 locations are using a category of type "same". | No stock.move.lines | Before PR | After PR | |---------------------|-----------|----------| | 40 | 168 s | 7.3 s | | 72 | 264 s | 12.33 s | When the only condition that can reject locations is the exceeding weight, this modification will slow down the process. However, the time loss in this case is smaller than the gain in the first case. The following benchmark was obtained by validating a purchase 1 line order with only fully filled locations. | No locations | Before PR | After PR | |--------------|-----------|----------| | 500 | 2.02s | 2.37 s | | 2000 | 7.85s | 9.76 s | | 10000 | 39.16 s | 48.86 s | opw-5949370 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270125 Forward-Port-Of: odoo/odoo#266872
This update fixes a bug where 401K matching contributions were incorrectly calculated for hourly employees with a fixed wage of zero. The change ensures that matching contributions are accurately determined based on the employee's actual earnings, providing correct retirement savings calculations. This improves payroll accuracy and compliance.
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#120483 Forward-Port-Of: odoo/enterprise#119370
This update fixes an issue where the salary distribution map wasn't being recalculated when bank accounts were archived or unarchived. This ensures accurate salary calculations are consistently applied, preventing potential discrepancies in payroll processing. The fix improves the reliability of our HR financial data.
Original PR description
When archiving or unarchiving bank accounts, salary distribution map is not recomputed. Task-6180142 Forward-Port-Of: odoo/odoo#262255
This update ensures that 'regenerate overtime' only affects the selected overtime ruleset, preventing unintended changes to other rules. A confirmation message is now displayed to alert users about resetting manual edits linked to the selected ruleset, improving data integrity and reducing potential errors.
Original PR description
When you click on "regenerate overtime", currently, it reset all overtimes of all overtime ruleset, it should only act on the selected one. Second, it should display a confirmation message: "This will reset all manual edit on overtime period linked to those rules. Do you confirm ?" Task-6095714 Forward-Port-Of: odoo/odoo#258103
This update significantly speeds up the process of checking if a field can be deleted within website forms. Previously, this check took several minutes, causing delays. Now, it completes in just milliseconds by focusing only on the fields that actually need to be validated, improving user experience and system performance.
Original PR description
Summary ======= `_check_if_used_in_website_form`, the ondelete hook on `ir.model.fields` that guards against deleting a field referenced by a website form, performs poorly on realistic databases. It…
Summary
=======
`_check_if_used_in_website_form`, the ondelete hook on
`ir.model.fields` that guards against deleting a field referenced by
a website form, performs poorly on realistic databases. It can take
multiple minutes to validate a single field deletion, blocking user
actions such as removing a Studio field.
This commit restricts the scan to columns that can actually contain
website form markup, bringing the hook from multi-minute to
sub-second without any loss of coverage.
The Problem
===========
Deleting any `ir.model.fields` record triggers this validation hook,
which must ensure the field is not referenced inside any website
form. The implementation iterates every stored HTML column returned
by `website._get_html_fields()` and runs one case-insensitive
`ILIKE '%data-model_name="<model>"%'` search per column against
`<model>.<html_field>`, then parses each match with `lxml` and
validates it with XPath.
Two root issues cause the multi-minute cost:
- **Unbounded scan surface**: all stored HTML columns are scanned
(~95 on realistic databases), even though the vast majority of them
declare `sanitize=True` and `sanitize_form=True` (the defaults).
When both flags are True, `<form>` tags are stripped on write and
the column can never physically contain website form markup.
- **Per-column `ILIKE` cost**: `ILIKE` on large TEXT/JSONB columns
performs a sequential scan. A single large HTML column is enough
to make the hook run for several minutes on its own.
Improvements
============
- Scan only columns that can actually contain forms:
- `ir.ui.view.arch_db` , primary target; all website forms are
stored there.
- HTML fields whose sanitization either is disabled
(`sanitize=False`, e.g. `blog.post.content`,
`website.custom_code_head`) or explicitly allows forms
(`sanitize_form=False`, e.g.
`product.template.website_description`, `hr.job.description`,
`event.event.description`). Any other HTML field strips `<form>`
on write and will never contain a form.
- Batch searches: group the deleted fields by model once and emit a
single `OR`-domain search per candidate column, instead of one
search per (field, column) pair.
- Parse each returned record with `lxml` and validate with XPath
directly. The `ILIKE` domain already filters out non-matching rows
DB-side.
Benchmarks
==========
Profiled on a database containing ~95 stored HTML columns and ~5.2k
views. The hook was invoked read-only via
`field._check_if_used_in_website_form()` on a custom field.
| Metric | Before | After |
| :----------------------------- | ---------: | ---------: |
| Hook wall time | ~444 s | ~173 ms |
| HTML columns scanned | 95 | 5 |
| SQL queries issued | 96 | 6 |
Key results:
- Hook wall time reduced from multi-minute to sub-second
(~2,570× faster on the profiled database).
- Scan surface reduced from ~95 columns to a handful (1 +
the form-capable HTML fields installed on the database, typically
under 10).
opw-6086536
Forward-Port-Of: odoo/odoo#268666
Forward-Port-Of: odoo/odoo#259846This update ensures that financial data associated with an IoT box is properly handled before it's removed from the system. Previously, deleting an IoT box could lead to data loss related to point-of-sale transactions. This change prevents this issue, maintaining data integrity for POS operations.
Original PR description
Before unlinking an iot.box from the database, we must ensure that its fiscal data module is not currently used in any pos.config. task-id: 5144489 Forward-Port-Of: odoo/enterprise#110099
This update corrects a potential error in the holiday payroll calculation. Previously, the base amount could exceed an employee's wage when calculating holiday pay. This change ensures that the base amount is always capped at the employee's regular wage, aligning with payroll regulations and improving accuracy.
Original PR description
The base amount should never be more than the employee's wage.
This update corrects a bug in the stock account closing entry that incorrectly calculated inventory values when multiple companies were involved. The fix ensures that the closing entry accurately reflects the inventory value for each company, resolving discrepancies in initial balances and stock valuations. This ensures accurate accounting reporting across multiple company setups.
Original PR description
**Steps to reproduce on a new db:** (bug also reproducable on runbot but the impact is less easy to compute because of influence of other existing companies) - create a new company as company 2 and…
**Steps to reproduce on a new db:** (bug also reproducable on runbot but the impact is less easy to compute because of influence of other existing companies) - create a new company as company 2 and use the existing default company as company 1. - create a warehouse for both company - for both comp, in settings for the 'fiscal localization' set Package : Generic Chart of account, if not already set (to have account journals). - for both comp, in settings for inventory valuation set 'periodic' and for periodic valuation set 'daily' From company 1 : - create a storable product with standard price method and set a cost of 30 - set an onhand quantity of 1 if you navigate to 'inventory valuation' you'll see that : - initial balance is 0 - ending stock is 30 - the variation lines have a balance of 30 - all of this is expected From company 2 : - change the cost of the product to 10 - set an onhand quantity of 1 if you navigate to 'inventory valuation' you'll see that : - initial balance is 0 - ending stock is 10 - the variation lines have a balance of 10 - all of this is expected From any company : - navigate to 'scheduled actions' and select the action 'Stock Account: Inventory Valuation Closing' - click on 'Run Manually' - navigate to 'inventory valuation' **Current behavior:** with company 1 selected : - the initial balance is now 30 - ending stock still 30 - no variation lines - the initial balance was correctly increased by the closing entry with company 2 selected: - the initial balance is now 40 - the ending stock is still 10 - the variation lines credit 30 in stock valuation In company 2 the closing entry debitted 40 in stock valuation instead of 10 which increased the initial balance to 40 instead of 10 If you open the journal items you'll find the closing amls have a balance of 40 instead of 10 **Cause of the issue:** The _cron_post_stock_valuation() method calls action_close_stock_valuation() on both companies https://github.com/odoo/odoo/blob/bfa39854e56da4bf23295d62f63d66973ad0d78e/addons/stock_account/models/res_company.py#L143-L144 This methods calls _action_close_stock_valuation with a context modified with only self.env.company.ids in 'allowed_company_ids' https://github.com/odoo/odoo/blob/bfa39854e56da4bf23295d62f63d66973ad0d78e/addons/stock_account/models/res_company.py#L56 This is needed because inside stock_value() we use the total value of the product https://github.com/odoo/odoo/blob/bfa39854e56da4bf23295d62f63d66973ad0d78e/addons/stock_account/models/res_company.py#L92 which will be the sum of the values of the product for each company inside allowed_company_id https://github.com/odoo/odoo/blob/bfa39854e56da4bf23295d62f63d66973ad0d78e/addons/stock_account/models/product.py#L274 So in case action_close_stock_valuation() was called from the 'generate entry' button from the inventory valuation view we need only the main company selected to be in the 'allowed_company_ids' so that the inventory value is computed based only on this company (as is the accounting value). The problem is that this does not work when calling the method from _cron_post_stock_valuation because then there is no 'allowed_company_ids' in the context (because it was called from _process_job() with a new env). so self.env.company will be the company of the user which will be company 1. https://github.com/odoo/odoo/blob/bfa39854e56da4bf23295d62f63d66973ad0d78e/odoo/orm/environments.py#L243 Therefore when _action_close_stock_valuation will be called on company 2, in the context, allowed_company_ids will be company 1. Then, when computing 'products', with_company() will add self (company 2) to the context. https://github.com/odoo/odoo/blob/616e82d7b3a53b1facf481e783baed3e99393d3c/addons/stock_account/models/res_company.py#L151-L152 So stock_value will return the sum of the total_value of each product for company 1 and company 2 which is 40 (instead of 10 for just company 2) https://github.com/odoo/odoo/blob/616e82d7b3a53b1facf481e783baed3e99393d3c/addons/stock_account/models/res_company.py#L242 We then create the closing accounting entry to match the accounting value with the stock value, which explains why the new initial accounting balance of company 2 is 40. **fix:** We set the context using self instead of self.env.companies This makes more sense as both in the cron use case and the generate entry use case the stock value we want is the one of the company in self. - In cron use case, it's obvious as the method is called in a for loop on each company - In the generate entry use case, self will also be the main company, because it's called, in actionGenerateEntry, on this.companyId https://github.com/odoo/odoo/blob/616e82d7b3a53b1facf481e783baed3e99393d3c/addons/stock_account/static/src/stock_valuation/controller.js#L75 which is computed based on the get_report_values https://github.com/odoo/odoo/blob/616e82d7b3a53b1facf481e783baed3e99393d3c/addons/stock_account/static/src/stock_valuation/controller.js#L21 https://github.com/odoo/odoo/blob/616e82d7b3a53b1facf481e783baed3e99393d3c/addons/stock_account/static/src/stock_valuation/controller.js#L28-L30 Which returns the main company https://github.com/odoo/odoo/blob/616e82d7b3a53b1facf481e783baed3e99393d3c/addons/stock_account/report/stock_valuation_report.py#L29 Most importantly, this is also aligned with how the accounting values are computed. https://github.com/odoo/odoo/blob/616e82d7b3a53b1facf481e783baed3e99393d3c/addons/stock_account/models/res_company.py#L103-L105 opw-6237402 Forward-Port-Of: odoo/odoo#269152 Forward-Port-Of: odoo/odoo#266932
This update ensures accurate product pricing when selling large quantities of items like boxes of screws. Previously, the system rounded base unit counts, leading to incorrect reference prices. Now, the system preserves high-precision values, allowing for correct calculations when selling in bulk packs.
Original PR description
**Description of the issue/feature this PR addresses:** The `Product Reference Price` feature in `website_sale` cannot correctly handle products sold in large packs when the reference quantity…
**Description of the issue/feature this PR addresses:** The `Product Reference Price` feature in `website_sale` cannot correctly handle products sold in large packs when the reference quantity requires a very small `base_unit_count`. For example, a product sold as a `box of 10000` screws should be able to use `0.0001` as its `Base Unit Count`, so the reference price can be computed against the box quantity correctly. **Current behavior before PR:** `base_unit_count` uses the default float precision, so values with more than two decimal places are rounded in the product form. When trying to set `Base Unit Count` to `0.0001`, the value is rounded to `0.00` / `0.01`, which makes the Product Reference Price computation incorrect. Steps to reproduce: 1. Go to Settings > Website and enable Product Reference Price. 2. Create or open a product named `Screws`. 3. Set Sales Price to `$ 1.00`. 4. On the product form, set Base Unit Count to `0.0001`. 5. In Custom Unit of Measure, type `box of 10000` and press Create. <img width="1374" height="740" alt="1" src="https://github.com/user-attachments/assets/2d4f7863-b2cd-4c7c-87e1-11526dc50551" /> **Desired behavior after PR is merged:** `base_unit_count` keeps high-precision values such as `0.0001`. This allows `Product Reference Price` to correctly support large-pack scenarios, such as selling screws in a `box of 10000`, by storing `base_unit_count` with unlimited numeric precision. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262579
The Budget Report was previously timing out on large customer databases due to how it processed data. This update significantly improves performance, allowing users to run the report without delays, even with extensive data. This enhancement ensures the Budget Report remains a reliable tool for financial analysis.
Original PR description
**Description** Opening the Budget Report from any budget record times out on databases with significant data volume. The request to `budget.report/formatted_read_grouping_sets` consistently times…
**Description**
Opening the Budget Report from any budget record times out on databases
with significant data volume. The request to
`budget.report/formatted_read_grouping_sets` consistently times out,
making the Budget Report completely unusable.
**Root cause:**
`budget.report` is an SQL view that consists of 5 UNION ALL branches.
When the list view loads, the ORM translates the `budget_analytic_id`
domain into a WHERE clause on the outer query wrapping the full UNION
ALL subquery. PostgreSQL cannot push this filter through a UNION ALL as
it's a hard optimization barrier. It must fully materialize the subquery
regardless of which budget is being viewed.
**Fix:**
Override _search on budget.report to extract budget_analytic_id and
budget_line_id conditions from the incoming domain using the Domain API.
budget_line_id is rewritten as Domain('id', op, value) so _to_sql()
correctly emits bl.id in the raw SQL. The resulting domain is injected
in context under budget_line_domain and read in _get_bl_query,
_get_aal_query (base module), and _get_pol_query (purchase module) to
filter budget_line rows inside each branch's LEFT JOIN ON clause.
This also removes the budget_report_budget_line_ids context key from
budget_line._compute_all, unifying both filters under one mechanism.
---
On customer DB (568k `account_analytic_line`, 27k `budget_line`,
116k confirmed `purchase_order_line`, 114k posted vendor bill lines
with purchase link):
| Budget | Before | After |
|---|---|---|
| 8 lines, 730d span | timeout | 2.27s |
| 14 lines | timeout | 2.39s |
| 14 lines, 1095d span | timeout | 1.63s |
- Before: https://explain.dalibo.com/plan/ehed5eb8de251426
- After: https://explain.dalibo.com/plan/db8aef35cag9hg6f
opw-6098047
Forward-Port-Of: odoo/enterprise#119728
Forward-Port-Of: odoo/enterprise#114692This update resolves an issue where automatic payment terminal integration blocked users from splitting bills. Now, users can manually set the payment amount or use the original 'Send' button, providing greater flexibility for handling various payment scenarios. This change enhances the user experience for point-of-sale transactions.
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
This update resolves an issue where the barcode inventory count feature would fail when using archived units of measure. The fix ensures that archived UOMs are correctly included in the inventory count cache, allowing users to accurately count stock even when units have been archived. This prevents errors during physical inventory processes.
Original PR description
### Steps to reproduce: - In the settings enable: "Units of Measure & Packagings", "Storage Locations" - Create a product in units and register 1 unit in stock - Inventory > Operations > Adjustments…
### Steps to reproduce: - In the settings enable: "Units of Measure & Packagings", "Storage Locations" - Create a product in units and register 1 unit in stock - Inventory > Operations > Adjustments > Physical Inventory - Select your line and request a count > Set Current Value - Inventory > Configurations > units of measures > UOM categories - Select unit and archive it - Go to the barcode app > Click Count inventory ### > Owl error: Uncaught promise ### Cause of the issue: Since the uom used on the quant is archived, it is not found by the search used to fill the barcodeCache: https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/components/main.js#L209-L213 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/models/stock_quant.py#L104-L106 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/components/main.js#L229 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/models/barcode_model.js#L37-L39 However, if the uom is not present in the barcode cache the `BarcodeQautnModel` will fail to createLinesState whihc raises a missing error: https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/models/barcode_quant_model.js#L712 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/lazy_barcode_cache.js#L107-L110 opw-6250090 Forward-Port-Of: odoo/enterprise#120065 Forward-Port-Of: odoo/enterprise#118813
This update optimizes how Odoo retrieves related mailings for testing, addressing a performance bottleneck that occurred when processing large campaigns. The change prevents crashes and significantly improves the speed of mass mailing operations, particularly for campaigns with many mailings. This ensures smoother and more reliable email sending.
Original PR description
**Description of the issue/feature this PR addresses:** The method _get_ab_testing_siblings_mailings currently scans all mailings in a campaign to apply a simple filter, which becomes expensive on databases with many large mailings. **Steps to reproduce bug:** 1) Run this script to get [enough sufficiently large mailings](https://gist.github.com/brcut-odoo/bb0d6d334bfe110afe16021d17d1b443) 2) Open one of the mailings and recieve a crash from the _get_ab_testing_siblings_mailings **Current behavior before PR** https://drive.google.com/file/d/19xftvzsGSQ9DxB67LNiLkKApzsD192ax/view?usp=drive_link **Current behavior after PR** https://drive.google.com/file/d/1apTJ0rWTKaATYa67ZmmN-7bKhrw4KuTx/view?usp=drive_link opw-6245908 Forward-Port-Of: odoo/odoo#268283
This update corrects a bug in Odoo's payroll calculations for the United Arab Emirates (AE) and Saudi Arabia (SA) localizations. The fix ensures accurate net cost calculations by standardizing how salary rules are processed, preventing negative value aggregation that was previously causing incorrect results.
Original PR description
Steps: - Add a new salary category with the parent_id of company contribution (COMP) in AE - Create a dummy salary rule of that category - Compute a payslip and see the net cost unchanged Or - Create and compute a payslip in SA - Company contributions will be subtracted from each other Issue: - In AE localization, the issue with the rule was dropping salary rules that have a parent of company contribution category - In SA localization, the issue with the NETCOST was the aggregation of individual rules could include negative values which is not the intended flow. Solution: A standardized approach was adopted in both localizations in order to match the calculation of the NETCOST across. This approach will account for the categories with company contribution parent as well as the positive values for the individual salary rules.
This update resolves a problem where invoice processing for French VAT (pdp) compliance was failing due to incorrect data retrieval. The fix ensures that invoice data is pulled from the correct commercial partner, guaranteeing accurate identification of PEPPOL identifiers and successful invoice sending. This improves the reliability of our French VAT processing.
Original PR description
…cial partner **STEP TO REPRODUCE** 1. Install l10n_fr_pdp. 2. On the demo FR company contact, create a new contact of type invoice address. 3. Create an invoice with this new contact, and try send the invoice. 4. The pdp invoice constraints checking for pdp identifiers fails. **CAUSE** We use the partner to retrieve the peppol_eas and peppol_endpoint field values, but for subcontact, those field are empty. We should use the commercial_partner_id which correspond to the company we try to invoice instead. opw-6235830 Forward-Port-Of: odoo/odoo#270014