Tuesday, May 12, 2026
28 changes · saas-19.2
Enhancements to existing features
This update streamlines the process of canceling old invoices in Mexico's EDI system. When a new invoice replaces an older one, the system now automatically cancels the original invoice, eliminating a manual step for users. This improves efficiency and reduces potential errors related to invoice management.
Original PR description
Triggers the EDI document cancellation method for the substituted invoice when the substitute document is signed, removing the requirement for the user to go back and click cancel again as well as bypassing calling a wizard with no options for the user to select from. task-5927581 Forward-Port-Of: odoo/enterprise#107541
Resolved issues and error corrections
A recent update removed a key piece of information from the onboarding plan wizard, causing it to display incorrectly in newer versions of Odoo. This fix restores the expected behavior, ensuring that plan badges are shown correctly when accessing onboarding plans through the chatter. This resolves a visual discrepancy impacting user experience.
Original PR description
Steps to reproduce: 1- Install Employees app 2- Open the app and select any employee 3- In the chatter, click the onboarding plan link Issue: Starting from version 18.4 and onwards, clicking the link opens the 'Launch Plan' wizard without the Offboarding/Onboarding plans Expected behavior: The wizard should contain the plan Badges just like in previous versions or when clicking the 'Activity' button in the chatter Why this happens: One of the changes in the commit ef34950 was removing the following line: `context.params = state` The `state` included the `active_model` value which was passed in the url. As a result, `res_model` attribute in the model 'mail_activity_schedule' is `false`. The `_compute_plan_available_ids` will then return an empty list. So the consequent call which gets the available plans to display as a Badge will not be made. opw-6074918 Forward-Port-Of: odoo/odoo#258349
This update corrects an issue during the tax migration process by simplifying the way negative signs are handled in W2 reporting for Australian businesses. Previously, a complex expression caused errors during upgrades. This change streamlines the process and ensures accurate tax calculations.
Original PR description
We do not need this extra aggregate expression. The purpose of this aggregate expression is only to invert the sign of the computation returned by the expression account_tax_report_payg_w2_tag.…
We do not need this extra aggregate expression. The purpose of this aggregate expression is only to invert the sign of the computation returned by the expression account_tax_report_payg_w2_tag. Instead of doing the sign inversion through a separate aggregate expression, we can directly include the negative (-) sign in account_tax_report_payg_w2_tag itself, as already done in the new report expressions. https://github.com/odoo/odoo/blob/30b4edace6b0859cb1b1ba4f7f2ea80ba5398e3d/addons/l10n_au/data/bas_a.xml#L386 https://github.com/odoo/odoo/commit/2c9ab8e77db7aa127a259f7f3e06ecfed94252ab Why is this fix needed? This aggregate expression creates issues during the tax_to_invert upgrade process. Since the sign conversion is handled through a separate expression, the upgrade query is unable to correctly identify the actual expression sign, which leads to incorrect computations during migration. Related PR: https://github.com/odoo/upgrade/pull/10162 - OPW: 6097598 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#263469
This update fixes a usability issue where calls in inactive channels weren't easily visible in the sidebar. Now, updating the channel's last interest date when a call starts ensures it remains prominent. This improves the user experience by making call initiation more noticeable and reducing confusion.
Original PR description
Starting a call in an inactive channel could leave it hidden from the sidebar when the channel had no recent messages, which was confusing for users. To make call initiation more visible, update the channel's last interest date when the first participant joins the call, similar to call notification messages. Subsequent participants joining the same call do not update it again. task-6185134 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an error that prevented users from generating Balance Sheet comparisons with specific date ranges. The fix ensures that date types are correctly handled, allowing the comparison feature to function as intended. This improves the reliability of balance sheet reporting.
Original PR description
Step to reproduce - Install the accountant module. - create a fiscal year (for 01/01/26 to 30/06/26) from setting and enable it - Navigate to Accounting > Report > Balance Sheet - Click the…
Step to reproduce
- Install the accountant module.
- create a fiscal year (for 01/01/26 to 30/06/26) from setting and enable it
- Navigate to Accounting > Report > Balance Sheet
- Click the `Comparison` smart button and set `Previous Period` to `2 periods`.
Observation:
- we face a traceback
``` File "/home/odoo/odoo/codebase/enterprise/saas-19.2/account_reports/models/account_report.py", line 5739, in _get_annotations
period_date_from = self._adjust_date_for_joined_comparison(options, period_date_from)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/codebase/enterprise/saas-19.2/account_reports/models/account_report.py", line 5695, in _adjust_date_for_joined_comparison
return min(period_date_from, comparison_date_from)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '<' not supported between instances of 'datetime.date' and 'str'
```
Cause:
- `_get_period_dates` return string in case we have date which falls in
`custom_range_match`, when `get_report_information` is called, while
`period_date_from` is of type date
- hence there is mismatch between types
Fix:
- `_get_period_dates` is supposed to return date object always, hence fixed the
return type in case we have match for custom range
opw-6185629This update fixes an issue where changing the delivery date for Hungarian invoices incorrectly recalculated journal entries, leading to financial discrepancies. The fix ensures that exchange rates are accurately applied when the delivery date is modified, resolving potential imbalances in tax and base amounts.
Original PR description
### Issue: When changing the delivery date (used as the Hungarian exchange rate date), some journal lines could be recomputed incorrectly, leading to unbalanced entries ### Cause:…
### Issue: When changing the delivery date (used as the Hungarian exchange rate date), some journal lines could be recomputed incorrectly, leading to unbalanced entries ### Cause: `expected_currency_rate` was recomputed when `delivery_date` changed, but the new value was never automatically applied In addition, after https://github.com/odoo/odoo/pull/225407, `_sync_tax_lines` partially updated the lines: https://github.com/odoo/odoo/blob/f5501e5c8dcf60444077912db4c87e7a3f2654a6/addons/account/models/account_move.py#L3029-L3031 https://github.com/odoo/odoo/blob/f5501e5c8dcf60444077912db4c87e7a3f2654a6/addons/account/models/account_move.py#L1633-L1637 These methods reapply the previous tax rate, causing base and tax lines to be updated inconsistently As a result, when the base amount increases, the tax amount decreases, and vice versa ### Steps to reproduce: - Install `l10n_hu_edi` and `accountant` with demo data, then switch to the `HU company` - Go to Currencies → USD and add two rates: April 5: HUF per Unit = 100 April 6: HUF per Unit = 150 - Create an Invoice: (Any customer, Currency: USD, Line: Price = 1000, Tax = 27%) - Open the Journal Items and duplicate the browser tab for comparison - In the duplicated tab, change the Delivery Date to April 5 and save - Change the Delivery Date back to today and compare both tabs ### Before the fix: The values differ between both tabs because the tax lines keeps the old exchange rate opw-5801126 Forward-Port-Of: odoo/odoo#263694 Forward-Port-Of: odoo/odoo#258310
This update fixes an issue where users could still edit protected company folders within the document management system. The change ensures that protected folders, specifically the company root, display as read-only in the details panel, preventing accidental modifications. This maintains data integrity and security.
Original PR description
In odoo/enterprise#106192, we have modified the function userPermissionViewOnly that was preventing the user from editing document he cannot: we have removed the condition preventing user to edit…
In odoo/enterprise#106192, we have modified the function userPermissionViewOnly that was preventing the user from editing document he cannot: we have removed the condition preventing user to edit protected document (mainly folder at the company root). That was an error as even if the user has "edit" access (which is ensured in that method), the document can still be protected and the form to edit it should be in readonly then. We ensure here that the form in the details panel is in readonly in that case. How to reproduce: - log as demo and go to Document - Click on Inbox folder - Open details panel - Change for example the contact of the document You get an error while you shouldn't be able to edit it (as the folder is protected). Technical note: we re-add the condition in the method userPermissionViewOnly: (!this.documentService.userIsDocumentManager && this.record.data?.user_folder_id === "COMPANY") that we slightly modify to limit the protected document to folder only: (!this.documentService.userIsDocumentManager && this.record.data?.user_folder_id === "COMPANY" && this.record.data?.type === "folder") Task-5881531 Forward-Port-Of: odoo/enterprise#116709
This update resolves an issue where newly created analytic distribution records would disappear. The fix ensures the widget's data is properly synchronized with the database before saving, preventing data loss when users interact with the distribution models. This improves data reliability and prevents disruptions to accounting processes.
Original PR description
Steps to reproduce 1. Go to Accounting → Configuration → Analytic Distribution Models 2. Create a new model, name it, and in the distribution column pick an analytic account 3. Click outside the row…
Steps to reproduce 1. Go to Accounting → Configuration → Analytic Distribution Models 2. Create a new model, name it, and in the distribution column pick an analytic account 3. Click outside the row and reload the page Issue The newly created record vanishes because `web_save` received `analytic_distribution: false`. The single click that closes the popover also triggers the editable list's `leaveEditMode`, which calls `record.save()`. That save runs before the widget has flushed the user's pick into `record.data`, so the write goes out with stale/empty data. This became reliably reproducible after [37d78a47bb20], which moved the list renderer's outside-click listener from `document` (bubble) to `window` (capture). Because the list is mounted before the widget, its capture-phase listener now fires first: `leaveEditMode` → `record.save()` is already in flight by the time the widget's own window click handler runs, so the widget's commit loses the race. Solution `record.save()` awaits `_askChanges()` before writing: https://github.com/odoo/odoo/blob/cdf8aaec82ee387c8f29b8327efbc95fd17e2cb8/addons/web/static/src/model/relational_model/record.js#L268-L271 `_askChanges()` triggers `NEED_LOCAL_CHANGES` on the model bus and awaits any proms handlers push onto it: https://github.com/odoo/odoo/blob/cdf8aaec82ee387c8f29b8327efbc95fd17e2cb8/addons/web/static/src/model/relational_model/relational_model.js#L249-L253 This is the framework's standard hook for widgets that hold uncommitted local state; `ace_field` and `domain_field` already use it. Subscribe the analytic distribution widget to the same event and, when the dropdown is open, push a `commitChanges()` prom that awaits the existing `save()`. Because `record.save()` awaits these proms before running `_save`, the widget's pending distribution is guaranteed to be on `record.data` by the time the write payload is built, regardless of click-listener ordering. opw-6106309 Forward-Port-Of: odoo/odoo#260421
This update resolves a bug that caused Purchase Orders to fail when quantities were below the vendor's minimum order quantity. The fix ensures a supplier is always identified, preventing crashes and allowing for accurate price calculations, even with small order sizes. This improves the reliability of procurement processes.
Original PR description
FIX] purchase_stock: handle missing seller during PO line update (min_qty) **Steps to Reproduce:** - Install Sale, Inventory, Manufacturing, and Purchase. - Enable MTO, Units of Measure, and Routes.…
FIX] purchase_stock: handle missing seller during PO line update (min_qty)
**Steps to Reproduce:**
- Install Sale, Inventory, Manufacturing, and Purchase.
- Enable MTO, Units of Measure, and Routes.
- Create a product:
Set a vendor price with min_qty = 1.0.
Enable MTO route.
Add a BoM with a component product.
Set quantity to 0.1 (less than vendor min_qty).
- Create a Sale Order with the same product added twice.
- Confirm the Sale Order.
**Issue:**
During procurement:
- First procurement correctly fetches the supplier.
- On PO line update (_update_purchase_order_line), seller is recomputed.
Due to min_qty filtering, no seller is returned when quantity is low.
This results in: Missing seller, Missing product_uom, Invalid price
computation, And finally causes a crash when confirming the Purchase Order,
in _get_stock_move_price_unit: ZeroDivisionErroR
Root Cause:
- _select_seller filters suppliers using min_qty.
During merge/update flow, recomputed quantity may not satisfy min_qty.
Existing valid supplier (from initial procurement) is ignored.
No fallback handling in _update_purchase_order_line.
**Solution:**
- Add fallback logic when _select_seller returns no result: Use
_prepare_sellers() to fetch a valid supplier ignoring min_qty.
- Ensure a supplier is always available for: UoM resolution, Price computation
Prevents crash and ensures consistent PO line updates.
**Result:**
- No traceback when quantity < vendor min_qty
Supplier, UoM, and price are properly set
**OPW-6106487**
Forward-Port-Of: odoo/odoo#259894This update resolves an error in the LU VAT reports generated for the FAIA report, ensuring the correct 'TVA' TaxType is used. This was triggered by customer feedback and confirmed by XSD files, preventing report generation failures. This ensures compliance with Luxembourg VAT regulations.
Original PR description
This is one of several commits fixing the FAIA xml export. The customer in ticket [opw-5427296](https://www.odoo.com/odoo/unassigned-tasks/5427296) received several errors which mention that the `TaxType` element should be 'TVA'. This is corroborated by one of these elements in the XSD files for the FAIA report. The XSD files can be found at the link below. https://pfi.public.lu/dam-assets/backup/FAIA/FAIA/XSD_Files.zip opw-6118272 [link](https://www.odoo.com/odoo/project.task/6118272) *For future techs or functional support agents: updating `l10n_lu_reports` may not automatically apply the fix. You may need to go to the relevant Views model and select ⚙️ > Compare/Reset, then Hard Reset.* Forward-Port-Of: odoo/enterprise#116344 Forward-Port-Of: odoo/enterprise#113720
This update fixes an issue where users were incorrectly directed to a standard form view when opening documents linked through Studio. Now, users can directly access the document's Kanban view, allowing them to preview and navigate the document content as intended. This enhances the user experience for document management.
Original PR description
Problem: When opening a linked `documents.document` record from a Many2One field added via Studio, the user is redirected to the standard form view. This is problematic because the form view does not allow the user to preview the actual document or navigate into it if the record is a folder. Solution: override `get_formview_action` to open the Kanban/List/Activity views. task-6068437 Forward-Port-Of: odoo/enterprise#116675 Forward-Port-Of: odoo/enterprise#113149
This update fixes an issue where the correct fiscal position (Domestic) wasn't being applied to sales orders in certain EU scenarios. The change ensures that VAT prefixes are properly considered, leading to accurate fiscal position detection and improved sales order processing, particularly for intra-EU B2B transactions. This resolves a discrepancy in how VAT was being handled.
Original PR description
With l10n_nl: - Set the fiscal positions in this order: 1. Domestic 2. EU Intra B2B - Create a contact with: - German address - Dutch delivery address - Dutch VAT - Create a second contact with: - German address - Dutch delivery address - No VAT - Create a Sales Order for each contact: - For the first contact, the applied fiscal position is EU Intra B2B - For the second contact, the applied fiscal position is Domestic The detected fiscal position should be Domestic in both cases In _get_fiscal_position vat_exclusion is computed using the VAT prefix of the partner and our company. But if the prefix of the VAT does not match the country of the partner, it's delivery address will still be overriden. opw-5892138 Forward-Port-Of: odoo/odoo#258899
This update fixes an issue where purchase order lines weren't correctly displaying the associated analytic distribution when a project was assigned. The fix ensures that the product's original analytic distribution, along with the project's, is consistently shown on new order lines. This improves accuracy in tracking costs by project.
Original PR description
__ ## Short functional explanation of the error When creating a Purchase Order. We add a line containing a product that has an analytic distribution. After setting a project on this PO, when we add…
__ ## Short functional explanation of the error When creating a Purchase Order. We add a line containing a product that has an analytic distribution. After setting a project on this PO, when we add another line containing the same product, the analytic distribution of the product isn't added anymore, only leaving it with the analytic distribution of the project. ## Reproduction Steps 1. Go to settings and enable Analytic Accounting. 2. Go to Accounting > Configuration > Analytic Distribution model. Create a model with a product (prd) you remember, and add an analytic distribution (ad). 3. Go to Project. On a given project (p), select the Hamburger menu and click Settings. Then, in the Settings tab, under Analytic, make sure the Project field is filled. 4. Create a new Purchase Order. Select a vendor and add a line with the product (prd). On the top right of the Form, click on the view button and select Analytic Distribution to show it on the form. There, we should see the product (prd) with its corresponding Analytic Distribution (ad) on the form. 5. Click on the Other Information tab and select the project (p). Click on the Product tab. There, under Analytic Distribution field, you should see (ad) and the Analytic Distribution of the project (p). 6. Click on save and add another line with the exact same product. ### Expected behavior Under Analytic Distribution, we should see (ad) and the Analytic Distribution of the project (p), as for the first order line ### Unexpected behavior Under Analytic Distribution, we only see the Analytic Distribution of the project (p). ## Origin of the issue When we add another line, we trigger the compute method of the Analytic Distribution. However, due to this piece of code: https://github.com/odoo/odoo/blob/eed303b9926062eb71be6cf8dc95165efc413ed8/addons/project_purchase/models/purchase_order_line.py#L14 when we create a new order line, we never compute its analytic distribution: `self` will contain only `project_lines`, and `empty_project_lines` is empty as well. Therefore, we call the super method with nothing, so when we get in the super method: https://github.com/odoo/odoo/blob/eed303b9926062eb71be6cf8dc95165efc413ed8/addons/purchase/models/purchase_order_line.py#L249-L259 we never compute the analytic distribution of the newly created line. This piece of code was added in this commit: https://github.com/odoo/odoo/commit/c1ea8446259bd3338c004e88d48ad77ded7ef2ae to fix the issue that when a user enters manually an analytic distribution, this entry will be lost when triggering the compute of the analytic distribution. However, due to the agency of the code, we cannot prevent losing *both* manually added analytic distributions and product analytic distribution. After consulting the product owner, we concluded that there was no perfect solution in this case, but we'd rather keep the product analytic distribution, as it is much harder to add it again after its removal. Therefore, this commit reverts the previously mentioned commit, while keeping the refactor it introduced. __ opw-6063418 Forward-Port-Of: odoo/odoo#257558
This update optimizes the installation of the stock_account module, significantly reducing memory usage during database initialization. By disabling prefetching, the module now uses 55% less memory, preventing potential database overload. While installation time increased slightly (10%), this is an acceptable tradeoff for improved stability and performance.
Original PR description
## The Problem During the initialization of `stock_account`, the logic creating `product.value` instances triggered cache misses on `product.product`, accessing fields (`company_id` and…
## The Problem During the initialization of `stock_account`, the logic creating `product.value` instances triggered cache misses on `product.product`, accessing fields (`company_id` and `standard_price`) inside `_create_product_value`, and field `uom_id` inside `_run_fifo_get_stack`. Due to prefetching, this loaded all product data into memory, causing significant memory usage on large databases. ## The Solution Disabled prefetching in the full flow. Didn't go with fetching only the needed fields instead of disabling for two main reasons: - Field `standard_price` accessed in the loop is company dependent, so it needs to be fetched inside, which would be a bit verbose. - Fetching `company_id` outside the loop, `standard_price` inside the loop, and `uom_id` which is accessed down the stack in the `.create` call on `product.value` won't be an explicit/robust solution for the long term. --- ## Benchmarks *Tested on a SaaS database with 500k products:* | | Before | After | Note | | :--- | :--- | :--- | :--- | | **Memory** | 3.6GB | 1.6GB | **-55%** (fits in memory limit) | | **Time** | 10m | 11m | **+10%** (acceptable tradeoff) | **OPW-6173153** Forward-Port-Of: odoo/odoo#262702
This change fixes an issue where products were incorrectly displayed on the website when viewed through Company B. The update ensures product searches respect the user's current company setting, preventing sales order errors. This improves data accuracy and prevents incorrect product visibility.
Original PR description
# Setup Have 2 companies : A & B # How to reproduce - Set your website's company to Company B - Create product X : - Company : Company A - Published - Name : xyz - Go to Users > Any User > Acces…
# Setup
Have 2 companies : A & B
# How to reproduce
- Set your website's company to Company B
- Create product X :
- Company : Company A
- Published
- Name : xyz
- Go to Users > Any User > Acces Rights > Allowed Companies => leave only Company A
- Connect as that user on the website
- Go to the Shop tab and search xyz
# The problem
The product X is displayed, even though we currently use the company B's website and the product is limited to company A.
This causes problem later when Sales Order are created using that product.
If you set the Allowed Companies of the user to both Company A and Company B, then the product is correctly hidden
# Why
When you search something in the search bar, the server does a `_search_with_fuzzy()` that ends up calling a simple `model.search()`.
In our case, this search should not return product X because there is an `ir.rule` that hides product not in the current company :
https://github.com/odoo/odoo/blob/0bb5ac6c1a87367c1ebb343ad6e6e6e56188cf13/addons/product/security/product_security.xml#L34-L38
But the `website` module has some particular rule about setting the current company :
https://github.com/odoo/odoo/blob/0bb5ac6c1a87367c1ebb343ad6e6e6e56188cf13/addons/website/models/ir_http.py#L249-L261
So, in our case, since the user does not have company B in its allowed companies, then
`allowed_company_ids` = Company A. So `('company_id', 'parent_of', company_ids)` is trucy and the product is displayed
# Proposed solution
Doing the search with `with_company` raise an AccessError because the company is not present in the allowed_companies. Chaging the allowed companies logic seems risky because it
may lead to unintended side effects.
We instead enforce the website's company in the search's domain
opw-6115647
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#262366
Forward-Port-Of: odoo/odoo#260138This update fixes an issue where partners sharing the same VAT number were incorrectly excluded from VAT reports if their individual turnover was below a threshold. The change groups partners by VAT number and includes them in the report if their combined turnover exceeds the threshold, ensuring accurate reporting of VAT data. This improves compliance and reporting accuracy for Belgian businesses.
Original PR description
When having different partners with the same vat number and their individual turnover values are less than the threshold they were not included in the partner vat listing report even though if the total turnover for their vat number is above the threshold. This commit handles this case by grouping by vat number and if the total turnover for a vat number is above the threshold then it will be shown in the report with another level beneath it to show the partners having this vat number even if their individual turnovers are below the threshold. task-6133010 Forward-Port-Of: odoo/enterprise#116495 Forward-Port-Of: odoo/enterprise#115251
This update resolves an issue where credit notes related to returned stock weren't accurately calculating the cost of goods sold (COGS). The fix ensures that the correct price unit – either the original invoice price or the returned move value – is used, regardless of how the credit note was created. This ensures accurate financial reporting for returns and adjustments.
Original PR description
**Steps to reproduce:** Problem A) - create a storable product avco perpetual - add 2 unit in stock and set a cost of 10 - set the invoicing policy as "delivered quantities" - create and confirm a SO…
**Steps to reproduce:** Problem A) - create a storable product avco perpetual - add 2 unit in stock and set a cost of 10 - set the invoicing policy as "delivered quantities" - create and confirm a SO for 2 quantities - validate the delivery - click on "Create Invoice" and confirm the invoice - from the delivery, create and validate a return for 1 unit. - from the product form, change the cost to 15 - from the sale order, click on "Create Invoice" - confirm the Credit Note Problem B) - create a storable product with fifo perpetual - confirm a PO for 1 unit at 10 and validate receive - confirm a PO for 1 unit at 20 and validate receive - confirm a PO for 1 unit at 60 and validate receive - create a SO for 3 unit - deliver 1 unit with backorder - deliver another unit with backorder - deliver the last unit - create and confirm invoice - return the second delivery - from the invoice click on 'credit note' and validate the credit note with a quantity of 1 **Current behavior:** Problem A) the cogs is 25 Problem B) the cogs is 30 **Expected behavior:** Problem A) it should be 10 Problem B) the cogs should be 20 cause the move returned had a value of 20 **Cause of the issue:** Inside \_get\_cogs_value(), if there is an original invoice linked to the credit note we take the unit_price from this invoice. But, if the credit note is not created from the invoice (via the Credit Note button) but via the sale order (via create invoices), the account\_move has no reverse\_entry_id so we won't use the price_unit from the original line. https://github.com/odoo/odoo/blob/686a0cf67bb1e818baf43309fc94f3f0462097ed/addons/stock_account/models/account_move_line.py#L56-L58 So basically what we do for now is: If the credit note was created from invoice we use the unit price from original invoice in all cases. If the credit note was created from sale order we use get\_price\_unit in all cases (which will work for fifo because we'll use the value of the returned move but fail for avco if the standard price has changed cause we use the standard price) https://github.com/odoo/odoo/blob/dccd2256660b1e211707b740074f5fbba95ae149/addons/stock_account/models/stock_move.py#L261-L265 **Fix:** Regardless of how the credit note is created, if it's fifo we use get\_price\_unit to adapt to the value of the moves, if not we use the unit_price from original invoice opw-6097090 Forward-Port-Of: odoo/odoo#259630
This update fixes a bug in the Belgium Payroll DMFA report that incorrectly displayed 'Days Per Week' as 5 when employees worked fewer than 5 days a week. The fix accurately calculates the number of working days based on the employee's actual schedule, ensuring accurate reporting for Belgian tax compliance.
Original PR description
## Issue When generating a DMFA report with a working schedule with more or less than 5 days a week, the *Days Per Week* value in the report is still appearing as 5. ## Steps to reproduce 1. Install…
## Issue
When generating a DMFA report with a working schedule with more or less than 5 days a week, the *Days Per Week* value in the report is still appearing as 5.
## Steps to reproduce
1. Install *Belgium - Payroll* (`l10n_be_hr_payroll`)
2. In Payroll's Settings:
- set *ONSS Registration Number* to `0830123456`
- set *DMFA Employer Class* to `083`
- create a *Work Address DMFA code* (any name, any numeral code, but set the *Working Address* to the Belgian company used for the rest of the steps)
3. In Employees' Settings, set the *Company Working Hours* to a new Working Schedule, with 9 hours/day, 4 days/week. E.g from Monday to Thursday included:
- Work from 8:00 to 12:00
- Lunch from 12:00 to 13:00
- Work from 13:00 to 18:00
4. Create an Employee E for the Belgian company:
- In the *Payroll* tab, set the start date of the contract to 01/01/2026.
- In the *Personal* tab, set the *NISS Number* to `85073003328`
5. Create the payslip for January 2026 for the Employee E.
6. In Payroll > Reporting > Belgium > DMFA, create a new DMFA for the first quarter of 2026 and generate the PDF report
7. **In the generated PDF report, the _Days per Week_ line is set to 5.**
## Cause
The number of days was calculated by multiplying `5` with the `work_time_rate` of the related calendar. This is inaccurate in the case of a company where employees are only expected to work 4 days a week.
opw-6103934
Forward-Port-Of: odoo/enterprise#116794
Forward-Port-Of: odoo/enterprise#113804Previously, the system incorrectly calculated currency rates using invoice line types other than products, leading to inaccurate VAT reports. This update fixes the system to prioritize the first product line when determining the currency rate, ensuring accurate reporting and compliance. This change improves the reliability of VAT calculations.
Original PR description
The currency rate was previously computed using the first invoice line, regardless of its type. This caused incorrect rate calculation when the first line was not a product line (e.g., section, note, or display-only lines). This fix filters invoice_line_ids to use the first actual product line when extracting amount_currency and balance, ensuring that the derived rate reflects a valid monetary line. opw-5208724 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#239920 Forward-Port-Of: odoo/odoo#237535
This update prevents unauthorized users from viewing or modifying assets linked to invoices. Previously, any user could access asset information, which created a potential security risk. Now, access is restricted to users within specific accounting groups, ensuring data integrity and security.
Original PR description
Only groups `account.group_account_readonly`, `account.group_account_invoice` or higher have access to model `account.asset`, therefore if an user goes to see an invoice with assets and they are not on either group, they will receive an error and won't be able to access said invoice. How to reproduce: - Create a vendor bill - Create an account.asset and link it to said account.move - Go to the form view with an user that it's on group "Purchase: User" for example --> They get a traceback --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#115053 Forward-Port-Of: odoo/enterprise#112890
This update resolves an issue preventing v19.1 upgrades when managing subscriptions with service products. The problem stemmed from an incorrect comparison between date fields, leading to a TypeError. The fix ensures accurate date calculations during upgrade processes, restoring stable subscription functionality.
Original PR description
**Steps-to-Reproduce** - In v19, install subscriptions. - create new subscription + service product with allow one time sale enabled. - make a SO with that product,any reccuring plan and any end…
**Steps-to-Reproduce**
- In v19, install subscriptions.
- create new subscription + service product with allow one time sale enabled.
- make a SO with that product,any reccuring plan and any end date.
```
id | name | subscription_state | next_invoice_date | end_date
----+--------+--------------------+-------------------+------------
1 | S00001 | 1_draft | | 2026-05-02
```
- confirm the SO
```
id | name | subscription_state | next_invoice_date | end_date
----+--------+--------------------+-------------------+------------
1 | S00001 | 3_progress | 2026-05-01 | 2026-05-02
```
- remove its recurring plan (some product sold for months for testing then converted to one time sale )
```
id | name | subscription_state | next_invoice_date | end_date
----+--------+--------------------+-------------------+------------
1 | S00001 | 3_progress | | 2026-05-02
```
- upgrade to v19.1 will fail or opening sales > To Invoice > Orders To Invoice gives this error or add amount_to_invoice in list view using studio to produce in v19 :
```
File "/home/odoo/odoo18/enterprise/sale_subscription/models/sale_order_line.py",
line 175, in _compute_amount_to_invoice
and (not order.end_date or order.next_invoice_date < order.end_date)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '<' not supported between instances of 'bool' and 'datetime.date'
```
- upgrade failing for v19.1 because amount_to_invoice added to list view [here](https://github.com/odoo/odoo/commit/427232efd121410380b62acf4fd2e9ee369e6542#diff-48cb4309a6006f91b2b40e4c1049860218d419fce1782c7dcc278329803129caR193-R213).
upg - [4220658](https://upgrade.odoo.com/odoo/upgrade.request/4220658)
opw - [6128033](https://www.odoo.com/odoo/project/70/tasks/6128033)
Forward-Port-Of: odoo/enterprise#115976This update fixes inaccuracies in the data used for calculating Belgian HR payroll through Prisma. Specifically, it addresses missing or incorrect codes related to leave types (LEAVE280, LEAVE115, LEAVE231) to ensure accurate payroll calculations and compliance with Belgian regulations. This resolves an issue identified in previous development.
Original PR description
Issue: ---------------------------------------- Some prisma codes are wrong. Solution: ---------------------------------------- Change the data files. There are some subtilities that were not implemented: - LEAVE280: 0304 (if less than a year) and 0345 (if more) - LEAVE115: 0820 (Work accident) and 0830 (Occupational Disease) opw-6090081 Forward-Port-Of: odoo/enterprise#116642 Forward-Port-Of: odoo/enterprise#112949
This update ensures that delivery orders are created accurately when sales orders are cancelled and then settled through the Point of Sale (PoS) system. Previously, products marked as delivered on the original sales order wouldn't appear on the delivery order. This fix resolves this issue, guaranteeing accurate inventory tracking and order fulfillment.
Original PR description
Steps to reproduce ------------------ 1. Create a sale order with 2 products, confirm it 2. Cancel the SO, then click "Set to Quotation" 3. Open PoS, settle the order and pay 4. Check the delivery…
Steps to reproduce ------------------ 1. Create a sale order with 2 products, confirm it 2. Cancel the SO, then click "Set to Quotation" 3. Open PoS, settle the order and pay 4. Check the delivery order linked to the PoS order The delivery is empty, yet the products still show as "delivered" on the sale order. Why it's happening ------------------ When the SO is cancelled, its moves go to 'cancel' state. After resetting to quotation, those moves stay cancelled. When PoS creates the delivery, the filter in `_create_move_from_pos_order_lines` checks `has_valued_move_ids()` which returns False (all moves are cancelled), and `not move_ids` is also False (cancelled moves still exist). So the lines coming from the SO are excluded from the delivery. The fix ------- We now also create deliveries for lines whose SO moves are all cancelled. These are lines coming from a cancelled SO that now need to be shipped after we have settled their order from PoS. Note ---- The commit c0f338711f028088c98ea459f27c1669b29738d7 fixes this starting from saas-18.2, by introducing a separate `pos_repair` module which simplifies the main `pos_sale` code. In 18.2+, only the test will be forward ported. opw-6055856 Forward-Port-Of: odoo/odoo#263917 Forward-Port-Of: odoo/odoo#256693
This update resolves an issue preventing accurate inventory counts when scanning pack-in-pack items. The fix ensures the system correctly identifies and updates quantities during inventory adjustments, allowing users to reliably track stock levels within nested packaging.
Original PR description
### Steps to reproduce: - In the settings enable "Packages" - Create a storable product A and put 1 unit in a package P in stock - Inventory > Products > Packages > open your package P - Set a parent…
### Steps to reproduce: - In the settings enable "Packages" - Create a storable product A and put 1 unit in a package P in stock - Inventory > Products > Packages > open your package P - Set a parent package PP as container - Inventory > Operations > Adjustments > Physical Inventory - Select you product line for A > Request a count (from the control panel button) - Enable Show Expected Quantity and confirm - Go to the barcode app > Count Inventory (1) - scan your parent package PP #### > traceback: Uncaught Promise > Cannot create property 'inventory_quantity' on boolean 'false' ### Cause of the issue: When the Package scan is processed, we loop over all quants related to it: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L566-L569 https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L602-L617 And for each of these we try to find an existing line representing the quant to update or we do create a new line. Now, the issue, is that the subpackages of the quant are not provided to find the quant candidate line to update. As such, no line is found we enter the else clause and try to createa a NewLine: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L617-L627 This time however, the appropriate subpackage (the one of the quant) is provided to the arguments. And, since the line representing this quant is already existing, the `_createNewLine` will return False: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L393-L399 https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L423 This leads to a traceback at the end of the else close since `false.inventory_quantity` doe not make sense (Cannot create property 'inventory_quantity' on boolean 'false') https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L626-L627 Fix: We adapt the `_processPackage` of the `BarcodeQuantModel` to mimic the existing 'update' behavior on the `BarcodePickingModel`: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_picking_model.js#L2110-L2133 Note that UOM converstion should not be required since quants are already uniformly expressed in the product uom: https://github.com/odoo/odoo/blob/30b4edace6b0859cb1b1ba4f7f2ea80ba5398e3d/addons/stock/models/stock_quant.py#L52-L54 opw-5864591 Forward-Port-Of: odoo/enterprise#116715
A bug causing spreadsheet image inserts to crash due to excessive data loading has been resolved. The fix bypasses a security check within the database, allowing for more efficient image handling and preventing memory errors when dealing with large attachments. This ensures stable and reliable spreadsheet functionality.
Original PR description
To reproduce: ============= - In a db with a large amount of attachments - Insert an image in a spreadsheet - Observe the request hanging then ending with an error Problem: ======== - `ir.attachment._search` is overridden to apply security rules by building a domain based on public, `res_model`, `res_id` and `create_uid` fields - When no `res_model` restriction is present, the fallback path ORs in `res_model != False`, which matches nearly every attachment in the database - All matching records are then loaded into memory for Python-side access filtering via `_filtered_access`, causing the request to time out and crash with a memory error Solution: ========= - Set `bypass_search_access=True` on the many2many field definition so the ORM skips the `_search` override and relies on the SQL join to restrict returned records opw-6152979 Forward-Port-Of: odoo/enterprise#115766
This update resolves an error that occurred when calculating overtime deductions for employees with specific filing statuses (beyond 'single' or 'jointly'). The fix ensures the system correctly handles a wider range of filing statuses, preventing unexpected crashes. This improves the accuracy of overtime calculations for US-based employees.
Original PR description
Issue: ---------------------------------------- When having an employee with `l10n_us_filing_status` not in `['single', 'jointly']` and evaluating the rule parameter…
Issue: ---------------------------------------- When having an employee with `l10n_us_filing_status` not in `['single', 'jointly']` and evaluating the rule parameter `l10n_us_qualified_overtime_deduction_cap` an error occurs. Cause: ---------------------------------------- `l10n_us_filing_status` can have 5 values: `['single', 'jointly', 'separately', 'head', 'survivor']` But only `['single', 'jointly']` are defined for `l10n_us_qualified_overtime_deduction_cap` ([src](https://github.com/odoo/enterprise/blob/2d2056766441157dc45ebc37b677841c44e5c513/l10n_us_hr_payroll/data/hr_rule_parameters_data.xml#L48)). When running the rule "Qualified Overtime", the custom Python crashes because we read a key that is not there: https://github.com/odoo/enterprise/blob/2d2056766441157dc45ebc37b677841c44e5c513/l10n_us_hr_payroll/data/hr_salary_rule_data.xml#L56 Solution: ---------------------------------------- In the custom Python condition, we first check if the key is there. The custom Python computation also tries to read the key, but it is run only if the condition is validated. So we don't need to change it. Also fixed indentation of test 069. opw-6129657 Forward-Port-Of: odoo/enterprise#116551 Forward-Port-Of: odoo/enterprise#115754
This update fixes an issue where loyalty point transactions in POS orders were only recorded as a net difference, not the individual earned and spent amounts. The change ensures that the loyalty history accurately reflects the complete transaction, providing a more precise record of customer loyalty activity. This improves reporting and data accuracy for loyalty programs.
Original PR description
When a loyalty card both earned and spent points in the same POS order, the history entry only reflected the net difference instead of the gross amounts. The root cause was that the JS payload sent only a single `points` field representing the net change. Fix by tracking `points_earned` and `points_spent` separately in `couponData` and sending them to the server. opw-6041420 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261399 Forward-Port-Of: odoo/odoo#256022
This update resolves a bug where invoices created from timesheeted sales orders weren't correctly calculating the invoiceable quantities. The fix ensures that invoiceable lines are recomputed every time an invoice is created, regardless of whether dates are provided, leading to accurate invoicing for both stored and service-based products. This improves the reliability of our invoicing process.
Original PR description
Steps --------- 1. Install Accounting, Sale and Timesheet 2. Create 2 product a. Product A - storable - invoiced on Ordered Quantity b. Product B - service - create a task on order - invoice on…
Steps
---------
1. Install Accounting, Sale and Timesheet
2. Create 2 product
a. Product A - storable - invoiced on Ordered Quantity
b. Product B - service - create a task on order - invoice on
timesheeted
3. Create an SO with 3 product A and 3 product B
4. Add a timesheet line for 1 hour of product A - can be done thanks to
the button appearing on the SO at confirmation
5. Create Invoice
6. Don't add dates to the wizard and confirm -> Both product appear
7. Add date range that do NOT include the timesheeted lines -> Only the
storable product appear
8. Repeat step 6 -> Only the storable product appear
Problem
---------
During the creation of the invoice, the invoiceable lines would get
computed dates where provided to the wizard
(`sale.order.line.qty_to_invoice`). When no dates were provided, we
would not manually trigger the invoiceable lines recomputation and were
relying one the data store in cache.
Solution
---------
Force the invoiceable quantity recomputation upon each invoice creation.
opw-6001094
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#261062