Daily updates from Odoo
Monday, May 18, 2026
111 changes
26 changes
Enhancements to existing features
This update simplifies how businesses can customize the website event registration process. By separating the registration logic, developers can now easily inherit and modify the underlying code, leading to more flexible and tailored event experiences. This change enhances the extensibility of our website event functionality.
Original PR description
Since this controller returns raw markup, it is impossible to inherit. By splitting the controller `registration_new`, allows to manage custom developments with the inheritance of the prepare method instead. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264242 Forward-Port-Of: odoo/odoo#244156
Resolved issues and error corrections
This fix resolves an issue where generating closing entries in the Inventory Valuation view produced incorrect results when multiple companies were selected. The update ensures that the generated account move lines accurately reflect the stock valuation data for the selected main company, preventing mismatched balances.
Original PR description
**Problem:** In view Inventory valuation, generate entry doesn't work when multiple companies are selected. In the view only the main company matters. That means that even if multiple companies are…
**Problem:** In view Inventory valuation, generate entry doesn't work when multiple companies are selected. In the view only the main company matters. That means that even if multiple companies are selected, only the stock variation lines related to the main company selected are displayed (which is expected). But if you then click on 'generate entry' the account move lines created will have wrong values (not matching the values appearing in the view) **Steps to reproduce:** - create 2 new companies (to have clean accounting) - create a warehouse for both companies - for both comp, in settings for the 'fiscal localization' set Package : Generic Chart of account, if not already set (to have account journals). From company 1 : - create a storable prod with avco perpetual category - confirm PO for 2 @ 10, receive - bill only 1 @ 10 From company 2: - make sure the category is also perpetual average from this other company - confirm PO for 2 @ 50, receive, don't bill Notice how from the 'Inventory Valuation' view, rightfully, only the main company matters (no matter what other comp are selected): - If main comp is comp 1 there is stock variation lines for amount of 10 (which is expected because we have 20 in stock and only 10 in stock valuation account) - If main comp is comp 2 there is stock variation lines for amount of 100 (which is expected because we have 100 in stock and only 0 in stock valuation account) With comp 1 and 2 selected and comp 1 as main company: - click on 'Generate Entry' **Current behavior:** - both line have a balance of 110 **Expected behavior:** - they should have a balance of 10 as we saw on the 'inventory valuation' view **Cause of the issue:** To generate the data from the 'inventory valuation' view, inside _get_report_data() we call stock_value() and stock_accounting_value() to compare values from inventory and value from accounting. https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/report/stock_valuation_report.py#L36-L37 stock_value() sums total_value() of each product in the valued accounts https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L90-L94 Whereas stock_acounting_value(), sums the balance of each account move line of each valuation account https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L112-L114 All of this is related to the main company because we call _get_report_data() with context 'allowed_company_ids' set to only the main company https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/report/stock_valuation_report.py#L13 But when we click on generate entry, _get_stock_valuation_account_vals() is called with no context modification to 'allowed_company_ids' so when we call stock_value(), https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L238-L239 total_value will be based on both company https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L92 Note that stock_accounting_value() is still rightfully based only on main company because we use self.id in the domain https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L105-L108 opw-6168699 Forward-Port-Of: odoo/odoo#263946 Forward-Port-Of: odoo/odoo#262776
This update fixes an issue where dependent taxes weren't correctly recalculated after a base tax was removed from a sales order or invoice. The fix ensures that tax amounts are accurately computed, particularly when using the 'Affect Base of Subsequent Taxes' setting. This improves the reliability of financial reporting.
Original PR description
**Steps to reproduce:** * Install the *Accounting* module with French localization (*l10n_fr_account*). * Create a *Sales Tax* with: * A new tax group (e.g., 'Codifab'). * Enable *Affect Base of…
**Steps to reproduce:** * Install the *Accounting* module with French localization (*l10n_fr_account*). * Create a *Sales Tax* with: * A new tax group (e.g., 'Codifab'). * Enable *Affect Base of Subsequent Taxes*. * Create a *Sales Order*: * Add the first tax (with *Affect Base of Subsequent Taxes*). * Then add the second tax (eg VAT tax). * Confirm the *Sales Order*. * Create a *Down Payment Invoice* (percentage-based). * Open the generated invoice and: * Remove the first tax (the one affecting the base). **Observed behavior:** * The amount of the second tax group does not update after removing the first tax, leading to incorrect tax computation. **Cause:** * In `_import_base_line_extra_tax_data`, the condition: `all(str(tax.id) in extra_tax_data['manual_tax_amounts'] for tax in sorted_taxes)` only ensured partial matching of taxes. * This allowed reuse of stale `manual_tax_amounts` when taxes were removed or modified, causing incorrect base values for dependent taxes (e.g., *Affect Base of Subsequent Taxes*). **Fix:** * Update the condition to enforce an exact match between current taxes and cached `manual_tax_amounts` by checking both size and membership. * Prevent reuse of outdated tax data when taxes change, ensuring proper recomputation of dependent taxes. * Align Python logic with the JS implementation for consistency between `account_tax.py` and `account_tax.js`. opw-6063970 Forward-Port-Of: odoo/odoo#264710 Forward-Port-Of: odoo/odoo#259566
This update corrects a technical issue in the French Intrastat export process. Previously, supplementary unit data for products with CN codes was being incorrectly omitted from the DEBWEB2 XML file. This fix ensures that all relevant quantity information is accurately included, improving the reliability of Intrastat reporting.
Original PR description
Steps to reproduce 1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set…
Steps to reproduce
1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set `intrastat_supplementary_unit_amount` on it.
2. Post EU customer invoices for that product.
3. Export the DEBWEB2 XML from the Intrastat report.
Issue
The FR export collapses engine rows a second time in `_group_items`, because the DEBWEB2 format groups more aggressively than the SQL. The aggregator only declares `value` and `weight`: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/models/account_intrastat_report.py#L308-L313 Items are then rebuilt as `dict(zip(grouping_key, key_tuple)) | grouped_item_values`. `SU_code` survives (it is in the grouping key), but the numeric `supplementary_units` is in neither side and is silently dropped as soon as two engine rows merge. The template then skips the element because of its `t-if="item.get('supplementary_units')"` guard: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/data/intrastat_export.xml#L61
opw-6139657
Forward-Port-Of: odoo/enterprise#117357
Forward-Port-Of: odoo/enterprise#117033This update resolves an issue preventing successful Envia deliveries in Chile. The problem stemmed from a mismatch between Odoo's state code mapping and Envia's API requirements. The Envia API expects a shorter state code (2-3 digits), which wasn't being applied correctly for the 'Metropolitana' region. This fix updates the mapping to ensure accurate data transmission to Envia.
Original PR description
### Steps to reproduce: - Install delivery_envia - Website > Configuration > eCommerce > Delivery Methods > Envia - Enable the delivery method, sync the carrier and Publish it - With a portal user >…
### Steps to reproduce:
- Install delivery_envia
- Website > Configuration > eCommerce > Delivery Methods > Envia
- Enable the delivery method, sync the carrier and Publish it
- With a portal user > Shop > Add any product to your cart > Checkout
- Register an address a valid 'Chile' address and confirm say:
'street and Number': Avenida Providencia 1432, Depto 402
'city': Santiago 'zip': 8320000
'country': Chile 'state': Metropolitana
#### > Envia Error: Invalid Option - String is too long at #->properties:destination
### Cause of the issue:
The problem is caused by the fact that Envia's api expects a 2-3 digits to represent state codes: https://docs.envia.com/reference/state-by-code
The mapping from Odoo's code state representation to envia's one is expected ot be performed by this mapping:
https://github.com/odoo/enterprise/blob/75cba6d5a88ebc4e0f35040a173ac1c443638daf/delivery_envia/models/envia_request.py#L27-L43 when the address is converted here:
https://github.com/odoo/enterprise/blob/75cba6d5a88ebc4e0f35040a173ac1c443638daf/delivery_envia/models/envia_request.py#L535-L542 That being said, the `Chile`'s code states of have been changed in [6694a3942c58ff1a56c9e4b36edbe126dd1e66f8](https://github.com/odoo/odoo/commit/6694a3942c58ff1a56c9e4b36edbe126dd1e66f8) to match the official Iso but not in the Envia's mapping leading a failling match keeping the 4 charracter long `CL-RM` of the `Metropolitan` state provided in to the Envia's api as address data.
opw-6210007
Forward-Port-Of: odoo/enterprise#117280A crash in the event registration modal was resolved by ensuring the modal is fully closed before attempting to manipulate its elements. This change prevents errors that occurred when switching between event views, improving stability and user experience.
Original PR description
Steps to reproduce: =================== 1. Go to Event, open an event page 2. Click "Register" & Select a ticket and confirm 3. Switch to edit mode => crash. Cause: ====== The cleanup callback called…
Steps to reproduce: =================== 1. Go to Event, open an event page 2. Click "Register" & Select a ticket and confirm 3. Switch to edit mode => crash. Cause: ====== The cleanup callback called `hide()` followed immediately by `dispose()`. Bootstrap's `hide()` is asynchronous — it registers a `transitionend` callback that fires `_hideModal()` after the CSS transition. `dispose()` nullifies `this._element` synchronously via `BaseComponent`, so when the `transitionend` fires and `_hideModal()` tries to access `this._element.style`, it crashes with: TypeError: Cannot read properties of null (reading 'style') This happened when switching to edit mode while the event registration modal was open: the `public.interactions` service stopped the interaction, triggering the cleanup. Solution: ========= Listen for `hidden.bs.modal` (fired at the end of `_hideModal`) and only `dispose()` inside that handler, ensuring `_element` is still valid throughout the transition. task-6133395 Forward-Port-Of: odoo/odoo#264365
This update resolves an issue where creating two overtime shifts on the same Saturday (ending at midnight) would trigger an error. The fix addresses a timing discrepancy in how overtime start and end times are calculated, preventing the 'Expected singleton' error. This ensures overtime is correctly registered for employees with complex shift schedules.
Original PR description
__ ## Short functional explanation of the error When we create 2 shifts for the same day for an employee, on a non-working day for their schedule. When trying to create the second one after setting…
__ ## Short functional explanation of the error When we create 2 shifts for the same day for an employee, on a non-working day for their schedule. When trying to create the second one after setting the end date to midnight, we get the error: `ValueError: Expected singleton: hr.attendance.overtime.line(2, 3)` ## Reproduction Steps 1. Create an Employee. In the Payroll tab, Make sure they have an active contract. Set their Working Hours to a fixed schedule, where they have saturdays as non-working days. In the Settings tab, set an Overtime Ruleset. 2. Click on the overtime ruleset. Then, for each rule, under Action, set the Work Entry Type To Use as Overtime Hours. 3. Go to Attendances. In Configuration > Settings, under Extra Hours, set the Extra Hours Validation as Approved By Manager. 4. Create an attendance for your Employee on a Saturday, from 12h to 18h. 5. Create a second attendance for your Employee on that same Saturday, from 18h to 00h00. Try to Save. Note: the timezone of your computer, the working schedule and the employee should be set at Brussels time. ### Expected behavior The Overtime is registered. ### Unexpected behavior An error occurs: `ValueError: Expected singleton: hr.attendance.overtime.line(2, 3)` ## Origin of the issue The end time of the overtime is defined as follows: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L54-L56 However, in the case where our shift ends after the computed end of the day (in our case, the end time of the shift is 00:00:00 and the end of the day is set at 23:59:59), it creates some problems. The end time of the overtime is set 1 second too early. Later we compute the start time of the overtime as follows: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L57 Thus, the time start of the overtime is also set one second too early. As our second shift starts right after the first one, after the execution of this code, we will get a second shift that starts before the end of the first one. Then, we add these values in a list: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L59 which will contain overlapping timeframes, and with which we create an Interval: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L60 But when we create an Interval with overlapping timeframes, we obtain only one interval as the timeframes are merged. https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L173 As a result, `overtime_intervals` will contain only one time frame with 2 different corresponding overtimes, which causes a singleton error when reaching: https://github.com/odoo/enterprise/blob/47faff7d6c9da5572e3bad3ff5a55b40c2ba81ac/hr_work_entry_attendance/models/hr_version.py#L179 __ opw-6096454 Forward-Port-Of: odoo/enterprise#117247 Forward-Port-Of: odoo/enterprise#114147
This update fixes an issue where scanning a packaging barcode (like '6' for a 6-pack) intermittently added quantities to the wrong line in the stock picking process. The fix ensures the barcode scan correctly identifies and updates the intended packaging unit, resolving the alternating quantity issue.
Original PR description
Issue ----- When there are 2 lines for a single product and different packaging uoms, scanning a packaging barcode alternates between lines. Steps to reproduce ----- - Enable packagings - Create a…
Issue ----- When there are 2 lines for a single product and different packaging uoms, scanning a packaging barcode alternates between lines. Steps to reproduce ----- - Enable packagings - Create a product AAA - barcode 1 - Create a packaging 6-Pack - 6 units - barcode for AAA set to 6 - Create a PO - one line for 30 units of AAA - one line for 5 6-Pack of AAA - Confirm PO and open picking in barcode - Scan "6" multiple times > Quantity increases on both lines, alternating for each scan Cause ----- Both lines can be found as matching lines when doing https://github.com/odoo/enterprise/blob/d279632db25713dd639a51385cad197dfdbd2bdc/stock_barcode/static/src/models/barcode_model.js#L1426 The reason it alternates between the lines is because we set the currently selected line first in the array - and since both lines match, the `foundLine` returned ends up being the non-selected line. https://github.com/odoo/enterprise/blob/d279632db25713dd639a51385cad197dfdbd2bdc/stock_barcode/static/src/models/barcode_model.js#L1823-L1832 We can avoid this y refining the `break` condition of the loop to also match the packaging uom. ----- Ticket: opw-6034572 Forward-Port-Of: odoo/enterprise#116961 Forward-Port-Of: odoo/enterprise#112578
This update resolves an issue preventing the MPESA payment method from correctly processing transactions initiated by Safaricom. It disables CSRF checks on callback endpoints and ensures URLs are consistently using HTTPS, addressing a common error related to invalid URLs. Additionally, the code now includes the till number for transactions, improving data accuracy.
Original PR description
1. The `MPESA` payment method needs a callback url where it does a `POST` request with the transaction details. Since the call comes from safaricom, CSRF will block those requests. This commit will…
1. The `MPESA` payment method needs a callback url where it does a `POST` request with the transaction details. Since the call comes from safaricom, CSRF will block those requests. This commit will disable CSRF checks on the callback endpoints which are expected to be called from an external service 2. Sometimes the `web.base.url` parameter is automatically set to http. But safaricom expects https for all the urls. So we need to ensure that the urls we send on `lipa_na_mpesa_register_urls` use https, otherwise the registration fails with an `invalid url` error. Additionally, I added the error message in case of error 4. In addition to the business short code we also need a till number for transactions. Since this is stable, I've added the till number as an extension of the business shortcode field and then parse it before usage. On master there is a new PR which will properly separate the fields Task-[6045833](https://www.odoo.com/odoo/project/1737/tasks/6045833) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254993
This update fixes an issue where pasting content into the composer created excessive nested divs, preventing users from correctly deleting pasted text. The fix also adds necessary plugins to properly handle links within the composer, ensuring accurate link selection and deletion.
Original PR description
Currently, when pasting content into the composer, we sanitize it by stripping all tags except a few allowed ones, and this creates a lot of nested divs in the pasted content. This prevents the content from being deleted correctly when the user is in the nested divs and presses backspace. For links, we currently missing the plugin that correctly handles them in the composer, this commit adds it and also adds the missing plugin LinkSelectionPlugin and OdooLinkSelectionPlugin for the composer. task-6214020 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264135
This update fixes a bug that prevented multi-day shift records from appearing on the live map. Now, technicians' locations and shifts are accurately displayed, and the map views (Gantt and Calendar) are optimized to show shifts on a daily basis, improving usability.
Original PR description
This commit changes the domains for the "My Map" and "Map By Resource" to only include shifts with a partner. Previously, it was including 'today' as part of the domain, which is incorrect as users may still want to view other days' shifts. task-6180159
This update fixes an issue where the departure date wasn't correctly displayed when an employee has multiple versions (e.g., contract and notice period). The change ensures the system accurately reflects the employee's departure date, improving payroll and reporting accuracy. This impacts how employees' end dates are tracked.
Original PR description
__ ## Short functional explanation of the error When we set the departure of an employee. The version is retrieved using the dismissal date. However, employees can work after their dismissal date,…
__ ## Short functional explanation of the error When we set the departure of an employee. The version is retrieved using the dismissal date. However, employees can work after their dismissal date, until their departure (in the case of a notice, for example). Therefore, the departure date should be chosen instead. ## Reproduction Steps 1. Go to Employees and create a new employee. In the Payroll tab, set a start date for their contract. Hit save. 2. This will create a version. You can see it top right, with the contract date. Click on the '+' next to it and set a date later. 3. Click on the cog in the top left and click End of Collaboration. Set an End Reason. Set the Dismissal Date to occur during the first version and the Departure Date to occur during the second version. Then, click Schedule. ### Expected behavior The Departure tab should appear when clicking on the second version, top right. ### Unexpected behavior The departure tab appears on the first version. ## Origin of the issue To select the version on which the departure occurs, we use this line of code: https://github.com/odoo/odoo/blob/be8b1bbad757fda27df579ce36cbc97324f58f62/addons/hr/models/hr_employee_departure.py#L117 `departure_date` should be used instead. __ opw-6079675 Forward-Port-Of: odoo/odoo#264667
This update ensures that employees on leave, even those in companies a user doesn't have access to, now correctly display a 'leave' icon in channel listings and avatar cards. Previously, the system was restricted by company access, leading to inaccurate status indicators. This change improves the user experience by providing a more complete and reliable view of employee availability.
Original PR description
* = hr_holidays Before this commit, when displaying the IM status icon for employees on leave of companies the user does not have access to, we would not display the `fa-plane` icon or the "Back on"…
* = hr_holidays Before this commit, when displaying the IM status icon for employees on leave of companies the user does not have access to, we would not display the `fa-plane` icon or the "Back on" indicator. Steps to reproduce: - Create a new company X - Create a new employee Y (with user) in company X - With a user who does not have access to company X open the General channel member list -> no leave icon, open the avatar card -> no icon This happens because since [1] the leave IM status icon is computed client side using the employee information, rather than computed on the `im_status` field itself. This however causes problem in a multi-company context due to the field `employee_ids@ResUsers` having a field-level domain restricting to the requesting user's active companies. This commit fixes the issue by fetching all of the user's employee_ids regardless of active company. [1] https://github.com/odoo/odoo/pull/210189 task-6191367 Forward-Port-Of: odoo/odoo#263024
This change fixes an issue where products were incorrectly displayed on the website when a user's website company was set to a different company than the product's assigned company. The update ensures product searches accurately reflect the user's current company setting, preventing incorrect product visibility and potential sales order errors. This improves data accuracy and sales process reliability.
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#262635
Forward-Port-Of: odoo/odoo#260138This update fixes an issue where payroll account merges incorrectly combined employee analytic distributions, leading to inaccurate financial reporting. The change ensures that each employee's specific distribution is preserved, preventing the overwriting of percentage allocations when multiple employees use the same accounting account. This improves the accuracy of payroll accounting and financial data.
Original PR description
Steps to reproduce 1. Enable "Batch Account Move Lines" in the Payroll settings. 2. Configure two employees' versions with an analytic distribution on the same analytic account but with different…
Steps to reproduce
1. Enable "Batch Account Move Lines" in the Payroll settings.
2. Configure two employees' versions with an analytic distribution on the
same analytic account but with different percentages (e.g. {acc: 50}
for the first employee and {acc: 70} for the second).
3. Generate a payslip run containing both employees and validate it.
Issue
The generated account move aggregates the two payslips into a single
line whose analytic_distribution matches only the last employee being
processed; the other employee's percentage is silently lost.
`_get_existing_lines` decides whether an incoming line can merge into an
already accumulated one. When the incoming line has an analytic
distribution, the merge condition delegates to
`_check_partially_matching_accounts`:
https://github.com/odoo/enterprise/blob/e4a1326c7a8a74da7970aeaa9900c19d01634e31/hr_payroll_account/models/hr_payslip.py#L254-L271
https://github.com/odoo/enterprise/blob/e4a1326c7a8a74da7970aeaa9900c19d01634e31/hr_payroll_account/models/hr_payslip.py#L273-L283
That helper returns True as soon as any analytic account of the new
line appears anywhere in the existing line's distribution dict, without
comparing percentages. Two distributions such as {acc: 50} and
{acc: 70} share the same account, so the helper returns True, the
lines are merged, and whichever distribution ends up on the merged line
overwrites the other — the total amount is correct but the analytic
split is wrong.
The logic introduced in commit https://github.com/odoo-dev/enterprise/commit/e40a3166286a6bc546e9543b935233d2a110dc52 successfully addressed merging for rule-level distributions
with composite keys (e.g., {'13,7,12': 40}). However, that implementation is overly inclusive for employee-specific distributions.
It fails to differentiate between cases where the same analytic account is utilized across various employees but with different percentage allocations.
Because it only checks for an account overlap rather than a perfect distributional match, it incorrectly aggregates distinct financial dimensions into a single journal line
Solution
Compare the full analytic_distribution dict by strict equality. Lines
merge only when the distribution is identical (same keys AND same
percentages), keeping the batch feature anonymizing identically
configured employees while preserving one line per distinct
distribution.
opw-6102508
Forward-Port-Of: odoo/enterprise#114156This update corrects a bug where the 'Purchase Orders' button disappeared when changing an Analytic Account's plan. The fix adjusts how the system identifies purchase orders linked to analytic accounts, ensuring the button remains visible regardless of the plan setting. This ensures users can always access purchase order details linked to their accounts.
Original PR description
# How to reproduce - Enable the analytic accounting in the settings - Create a PO - Add a PO line - Set the Analytic Distribution of that PO line to an Analytic Account of your choice - Confirm the…
# How to reproduce
- Enable the analytic accounting in the settings
- Create a PO
- Add a PO line
- Set the Analytic Distribution of that PO line to an Analytic Account of your choice
- Confirm the PO
- Create a Vendor Bill from that PO and confirm the VB
- Go to the Analytic Account chosen before
- Change the Plan of that Analytic Account
# The problem
When the Plan is not set to the "Project Plan", the Purchase Orders smart button disappears
# Why
The Purchases Orders smart button is invisible if the variable purchase_order_count is equal to 0. That field is computed by a function that does a search with the following domain :
```py
[('order_line.invoice_lines.analytic_line_ids.account_id', '=', account.id)]
```
When we change the Plan of the Analytic Account, analytic_line_ids.account_id is set to NULL, so the search return nothing.
Why is that field set to NULL ?
Well, to reference its plan, an Analytic Line does not use a python-defined field. In fact, each time a new Analytic Plan is added to the database, a new column is added to the Analytic Line model. That column's name is x_plan{plan.id}_id or, for the specific case of the "Project Plan", it is account_id
When the Plan of an Analytic Account is changed, it takes every Analytic Line associated with that Plan and switch which column containing the id of the Analytic Account.
Take for exemple the following Analytic Line :
```
(account_id = NULL, x_plan2_id = NULL, x_plan3_id = 1)
```
When the associated Analytic Account's Plan is changed to the "Project Plan", it becomes :
```
(account_id = 1, x_plan2_id = NULL, x_plan3_id = NULL)
```
So, we need to adapt to search so that it uses the right plan's name.
opw-5897037
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#263652
Forward-Port-Of: odoo/odoo#248236This update corrects a bug where the payment button was incorrectly displayed, preventing users from completing transactions. Previously, the system relied on an outdated check for KYC completion, now the system correctly determines if payment initiation is active, ensuring the payment flow functions properly.
Original PR description
Currently, is_payment_enabled is used to determine whether the payment button should be displayed. However, this field only indicates that the TPP / institution allow payment initiation, not that it's active. Since 19.2, `/initiate_payment` no longer checks whether the KYC flow has been completed before initiating a payment. As a result, users can now reach a blocked state where the payment flow is exposed but cannot actually proceed. No task ID
This update ensures Odoo correctly sets the `toStateCode` field for SEZ transactions when generating e-waybills. Previously, this was missing, causing API errors and preventing shipments from being processed. This fix ensures compliance with e-waybill regulations and avoids disruptions to international trade.
Original PR description
For SEZ transactions, the e-waybill API requires `toStateCode` to be set to 99. Previously, this value was not enforced, leading to API errors: - 373 for export transactions - 641 for supply and CKD/SKD/lots supply This fix updates the logic to derive `toStateCode` based on the invoice's GST treatment. When the transaction is identified as SEZ, `toStateCode` is correctly set to 99, ensuring compliance with e-waybill requirements and preventing API failures. task-6117694 Forward-Port-Of: odoo/odoo#259327
This update resolves an issue where intercompany invoices were incorrectly flagged with a tax validation error. The fix ensures that taxes are correctly recalculated when processing invoices between companies with different fiscal positions, improving the accuracy of intercompany accounting. This prevents disruptions to cross-border transactions.
Original PR description
**Steps to reproduce:** * Install the *Accounting* module. * Install localisation modules for two different regions: * *Belgium* (**l10n_be**) * *Luxembourg* (**l10n_lu**) * Configure two companies,…
**Steps to reproduce:** * Install the *Accounting* module. * Install localisation modules for two different regions: * *Belgium* (**l10n_be**) * *Luxembourg* (**l10n_lu**) * Configure two companies, each assigned to one of the above regions. * Create fiscal positions: * In the Belgium company, create a fiscal position for Luxembourg. * In the Luxembourg company, create a fiscal position for Belgium. * Go to *Accounting > Configuration > Settings*. Enable *Inter-Company Transactions*. Enable synchronization of *Vendor Bills and Invoices* for both companies. * Create an invoice in the Luxembourg company. Select a partner belonging to the Belgium company. Add a product with applicable taxes. **Observed behavior:** * A validation error is raised: 'This entry contains taxes that are not compatible with your fiscal position. Please check the country set in the fiscal position and in your tax configuration.' **Cause:** * During intercompany bill creation, a foreign fiscal position is applied before recomputing taxes. * If no mapped foreign taxes exist, the system keeps domestic purchase taxes. * This leads to a mismatch between taxes and fiscal position, triggering the validation error. **Fix:** * Add a safeguard in *_inter_company_create_invoices()*. * After *_inter_company_sync_invoice_line_taxes()* recomputes taxes, *_inter_company_has_incompatible_fiscal_position_taxes()* checks whether the fiscal position is incompatible. * If incompatible, the fiscal position is removed and taxes are recomputed without it. opw-6103671 Forward-Port-Of: odoo/enterprise#117450 Forward-Port-Of: odoo/enterprise#115085
This update fixes a calculation error in the Belgian payroll module (l10n_be_hr_payroll) that was incorrectly applying tax rules to employees outside of Belgium. The change ensures that the Niss (Non-Investment Savings Scheme) calculations are now accurate only for Belgian employees, improving the financial reporting and compliance of the system.
Original PR description
Forward-Port-Of: odoo/enterprise#117530
This update fixes an error in the Italian Annual VAT Report that was incorrectly calculating the balance amount for line VF25. The fix ensures the report accurately reflects the total taxable base as required by Italian tax regulations, aligning with official government guidelines. This ensures accurate VAT reporting for Italian businesses.
Original PR description
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive…
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive operations, the report erroneously mixes tax amounts into the balance column. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to Tax Report and visualize the Annual Tax Report (IT) 3. Go to VF VAT Report 4. See the VF25 is mixing taxes and balances ### Cause of the issue: The root cause lies in the aggregation_formula definition for the tax_annual_report_line_VF25 record. The formula was incorrectly configured to aggregate the .tax expressions for lines VF1 to VF13 (VF1.tax + VF2.tax + ...) instead of their respective .balance expressions, while correctly using .balance for the remaining lines (VF17 to VF24). https://github.com/odoo/odoo/blob/878c08cf522a3278b4e6ff5f3d18444989e9998d/addons/l10n_it/data/tax_report/annual_report_sections/vf.xml#L286-L299 It's just a typo in this commit: https://github.com/odoo/odoo/pull/164064/changes/f292ba119d6376dbfb3c1fac4960c9c56a74d938 ### Reason to introduce the fix: From documentation https://www.agenziaentrate.gov.it/portale/documents/20143/9602686/IVA_ANNUALE_2026_istr.pdf/2a42fb92-1b76-229a-d0f5-06069d79b514?t=1768504755711 : > Rigo VF25, colonna 1, va indicato il totale degli imponibili determinato sommando gli importi riportati ai righi da VF1 a VF23, colonna 1, diminuito dell’importo di cui al rigo VF24. In colonna 2 va indicato il totale delle imposte determinato sommando gli importi delle colonne 2 dei righi da VF1 a VF13. opw-6172791 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264379
This update fixes an error in the calculation of basic salaries for employees in Mexico. Previously, unpaid leave wasn't correctly factored into the daily rate, leading to inaccurate payments. Now, the calculation accurately reflects total calendar days worked, ensuring correct payments for all employees, including those on unpaid leave.
Original PR description
In Mexico, the basic salary must be calculated based on the total calendar days of the period. This ensures that both worked days and non-working days (e.g. Sundays) contribute equally to the total…
In Mexico, the basic salary must be calculated based on the total calendar days of the period. This ensures that both worked days and non-working days (e.g. Sundays) contribute equally to the total payment. This calculation also applies to the daily schedule, as the proportional daily wage must be divided equivalently across the hours of the day. Current behavior: When an employee has an unpaid leave, the basic salary is incorrectly prorated using only the registered days/hours. Example: For a monthly wage of 30,000 MXN in a month with 22 scheduled days (21 attendances + 1 unpaid leave), the implicit daily rate becomes 1,363.63 (30,000 / 22). This leads to an incorrect basic salary of 28,636.36 MXN for the days worked. This also happens with unpaid leave for x hours, e.g., for 2 hours, the unpaid leave is calculated as 2 hours * (30,000 / (22 days * 8 hours)) = 340.90 MXN, which is incorrect. Expected behavior: The basic salary should be derived from the full period (e.g., 30 days for a month, 15 for a bi-weekly period). Example: For a 30,000 MXN wage, the daily rate should be 1,000 MXN (30,000 / 30 days). If there is 1 unpaid leave, the basic salary should be 29,000 MXN (29 days * 1,000 MXN), regardless of the number of scheduled working days in the calendar. For unpaid leaves by hours, e.g., for 2 hours, the unpaid leave should be calculated as 2 hours * (30,000 / (30 days * 8 hours)) = 250.00 MXN. To achieve this, the calculation of the days in the `_get_worked_day_lines` is: * Adjust worked days/hours for out-of-contract entries where necessary, ensuring that rest days(Sundays) are included in the count. * Get all worked hours in the lines. * Calculate the number of days to pay based on the total hours and the hours per day. ### Case: payslip does not cover the complete pay period Current behavior: If a payslip is created for a partial period, the total amount is the full period wage. Expected behavior: The total amount should be pro-rated based on the days of the period. For example, if a payslip is created for 25 days(with a monthly schedule pay), the total amount should be the daily salary multiplied by 25 days. To achieve this, `_compute_amount` is updated to calculate the wage based on the `l10n_mx_daily_salary`. Changes on tests: * Add: * `test_monthly_payslip_with_partial_leave`, `test_partial_payslip`, `test_partial_payslip_new_hire_month_31_days` and `test_partial_payslip_new_hire_month_28_days`. * `test_hourly_payslip_by_attendance` to validate when `Work Entry Source` is set to "attendance". * Update: * `test_hourly_payslip`, `test_monthly_payslip` and `test_partial_payslip_new_hire` to align with the new calculation. * Adjust payslips dates to match the `schedule_pay` in `test_regular_payslip_subsidy` and `test_weekly_schedule_pay_no_code` * Fix a one-day difference in `TestMxEdiHrPayrollCommon`(16 days instead of 15 days for a bi-weekly schedule), and update the corresponding CFDI values. * Refactor tests and add new helpers. ### Error on [warning issues generation][1] and [`_compute_is_wrong_duration`][2] The warning: `"The duration of the payslip is not accurate according to the structure type."` appears with these custom periods for Mexican Payroll, although the period is correct: * `10_days` * `14_days` * `bi-weekly` Steps to replicate: * Install `l10n_mx_hr_payroll` module. * Switch to "INNOVACION VALOR Y DESARROLLO SA SA" company. * Go to Employees and open "Cesar Osbaldo Cruz Solorzano". * Click on "Payroll" tab, change the "Pay Schedule" to any option listed above, for example "Bi-weekly". * Go to Payroll > Payslips > Payslips and create a new pay run. * Select Salary Structure 'Mexico: Regular Pay', Pay Schedule 'Bi-weekly' and the Period '01/01/2026 -> 01/15/2026'. * Click on "Continue", select Cesar and click on "Select". * It appears the warning issue. Problem: The warning is raised because of `slip.date_from + slip._get_schedule_timedelta() != slip.date_to` condition, because `_get_schedule_timedelta` function calls [`self._schedule_timedelta(schedule, self.date_from)`][3] without the `country_code` argument. In the Mexican Payroll [_schedule_timedelta is overriden][4] but it is necessary to call it with the country code to use the custom periods; similar to how the [`date_end` is computed][5]. Solution: Call `_get_schedule_timedelta` passing the `country_code` [1]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip.py#L1367 [2]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip.py#L1454 [3]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip.py#L275 [4]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/l10n_mx_hr_payroll/models/hr_payslip.py#L58 [5]: https://github.com/odoo/enterprise/blob/1666ac87b6cb40e904210fecd159df3ac5b6b33a/hr_payroll/models/hr_payslip_run.py#L211 target: 19.0 task-6073601 Forward-Port-Of: odoo/enterprise#115044 Forward-Port-Of: odoo/enterprise#112524
This update resolves a restriction in the l10n_mx_edi module that prevented credit notes (out-refunds) from utilizing Payment Policies (PPD) as required by Mexican tax regulations (SAT). The change allows credit notes to correctly align with SAT portal requirements, ensuring accurate financial reporting. This improves compliance and simplifies the process for handling refunds in Mexico.
Original PR description
Currently, credit notes cannot be PPD (payment_policy), however, SAT portal allows it. **STEP TO REPRODUCE** 1. Install the l10n_mx_edi module. 2. Create an invoice with PPD (either changing it or through payment terms). 3. After send CFDI, generate a credit note and try to set PPD **FIX** Allow move_type = 'out_refund' to be PPD. Task-6049654 Forward-Port-Of: odoo/enterprise#114886
This update fixes a confusion issue in the split bill screen for point-of-sale orders. Previously, users couldn't easily identify which variant price corresponded to each order line when multiple variant options were selected. Now, order line attributes are displayed, making it easier to manage and understand split orders with different variant prices.
Original PR description
Currently, when using the split bill screen you cannot differentiate variants. That's problematic when each variant is assigned to an extra price and you have to determine which price corresponds to each variant. Steps to reproduce: ------------------- * Go to the product and search for the Bacon Burger * Assign a different extra price for each variant option * Open Restaurant * Order the bacon burger multiple times, one for each possible variant * Split the order > Observation: On the split screen you see multiple lines of bacon burger each with a different price but if you don't know all the extra price possible it's impossible to know which orderline corresponds to each variant. Why the fix: ------------ Attributes are only shown in display mode, we also show them in split mode. opw-6041713 Forward-Port-Of: odoo/odoo#264059 Forward-Port-Of: odoo/odoo#257265
This update resolves an issue where changes made to timesheet data in one Odoo tab weren't consistently reflected in other tabs. The fix ensures that all modifications are saved and synchronized across different windows, improving data accuracy and user experience. This enhancement guarantees that users always work with the most up-to-date timesheet information.
Original PR description
Steps to reproduce: - Open Odoo in two tabs - Open the systray in tab 1 - Change some fields - Close the systray to save - Open the systray in tab 2 All fields are not in line in both tabs. This commit, hence, ensures that all data changed in the inline form is saved and consistent across different windows. When switching window, the systray is closed and the data is saved to the local storage. When opening the systray in another tab, the local storage will be accessed to read the latests changes (i.e., the modifications done in the other tab). task-6180394 Forward-Port-Of: odoo/enterprise#116007
This update fixes an issue where the reprint button was unavailable on preparation printers across different devices within the same order session. By moving data storage to a shared session variable, the reprint button now works consistently on all devices sharing the same order, streamlining the preparation process for restaurant orders.
Original PR description
When sending an order to a preparation printer, the reprint button was invisible on any device other than the one that originally sent the order. This happened because `lastPrints` was stored in the order's `uiState`, which is local to each device. Moving it to `last_order_preparation_change` — which is shared across devices in the same session — fixes the issue. The reprint button is now visible and functional on all devices sharing the same session. --- Task: https://www.odoo.com/odoo/project/1737/tasks/6196913 Forward-Port-Of: odoo/odoo#264426 Forward-Port-Of: odoo/odoo#263094
20 changes
Enhancements to existing features
This update simplifies how businesses can customize the website event registration process. By separating the registration logic, developers can now easily inherit and modify the underlying code, making it simpler to tailor events to specific needs. This enhances flexibility and reduces the complexity of adding custom features to our website events.
Original PR description
Since this controller returns raw markup, it is impossible to inherit. By splitting the controller `registration_new`, allows to manage custom developments with the inheritance of the prepare method instead. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264242 Forward-Port-Of: odoo/odoo#244156
Resolved issues and error corrections
This update resolves an issue where allocated leave time wasn't correctly displayed in the Time Off Request wizard when duplicate leave types were created. The fix ensures that each leave type's allocation data is accurately retrieved, regardless of shared names, preventing incorrect leave calculations.
Original PR description
Pre-requisite: --------------------------------------- 1. Install the Time Off module 2. Create a new company (e.g, Test Company) 3. Create New Timeoff Type: * Ensure a default company is set (e.g,…
Pre-requisite:
---------------------------------------
1. Install the Time Off module
2. Create a new company (e.g, Test Company)
3. Create New Timeoff Type:
* Ensure a default company is set (e.g, YourCompany)
4. Duplicate the created Time off type:
* Remove (Copy) from the name so both records share the same name
* Clear the Company field on the duplicated record
Steps to reproduce:
---------------------------------------
1. Go to Time Off type which has no Company
2. Allocation Smart button > New
3. Set allocation for some days (e. g, 10 Days) > Approve allocation
4. Now, click on Employee > Time Off smart button
5. On the Dashboard, you can see allocated leaves
6. Click on any day to create a Time Off Request
Observation:
---------------------------------------
The allocated Time Off Type is not available in the request wizard, even though allocation exists.
Issue:
---------------------------------------
When natively computing allocation statistics for the UI, the `_compute_leaves` loops through a pre-fetched `data_days` structure and incorrectly extracts the calculation metrics by matching the `holiday_status.name` string via a list comprehension lookup index (`item[0]`).
https://github.com/odoo/odoo/blob/73d73c5c6606e0b34c754bfc4de035840951dd3b/addons/hr_holidays/models/hr_leave_type.py#L288-L294
If Time Off Type A and Time Off Type B share the name 'Generic Leave', the list comprehension evaluates sequentially and forcefully maps the dictionary of whichever version structurally sits first in the memory sequence directly onto both overlapping identifiers simultaneously!
Solution:
---------------------------------------
Directly match records using their unique ID.
This ensures that each database record always retrieves its own correct data, preventing any mix-up or accidental sharing of values between records that may have the same name.
opw-6105759
Forward-Port-Of: odoo/odoo#264104
Forward-Port-Of: odoo/odoo#261680This update fixes an issue where the product carousel displayed fewer than 16 products when a product had over 256 variants. The previous fix was a workaround that increased search limits. Now, the system correctly handles products with a large number of variants, ensuring a complete and accurate product carousel display. This improves the user experience for browsing products with many options.
Original PR description
# How to reproduce - Create a Product with more than 256 variants - Publish it to the website - Go to the website and add a Product Carousel - Set it to display newest products & hide variants # The…
# How to reproduce - Create a Product with more than 256 variants - Publish it to the website - Go to the website and add a Product Carousel - Set it to display newest products & hide variants # The problem Fewer than 16 products are displayed # Cause This issue was already adressed by this commit : https://github.com/odoo/odoo/pull/195857 But because of limitations for specifically the "Newest Products" filter (cf. original commit message), the fix was only a workaround. Indeed, it increased the search limit to 256 before filtering out the variants, which caused problems when there was more than 256 variants. But since then, big changes made in 19.0 has allowed us to implement a better fix : https://github.com/odoo/odoo/commit/e3b062e5d3820 # Proposed Solution Since we can now pass the model in the options : https://github.com/odoo/odoo/blob/b5069328734e623c12b0de50a177d501f7f0c995/addons/website/models/website_snippet_filter.py#L90 We give "product.template" when the `hide_variants` option is enabled and we filter on products. This allows use to remove the whole workaround that needed increase the limit on product searchs then getting their templates. A recent commit blocks passing "product.template" since it does not have a dedicated snippet filter : https://github.com/odoo/odoo/pull/257208/changes/8e264ae4ea6ae16bbd410ac384733ff8759938a6 But in the commit message, they mention that this targets snippet in single-record mode, which is not our case. So, we move the logic to only be applied for single-record filters opw-6054059 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260340
This fix resolves an issue where generating closing entries in the Inventory Valuation view incorrectly calculated values when multiple companies were selected. The update ensures that the generated account move lines accurately reflect the inventory valuation based on the selected main company, preventing mismatched balances.
Original PR description
**Problem:** In view Inventory valuation, generate entry doesn't work when multiple companies are selected. In the view only the main company matters. That means that even if multiple companies are…
**Problem:** In view Inventory valuation, generate entry doesn't work when multiple companies are selected. In the view only the main company matters. That means that even if multiple companies are selected, only the stock variation lines related to the main company selected are displayed (which is expected). But if you then click on 'generate entry' the account move lines created will have wrong values (not matching the values appearing in the view) **Steps to reproduce:** - create 2 new companies (to have clean accounting) - create a warehouse for both companies - for both comp, in settings for the 'fiscal localization' set Package : Generic Chart of account, if not already set (to have account journals). From company 1 : - create a storable prod with avco perpetual category - confirm PO for 2 @ 10, receive - bill only 1 @ 10 From company 2: - make sure the category is also perpetual average from this other company - confirm PO for 2 @ 50, receive, don't bill Notice how from the 'Inventory Valuation' view, rightfully, only the main company matters (no matter what other comp are selected): - If main comp is comp 1 there is stock variation lines for amount of 10 (which is expected because we have 20 in stock and only 10 in stock valuation account) - If main comp is comp 2 there is stock variation lines for amount of 100 (which is expected because we have 100 in stock and only 0 in stock valuation account) With comp 1 and 2 selected and comp 1 as main company: - click on 'Generate Entry' **Current behavior:** - both line have a balance of 110 **Expected behavior:** - they should have a balance of 10 as we saw on the 'inventory valuation' view **Cause of the issue:** To generate the data from the 'inventory valuation' view, inside _get_report_data() we call stock_value() and stock_accounting_value() to compare values from inventory and value from accounting. https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/report/stock_valuation_report.py#L36-L37 stock_value() sums total_value() of each product in the valued accounts https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L90-L94 Whereas stock_acounting_value(), sums the balance of each account move line of each valuation account https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L112-L114 All of this is related to the main company because we call _get_report_data() with context 'allowed_company_ids' set to only the main company https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/report/stock_valuation_report.py#L13 But when we click on generate entry, _get_stock_valuation_account_vals() is called with no context modification to 'allowed_company_ids' so when we call stock_value(), https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L238-L239 total_value will be based on both company https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L92 Note that stock_accounting_value() is still rightfully based only on main company because we use self.id in the domain https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L105-L108 opw-6168699 Forward-Port-Of: odoo/odoo#263946 Forward-Port-Of: odoo/odoo#262776
This update corrects a bug in the French Intrastat export process. Previously, supplementary unit data for products with CN codes wasn't being correctly included in the DEBWEB2 XML file. This fix ensures accurate reporting of product quantities for Intrastat purposes, preventing potential reporting discrepancies.
Original PR description
Steps to reproduce 1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set…
Steps to reproduce
1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set `intrastat_supplementary_unit_amount` on it.
2. Post EU customer invoices for that product.
3. Export the DEBWEB2 XML from the Intrastat report.
Issue
The FR export collapses engine rows a second time in `_group_items`, because the DEBWEB2 format groups more aggressively than the SQL. The aggregator only declares `value` and `weight`: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/models/account_intrastat_report.py#L308-L313 Items are then rebuilt as `dict(zip(grouping_key, key_tuple)) | grouped_item_values`. `SU_code` survives (it is in the grouping key), but the numeric `supplementary_units` is in neither side and is silently dropped as soon as two engine rows merge. The template then skips the element because of its `t-if="item.get('supplementary_units')"` guard: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/data/intrastat_export.xml#L61
opw-6139657
Forward-Port-Of: odoo/enterprise#117357
Forward-Port-Of: odoo/enterprise#117033This update resolves an issue preventing Envia deliveries in Chile. The problem stemmed from a mismatch between Odoo's state code representation and Envia's API requirements. A recent update to Chile's official state codes was not reflected in the system's mapping, causing delivery errors. This fix ensures accurate address data is sent to Envia, enabling successful deliveries.
Original PR description
### Steps to reproduce: - Install delivery_envia - Website > Configuration > eCommerce > Delivery Methods > Envia - Enable the delivery method, sync the carrier and Publish it - With a portal user >…
### Steps to reproduce:
- Install delivery_envia
- Website > Configuration > eCommerce > Delivery Methods > Envia
- Enable the delivery method, sync the carrier and Publish it
- With a portal user > Shop > Add any product to your cart > Checkout
- Register an address a valid 'Chile' address and confirm say:
'street and Number': Avenida Providencia 1432, Depto 402
'city': Santiago 'zip': 8320000
'country': Chile 'state': Metropolitana
#### > Envia Error: Invalid Option - String is too long at #->properties:destination
### Cause of the issue:
The problem is caused by the fact that Envia's api expects a 2-3 digits to represent state codes: https://docs.envia.com/reference/state-by-code
The mapping from Odoo's code state representation to envia's one is expected ot be performed by this mapping:
https://github.com/odoo/enterprise/blob/75cba6d5a88ebc4e0f35040a173ac1c443638daf/delivery_envia/models/envia_request.py#L27-L43 when the address is converted here:
https://github.com/odoo/enterprise/blob/75cba6d5a88ebc4e0f35040a173ac1c443638daf/delivery_envia/models/envia_request.py#L535-L542 That being said, the `Chile`'s code states of have been changed in [6694a3942c58ff1a56c9e4b36edbe126dd1e66f8](https://github.com/odoo/odoo/commit/6694a3942c58ff1a56c9e4b36edbe126dd1e66f8) to match the official Iso but not in the Envia's mapping leading a failling match keeping the 4 charracter long `CL-RM` of the `Metropolitan` state provided in to the Envia's api as address data.
opw-6210007
Forward-Port-Of: odoo/enterprise#117280This update resolves a crash that occurred when users switched to edit mode while an event registration modal was open. The fix ensures the modal is properly cleaned up after the transition, preventing errors related to accessing the modal's style properties. This improves stability and prevents unexpected application behavior.
Original PR description
Steps to reproduce: =================== 1. Go to Event, open an event page 2. Click "Register" & Select a ticket and confirm 3. Switch to edit mode => crash. Cause: ====== The cleanup callback called…
Steps to reproduce: =================== 1. Go to Event, open an event page 2. Click "Register" & Select a ticket and confirm 3. Switch to edit mode => crash. Cause: ====== The cleanup callback called `hide()` followed immediately by `dispose()`. Bootstrap's `hide()` is asynchronous — it registers a `transitionend` callback that fires `_hideModal()` after the CSS transition. `dispose()` nullifies `this._element` synchronously via `BaseComponent`, so when the `transitionend` fires and `_hideModal()` tries to access `this._element.style`, it crashes with: TypeError: Cannot read properties of null (reading 'style') This happened when switching to edit mode while the event registration modal was open: the `public.interactions` service stopped the interaction, triggering the cleanup. Solution: ========= Listen for `hidden.bs.modal` (fired at the end of `_hideModal`) and only `dispose()` inside that handler, ensuring `_element` is still valid throughout the transition. task-6133395 Forward-Port-Of: odoo/odoo#264365
This update corrects a calculation error related to non-investment savings schemes (NISS) for employees in Belgium. The change ensures that NISS contributions are accurately reflected in payroll calculations for Belgian businesses using the Enterprise module. This improves the accuracy of financial reporting and compliance for our Belgian clients.
This update resolves an issue where multi-company orders were incorrectly assigning fiscal positions, leading to 'incompatible companies' errors. The fix ensures the sale order's company is used when calculating the fiscal position, guaranteeing accurate accounting and order confirmation. This improves order processing reliability in our multi-company setup.
Original PR description
Issue: --- Due to this issue, in multi-company environment, wrong fiscal position might be assigned to the order, leading to `incompatible companies` error. Steps to reproduce: 1- On multi-company…
Issue: --- Due to this issue, in multi-company environment, wrong fiscal position might be assigned to the order, leading to `incompatible companies` error. Steps to reproduce: 1- On multi-company setup, assign a website to the second company. 2- Configure pickup method for second company. 3- Configure fiscal positions for both companies. 4- Setup auto invoice for second company. 5- Using public user, add a product to cart and checkout. 6- Use pickup method, and pay. The order is not confirmed. If you enable debug mode after payment, it will show an `incompatible companies` error. Cause: --- https://github.com/odoo/odoo/blob/43f5ceadbc1f7df9898c327bf65bffdbe9860c1c/addons/account/models/partner.py#L247-L279 `_get_fiscal_position` is using environment company to compute the fiscal position. However, `_compute_fiscal_position_id` causing the issue here is triggered inside `report_saleorder` template with user set as odoobot when trying to to send the confirmation. As a result, the odoobot company's fiscal position will be used causing this issue. Fix: --- We should ensure company from sale order is used by setting it as env company. opw-6186296 Forward-Port-Of: odoo/odoo#264123
This update fixes an issue where payroll account lines were incorrectly merging employee data, leading to inaccurate allocation of funds across different analytic accounts. The change ensures that each employee's specific analytic distribution is accurately reflected, preventing data loss and maintaining correct financial reporting. This update improves the accuracy of payroll accounting.
Original PR description
Steps to reproduce 1. Enable "Batch Account Move Lines" in the Payroll settings. 2. Configure two employees' versions with an analytic distribution on the same analytic account but with different…
Steps to reproduce
1. Enable "Batch Account Move Lines" in the Payroll settings.
2. Configure two employees' versions with an analytic distribution on the
same analytic account but with different percentages (e.g. {acc: 50}
for the first employee and {acc: 70} for the second).
3. Generate a payslip run containing both employees and validate it.
Issue
The generated account move aggregates the two payslips into a single
line whose analytic_distribution matches only the last employee being
processed; the other employee's percentage is silently lost.
`_get_existing_lines` decides whether an incoming line can merge into an
already accumulated one. When the incoming line has an analytic
distribution, the merge condition delegates to
`_check_partially_matching_accounts`:
https://github.com/odoo/enterprise/blob/e4a1326c7a8a74da7970aeaa9900c19d01634e31/hr_payroll_account/models/hr_payslip.py#L254-L271
https://github.com/odoo/enterprise/blob/e4a1326c7a8a74da7970aeaa9900c19d01634e31/hr_payroll_account/models/hr_payslip.py#L273-L283
That helper returns True as soon as any analytic account of the new
line appears anywhere in the existing line's distribution dict, without
comparing percentages. Two distributions such as {acc: 50} and
{acc: 70} share the same account, so the helper returns True, the
lines are merged, and whichever distribution ends up on the merged line
overwrites the other — the total amount is correct but the analytic
split is wrong.
The logic introduced in commit https://github.com/odoo-dev/enterprise/commit/e40a3166286a6bc546e9543b935233d2a110dc52 successfully addressed merging for rule-level distributions
with composite keys (e.g., {'13,7,12': 40}). However, that implementation is overly inclusive for employee-specific distributions.
It fails to differentiate between cases where the same analytic account is utilized across various employees but with different percentage allocations.
Because it only checks for an account overlap rather than a perfect distributional match, it incorrectly aggregates distinct financial dimensions into a single journal line
Solution
Compare the full analytic_distribution dict by strict equality. Lines
merge only when the distribution is identical (same keys AND same
percentages), keeping the batch feature anonymizing identically
configured employees while preserving one line per distinct
distribution.
opw-6102508
Forward-Port-Of: odoo/enterprise#114156This update ensures the reprint button is consistently visible and functional on all devices sharing the same Point of Sale session. Previously, the reprint button was only available on the device that initially sent the order to the preparation printer. This change improves the user experience and streamlines order fulfillment.
Original PR description
When sending an order to a preparation printer, the reprint button was invisible on any device other than the one that originally sent the order. This happened because `lastPrints` was stored in the order's `uiState`, which is local to each device. Moving it to `last_order_preparation_change` — which is shared across devices in the same session — fixes the issue. The reprint button is now visible and functional on all devices sharing the same session. --- Task: https://www.odoo.com/odoo/project/1737/tasks/6196913 Forward-Port-Of: odoo/odoo#263094
This update ensures that when reserving stock with packaged items, the system correctly considers the total quantity available, regardless of how it's divided into full packaging units. Previously, large stock levels were incorrectly limiting reservation quantities. This fix improves the accuracy of stock availability calculations and prevents over-reservation issues.
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#263114
Forward-Port-Of: odoo/odoo#257342This update fixes an issue where list markers with trailing empty lines weren't correctly styled, and ensures font sizes are applied consistently across list items regardless of how they were created (inline styles, dropdowns, or links). It also resolves conflicts between background and font colors within lists.
Original PR description
### Steps to reproduce: **Issue 1:** - Create a list with multiple items and leave the last item empty. - Press Ctrl + A to select all content. - Apply a text color from the toolbar. - The list…
### Steps to reproduce: **Issue 1:** - Create a list with multiple items and leave the last item empty. - Press Ctrl + A to select all content. - Apply a text color from the toolbar. - The list marker of the last item does not receive the color. **Issue 2:** - Create a list and type some text. - Press Ctrl+A to select all. - Apply a font size via the font-size input (inline style=`font-size: ...`). - Then apply a font size via the font-size dropdown (class-based). - Font size from the dropdown is not applied. **Issue 3:** - Create a list item and type some text. - Convert the text into a link. - Copy the link. - Press Enter and paste the link. - Select the entire list using the mouse. - Apply font size & observe that font size is not applied to some list items. **Issue 4:** - Go to Todo and create a list. - Select all items (Ctrl + A). - Apply a background color class from the toolbar. - Apply a font color using inline styling. - Observe that the font color is not visible. ### Description of the issue/feature this PR addresses: - Full-selection detection relied on Range.isPointInRange() checks on list item leaf nodes. When a list item ended with a trailing empty line, the selection often stopped on the `<li>` element and did not include the `<br>` placeholder. As a result, such list items were not considered fully selected when applying text color, and their markers remained unstyled. - Applying a font-size class on a fully-selected list item could leave existing inline font-size on list item, so new class didn’t take effect. - Creating links inside list items & repeated copy-paste operations left empty text nodes (feff cleanup). Manual selection doesn't include these nodes, `areNodeContentsFullySelected` reports that list item is not fully selected. As a result, some list items were not considered fully selected, and font size was not applied. - Background color `(bg-*)` classes also define a color property. When a font color is applied, the color is set on the `<li>`, but the nested `font.bg-*` element’s color takes precedence, causing the applied font color to be overridden. ### Desired behavior after PR is merged: - List items with trailing empty line are now treated as fully selected, even when selection ends before the `<br>` placeholder. - Clear any existing font-size styles on the list item before applying the new font-size class, so the dropdown font size applies correctly. - Empty text nodes are removed before applying font size, ensuring full list item selection and consistent font-size application. - When a list item (li) has a text color (inline style or text-* class), and nested font element has only a background color class then font element now inherits the color from the li. task - 5454639 Forward-Port-Of: odoo/odoo#264586 Forward-Port-Of: odoo/odoo#241827
This update clarifies the display of extra prices when customers select combo items in the POS system. Previously, customers were confused about additional costs, leading to inquiries about 'too much' charges. This change ensures transparent pricing and avoids customer confusion, improving the overall checkout experience.
Original PR description
The display for the extra price during the combo selection was not very clear. The customer were not aware of the additional cost that were applied when choosing some elements that were not included but extra. This led to customer asking cashier if there was a problem because they were paying "too much" when the computation was actually correct but not clear enough. task-id: 6142095 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261264 Forward-Port-Of: odoo/odoo#260705
This update fixes an inconsistency in how leave durations are calculated for employees using credit time calendars. Previously, the system miscalculated leave times when attendance was split between regular and credit time periods. This change ensures accurate leave duration tracking, particularly for employees with complex work schedules.
Original PR description
purpose: when creating leaves for employees with credit time calendar, the duration computation is differnet with similar configrations (regular attendance in the morning then credit time in the afternoon and the opposite) backporting the fix done in this commit which overrides `_work_intervals_batch` to exclude intervals that count as absense: https://github.com/odoo/odoo/pull/239420/changes/0168eb28d8986969c30a08ef41de8eff9aaa765a task-id: 6212942 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a bug that prevented users from selecting additional Service-type Sale Order Lines (SOLs) when creating timesheets linked to Sales Orders. The fix ensures that timesheets can now correctly associate with all relevant SOLs, regardless of the default SOL selection. This improves the accuracy and usability of timesheet reporting.
Original PR description
Steps to reproduce: - Install sale_timesheet - Create a Sales Order with multiple Service-type Sale Order Lines - Create a timesheet from the Sales Order stat button or from the Timesheets app Issue: It is not possible to select another SOL. If the default SOL is removed. Cause: The so_line domain does not include SOLs with `qty_delivered_method = 'timesheet'`. Fix: Include timesheet SOLs in the domain. Task-5969200
This update corrects a bug where the 'Purchase Orders' button disappeared when changing an Analytic Account's plan. The fix adjusts how the system identifies purchase orders linked to analytic accounts, ensuring the button remains visible regardless of the plan setting. This ensures users can always access purchase order information related to their accounts.
Original PR description
# How to reproduce - Enable the analytic accounting in the settings - Create a PO - Add a PO line - Set the Analytic Distribution of that PO line to an Analytic Account of your choice - Confirm the…
# How to reproduce
- Enable the analytic accounting in the settings
- Create a PO
- Add a PO line
- Set the Analytic Distribution of that PO line to an Analytic Account of your choice
- Confirm the PO
- Create a Vendor Bill from that PO and confirm the VB
- Go to the Analytic Account chosen before
- Change the Plan of that Analytic Account
# The problem
When the Plan is not set to the "Project Plan", the Purchase Orders smart button disappears
# Why
The Purchases Orders smart button is invisible if the variable purchase_order_count is equal to 0. That field is computed by a function that does a search with the following domain :
```py
[('order_line.invoice_lines.analytic_line_ids.account_id', '=', account.id)]
```
When we change the Plan of the Analytic Account, analytic_line_ids.account_id is set to NULL, so the search return nothing.
Why is that field set to NULL ?
Well, to reference its plan, an Analytic Line does not use a python-defined field. In fact, each time a new Analytic Plan is added to the database, a new column is added to the Analytic Line model. That column's name is x_plan{plan.id}_id or, for the specific case of the "Project Plan", it is account_id
When the Plan of an Analytic Account is changed, it takes every Analytic Line associated with that Plan and switch which column containing the id of the Analytic Account.
Take for exemple the following Analytic Line :
```
(account_id = NULL, x_plan2_id = NULL, x_plan3_id = 1)
```
When the associated Analytic Account's Plan is changed to the "Project Plan", it becomes :
```
(account_id = 1, x_plan2_id = NULL, x_plan3_id = NULL)
```
So, we need to adapt to search so that it uses the right plan's name.
opw-5897037
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#263652
Forward-Port-Of: odoo/odoo#248236This update fixes an issue where the total working hours weren't being displayed correctly in the Planning Gantt view when the view wasn't grouped by resources. The change ensures accurate working hour calculations are reflected in the total row, regardless of grouping settings, improving planning accuracy.
Original PR description
Issue: ---------------------------------------- In the Planning Gantt view when we don't group by resources, the total row is not considering the working hours. Steps to reproduce:…
Issue: ---------------------------------------- In the Planning Gantt view when we don't group by resources, the total row is not considering the working hours. Steps to reproduce: ---------------------------------------- - Open Planning - Remove the default group by resources - Have at least a planning slot for a non-flexible employee - The total row doesn't take the working schedule into account Cause: ---------------------------------------- Since [an improvement,](https://github.com/odoo/enterprise/commit/cc35e1a4729453e4f788034a94402ab048eadfcb) the working hours data in given to the `PlanningGanttRenderer` through the progress bars data. This is an issue because the progress bars are only there if we group by resources. ([src](https://github.com/odoo/enterprise/blob/423ab064847dd41d36778a812390e3bec53ba4dc/planning/models/planning_slot.py#L2669-L2678)) Solution: ---------------------------------------- In this commit we partially revert the commit adding the working intervals in the progress bars. Instead of doing it in `_gantt_progress_bar_resource_id()` we create a new method `_get_gantt_planning_data()` which is called directly in `get_gantt_data()` and returns useful information even when there are no progress bars. opw-5507063 Forward-Port-Of: odoo/enterprise#116824 Forward-Port-Of: odoo/enterprise#112522
This update fixes inconsistencies in the XML structure used for Swedish payments (l10n_se_bban). Specifically, it ensures the correct format for bank identification codes (BIC) and addresses a known issue with bank account data, improving compatibility with Swedish banking systems. This ensures accurate and reliable payment processing.
Original PR description
Here is few fixes added to the swedish iso 20022 XML: - CdtrAgt seems to be always mandatory, change the condition in `_skip_CdtrAgt` to always use the CdtrAgt if payment_method is iso20022_se - The `_is_se_bban` is too restrictive, this should be always True when payment method is swedish iso - The `FinInstnId` node can either contain BIC or ClrSysMmbId. But as ClrSysMmbId seems to change from one bank to another, it's more relevant to always use the BIC. opw-5395736 Forward-Port-Of: odoo/enterprise#114662
This update resolves a restriction in the l10n_mx_edi module, allowing credit notes (out-refunds) to utilize Payment Policies (PPD) as required by Mexican tax regulations (SAT). Previously, this functionality was unavailable, creating a discrepancy between Odoo and the SAT portal. This change ensures compliance and simplifies credit note processing.
Original PR description
Currently, credit notes cannot be PPD (payment_policy), however, SAT portal allows it. **STEP TO REPRODUCE** 1. Install the l10n_mx_edi module. 2. Create an invoice with PPD (either changing it or through payment terms). 3. After send CFDI, generate a credit note and try to set PPD **FIX** Allow move_type = 'out_refund' to be PPD. Task-6049654 Forward-Port-Of: odoo/enterprise#114886
13 changes
Resolved issues and error corrections
This update fixes an inconsistency in how rental prices are calculated when dealing with time-zoned dates. Previously, using relativedelta on UTC dates resulted in incorrect price calculations. Now, the system accurately calculates rental durations based on the original time zones of the start and end dates, ensuring consistent pricing across different time zones.
Original PR description
Relativedelta on UTC dates or time-zoned dates doesn't return the same result. In order to calculate consistent prices (price for 1 month in December = price for 1 month in January), we need to work…
Relativedelta on UTC dates or time-zoned dates doesn't return the same result. In order to calculate consistent prices (price for 1 month in December = price for 1 month in January), we need to work on time-zoned dates. Example: Consider a website in UTC+1 (Brussels timezone DST off). And a rental from the 01/12/2025 to the 31/12/2025 = by design, from the 01/01/2025 00h00 (start_date) to the 31/12/2025 23h59 (end_date). Converted in UTC for the back-end, we have: from the 30/11/2025 23h00 to the 31/12/2025 22h59. relativedelta(end_date, start_date) = time between the 2 dates is calculated as follow: 30/11/2025 23h00 + 1 month = 30/12/2025 23h00 +23h59 = 31/12/2025 22h59. Time difference = 1 month, 23 hours, 59 minutes. Price = 2 months. Consider a second rental from the 01/01/2026 to the 31/01/2026. 31/12/2025 23h00 + 30 days = 30/01/2026 23h + 23h59 = 31/01/2026 22h59. Time difference = 30 days, 23 hours, 59 minutes. Price = 1 month. opw-5130762 Forward-Port-Of: odoo/enterprise#114212 Forward-Port-Of: odoo/enterprise#98571
This update resolves a bug that caused incorrect redirects to the receipt screen when using eWallet with automatic receipt printing and skipping the preview screen in Point of Sale. The removal of a redundant property ensures the correct feedback screen is displayed, improving the user experience for eWallet transactions.
Original PR description
- Remove unused `paymentMethodId` prop from FeedbackScreen which caused incorrect redirect to receipt screen instead of feedback screen when using eWallet with "Automatic Receipt Printing" and "Skip Preview Screen" enabled. - The prop `paymentMethodId` is already removed in versions > `19.0`. task-id: 6008245 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252176
This update addresses an issue where customers could have orders automatically confirmed when a gift card fully covered a shopping cart. Now, Odoo will require the standard checkout step to be completed, even if a gift card brings the total to zero, ensuring accurate order processing and preventing potential errors.
Original PR description
**Before this commit** If a gift card balance fully covers a shopping cart containing multiple events, Odoo auto-confirms the order as soon as the last event is added, skipping the final checkout step. **After this commit** Sale orders will no longer be automatically confirmed when a customer registers for a paid event, even if an applied gift card brings the total balance to zero. opw-5896626 Forward-Port-Of: odoo/odoo#264599 Forward-Port-Of: odoo/odoo#246629
This update corrects a technical issue in the French Intrastat export process. Previously, crucial quantity data related to supplementary units wasn't being included in the DEBWEB2 XML file, leading to incomplete reporting. This fix ensures accurate Intrastat reporting for products with supplementary units, improving data integrity.
Original PR description
Steps to reproduce 1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set…
Steps to reproduce
1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set `intrastat_supplementary_unit_amount` on it.
2. Post EU customer invoices for that product.
3. Export the DEBWEB2 XML from the Intrastat report.
Issue
The FR export collapses engine rows a second time in `_group_items`, because the DEBWEB2 format groups more aggressively than the SQL. The aggregator only declares `value` and `weight`: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/models/account_intrastat_report.py#L308-L313 Items are then rebuilt as `dict(zip(grouping_key, key_tuple)) | grouped_item_values`. `SU_code` survives (it is in the grouping key), but the numeric `supplementary_units` is in neither side and is silently dropped as soon as two engine rows merge. The template then skips the element because of its `t-if="item.get('supplementary_units')"` guard: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/data/intrastat_export.xml#L61
opw-6139657
Forward-Port-Of: odoo/enterprise#117357
Forward-Port-Of: odoo/enterprise#117033This update resolves a crash that occurred when users switched to edit mode while an event registration modal was open. The fix ensures the modal is properly cleaned up after the transition, preventing errors related to accessing the modal's style properties. This improves stability and prevents unexpected application behavior.
Original PR description
Steps to reproduce: =================== 1. Go to Event, open an event page 2. Click "Register" & Select a ticket and confirm 3. Switch to edit mode => crash. Cause: ====== The cleanup callback called…
Steps to reproduce: =================== 1. Go to Event, open an event page 2. Click "Register" & Select a ticket and confirm 3. Switch to edit mode => crash. Cause: ====== The cleanup callback called `hide()` followed immediately by `dispose()`. Bootstrap's `hide()` is asynchronous — it registers a `transitionend` callback that fires `_hideModal()` after the CSS transition. `dispose()` nullifies `this._element` synchronously via `BaseComponent`, so when the `transitionend` fires and `_hideModal()` tries to access `this._element.style`, it crashes with: TypeError: Cannot read properties of null (reading 'style') This happened when switching to edit mode while the event registration modal was open: the `public.interactions` service stopped the interaction, triggering the cleanup. Solution: ========= Listen for `hidden.bs.modal` (fired at the end of `_hideModal`) and only `dispose()` inside that handler, ensuring `_element` is still valid throughout the transition. task-6133395 Forward-Port-Of: odoo/odoo#264365
This update ensures Odoo correctly sets the `toStateCode` field for SEZ transactions when generating e-waybills. Previously, this was a source of API errors, particularly for export and supply transactions. By enforcing the required `toStateCode` of 99, this fix ensures compliance with e-waybill regulations and prevents disruptions to shipping.
Original PR description
For SEZ transactions, the e-waybill API requires `toStateCode` to be set to 99. Previously, this value was not enforced, leading to API errors: - 373 for export transactions - 641 for supply and CKD/SKD/lots supply This fix updates the logic to derive `toStateCode` based on the invoice's GST treatment. When the transaction is identified as SEZ, `toStateCode` is correctly set to 99, ensuring compliance with e-waybill requirements and preventing API failures. task-6117694 Forward-Port-Of: odoo/odoo#259327
This update resolves an issue where multi-company orders were incorrectly assigning fiscal positions, leading to 'incompatible companies' errors. The fix ensures the sale order's company is used when calculating the fiscal position, guaranteeing accurate accounting and order confirmation. This improves order processing reliability in our multi-company setup.
Original PR description
Issue: --- Due to this issue, in multi-company environment, wrong fiscal position might be assigned to the order, leading to `incompatible companies` error. Steps to reproduce: 1- On multi-company…
Issue: --- Due to this issue, in multi-company environment, wrong fiscal position might be assigned to the order, leading to `incompatible companies` error. Steps to reproduce: 1- On multi-company setup, assign a website to the second company. 2- Configure pickup method for second company. 3- Configure fiscal positions for both companies. 4- Setup auto invoice for second company. 5- Using public user, add a product to cart and checkout. 6- Use pickup method, and pay. The order is not confirmed. If you enable debug mode after payment, it will show an `incompatible companies` error. Cause: --- https://github.com/odoo/odoo/blob/43f5ceadbc1f7df9898c327bf65bffdbe9860c1c/addons/account/models/partner.py#L247-L279 `_get_fiscal_position` is using environment company to compute the fiscal position. However, `_compute_fiscal_position_id` causing the issue here is triggered inside `report_saleorder` template with user set as odoobot when trying to to send the confirmation. As a result, the odoobot company's fiscal position will be used causing this issue. Fix: --- We should ensure company from sale order is used by setting it as env company. opw-6186296 Forward-Port-Of: odoo/odoo#264123
This fix resolves an issue where payroll account merges incorrectly combined employee payments, leading to inaccurate analytic distribution reporting. The update ensures that each employee's specific analytic distribution is correctly applied, preventing data aggregation and maintaining accurate financial reporting. This improves the reliability of payroll accounting data.
Original PR description
Steps to reproduce 1. Enable "Batch Account Move Lines" in the Payroll settings. 2. Configure two employees' versions with an analytic distribution on the same analytic account but with different…
Steps to reproduce
1. Enable "Batch Account Move Lines" in the Payroll settings.
2. Configure two employees' versions with an analytic distribution on the
same analytic account but with different percentages (e.g. {acc: 50}
for the first employee and {acc: 70} for the second).
3. Generate a payslip run containing both employees and validate it.
Issue
The generated account move aggregates the two payslips into a single
line whose analytic_distribution matches only the last employee being
processed; the other employee's percentage is silently lost.
`_get_existing_lines` decides whether an incoming line can merge into an
already accumulated one. When the incoming line has an analytic
distribution, the merge condition delegates to
`_check_partially_matching_accounts`:
https://github.com/odoo/enterprise/blob/e4a1326c7a8a74da7970aeaa9900c19d01634e31/hr_payroll_account/models/hr_payslip.py#L254-L271
https://github.com/odoo/enterprise/blob/e4a1326c7a8a74da7970aeaa9900c19d01634e31/hr_payroll_account/models/hr_payslip.py#L273-L283
That helper returns True as soon as any analytic account of the new
line appears anywhere in the existing line's distribution dict, without
comparing percentages. Two distributions such as {acc: 50} and
{acc: 70} share the same account, so the helper returns True, the
lines are merged, and whichever distribution ends up on the merged line
overwrites the other — the total amount is correct but the analytic
split is wrong.
The logic introduced in commit https://github.com/odoo-dev/enterprise/commit/e40a3166286a6bc546e9543b935233d2a110dc52 successfully addressed merging for rule-level distributions
with composite keys (e.g., {'13,7,12': 40}). However, that implementation is overly inclusive for employee-specific distributions.
It fails to differentiate between cases where the same analytic account is utilized across various employees but with different percentage allocations.
Because it only checks for an account overlap rather than a perfect distributional match, it incorrectly aggregates distinct financial dimensions into a single journal line
Solution
Compare the full analytic_distribution dict by strict equality. Lines
merge only when the distribution is identical (same keys AND same
percentages), keeping the batch feature anonymizing identically
configured employees while preserving one line per distinct
distribution.
opw-6102508
Forward-Port-Of: odoo/enterprise#114156This update resolves a bug that prevented users from opening the payroll module when creating overtime attendance records. The fix addresses an issue where the system was receiving duplicate overtime data, causing an error. This ensures payroll processing functions correctly for all attendance scenarios.
Original PR description
Steps to reproduce: - Install `hr_work_entry_attendance` module - Create an Employee and set contract date - Attendance > Create attendance for Employee(eg: [image](https://www.awesomescreenshot.com/image/58801595?key=ecc9a2f5ec51cb569432e5bf580540f9)) - Add a new line in Overtime Details (eg: [image](https://www.awesomescreenshot.com/image/58801650?key=f5a886217299bca8bbece27839377bf4)) - Try to open `Payroll` Traceback: `ValueError: Expected singleton: hr.attendance.overtime.line(309, 310)` At [1], this error occurs because we are getting multiple records of `hr.attendance.overtime.line` in `overtime_intervals`. [1]: https://github.com/odoo/enterprise/blob/62f59f87a513a86a61f871ca743e7f7b04926a82/hr_work_entry_attendance/models/hr_version.py#L82 sentry-7251235434
This update resolves an issue where intercompany invoices were flagged with an incorrect tax validation error. The fix ensures that taxes are correctly recalculated when processing invoices between companies with different fiscal positions, improving the accuracy of intercompany accounting. This prevents disruptions to cross-border transactions.
Original PR description
**Steps to reproduce:** * Install the *Accounting* module. * Install localisation modules for two different regions: * *Belgium* (**l10n_be**) * *Luxembourg* (**l10n_lu**) * Configure two companies,…
**Steps to reproduce:** * Install the *Accounting* module. * Install localisation modules for two different regions: * *Belgium* (**l10n_be**) * *Luxembourg* (**l10n_lu**) * Configure two companies, each assigned to one of the above regions. * Create fiscal positions: * In the Belgium company, create a fiscal position for Luxembourg. * In the Luxembourg company, create a fiscal position for Belgium. * Go to *Accounting > Configuration > Settings*. Enable *Inter-Company Transactions*. Enable synchronization of *Vendor Bills and Invoices* for both companies. * Create an invoice in the Luxembourg company. Select a partner belonging to the Belgium company. Add a product with applicable taxes. **Observed behavior:** * A validation error is raised: 'This entry contains taxes that are not compatible with your fiscal position. Please check the country set in the fiscal position and in your tax configuration.' **Cause:** * During intercompany bill creation, a foreign fiscal position is applied before recomputing taxes. * If no mapped foreign taxes exist, the system keeps domestic purchase taxes. * This leads to a mismatch between taxes and fiscal position, triggering the validation error. **Fix:** * Add a safeguard in *_inter_company_create_invoices()*. * After *_inter_company_sync_invoice_line_taxes()* recomputes taxes, *_inter_company_has_incompatible_fiscal_position_taxes()* checks whether the fiscal position is incompatible. * If incompatible, the fiscal position is removed and taxes are recomputed without it. opw-6103671 Forward-Port-Of: odoo/enterprise#117450 Forward-Port-Of: odoo/enterprise#115085
This update fixes an error in the Italian Annual VAT Report that was incorrectly calculating the balance amount for line VF25. The fix ensures the report accurately reflects the total taxable base as required by Italian tax regulations. This ensures compliance with Italian tax reporting standards.
Original PR description
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive…
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive operations, the report erroneously mixes tax amounts into the balance column. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to Tax Report and visualize the Annual Tax Report (IT) 3. Go to VF VAT Report 4. See the VF25 is mixing taxes and balances ### Cause of the issue: The root cause lies in the aggregation_formula definition for the tax_annual_report_line_VF25 record. The formula was incorrectly configured to aggregate the .tax expressions for lines VF1 to VF13 (VF1.tax + VF2.tax + ...) instead of their respective .balance expressions, while correctly using .balance for the remaining lines (VF17 to VF24). https://github.com/odoo/odoo/blob/878c08cf522a3278b4e6ff5f3d18444989e9998d/addons/l10n_it/data/tax_report/annual_report_sections/vf.xml#L286-L299 It's just a typo in this commit: https://github.com/odoo/odoo/pull/164064/changes/f292ba119d6376dbfb3c1fac4960c9c56a74d938 ### Reason to introduce the fix: From documentation https://www.agenziaentrate.gov.it/portale/documents/20143/9602686/IVA_ANNUALE_2026_istr.pdf/2a42fb92-1b76-229a-d0f5-06069d79b514?t=1768504755711 : > Rigo VF25, colonna 1, va indicato il totale degli imponibili determinato sommando gli importi riportati ai righi da VF1 a VF23, colonna 1, diminuito dell’importo di cui al rigo VF24. In colonna 2 va indicato il totale delle imposte determinato sommando gli importi delle colonne 2 dei righi da VF1 a VF13. opw-6172791 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264379
This update resolves a restriction in the l10n_mx_edi module that prevented credit notes (out-refunds) from using Payment Policy Defaults (PPD). Previously, the Mexican SAT portal required PPD for certain credit note types, but this functionality was not available within Odoo. This change aligns Odoo with SAT requirements, streamlining the process for Mexican businesses.
Original PR description
Currently, credit notes cannot be PPD (payment_policy), however, SAT portal allows it. **STEP TO REPRODUCE** 1. Install the l10n_mx_edi module. 2. Create an invoice with PPD (either changing it or through payment terms). 3. After send CFDI, generate a credit note and try to set PPD **FIX** Allow move_type = 'out_refund' to be PPD. Task-6049654 Forward-Port-Of: odoo/enterprise#114886
This update fixes a bug that caused remote meeting tabs to crash when the host ended a call. The change ensures that call action elements handle call disappearances gracefully, preventing errors and maintaining the existing user interface. This improves stability and reliability for users accessing meetings from multiple tabs.
Original PR description
**Steps to Reproduce:** - Start a new meeting (Host Tab). - Duplicate the tab or open the same meeting URL in another tab (remote tab). - In the remote tab, open the call menu (dropdown). - From the…
**Steps to Reproduce:** - Start a new meeting (Host Tab). - Duplicate the tab or open the same meeting URL in another tab (remote tab). - In the remote tab, open the call menu (dropdown). - From the host tab, disconnect/end the call. - Crashes on Remote Tab. **Current behavior before PR:** Before this PR, duplicating a meeting tab could leave the remote tab with a stale call action dropdown after the host ended the call. Since some action properties and handlers still assumed that selfSession and channel were always available, interacting with the dropdown could crash with errors. **Desired behavior after PR is merged:** After this PR, call action labels/classes defensively tolerate missing selfSession or channel references, and stale click handlers gracefully no-op when the call disappears mid-interaction. This prevents remote tab crashes during call teardown while preserving the existing UI behavior. task-[6191740](https://www.odoo.com/odoo/project/1519/tasks/6191740) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
1 change
Resolved issues and error corrections
This update resolves a limitation in the l10n_mx_edi module, allowing credit notes (out-of-funds) to be configured with Payment Policy Details (PPD) as required by the Mexican SAT portal. Previously, this configuration was restricted, causing potential issues with VAT refund processing. This change ensures compliance and streamlines the credit note generation process for Mexican businesses.
Original PR description
Currently, credit notes cannot be PPD (payment_policy), however, SAT portal allows it. **STEP TO REPRODUCE** 1. Install the l10n_mx_edi module. 2. Create an invoice with PPD (either changing it or through payment terms). 3. After send CFDI, generate a credit note and try to set PPD **FIX** Allow move_type = 'out_refund' to be PPD. Task-6049654 Forward-Port-Of: odoo/enterprise#114886
13 changes
Resolved issues and error corrections
This update resolves two issues impacting the website editor and donation functionality. First, it eliminates a potential infinite loop in the editor when undoing actions, ensuring a smoother user experience. Second, it corrects a bug where donation amounts weren't updating correctly after navigating back, guaranteeing accurate donation processing.
Original PR description
*:website, website_payment > Commit 1: [FIX] web_editor: prevent infinite bounce loop when clicking undo Steps to reproduce: 1. Click on a snippet without dragging it. 2. Notice that the "Drag…
*:website, website_payment > Commit 1: [FIX] web_editor: prevent infinite bounce loop when clicking undo Steps to reproduce: 1. Click on a snippet without dragging it. 2. Notice that the "Drag building blocks here" section starts bouncing. 3. Observe that a step is added to the history (Undo becomes available). 4. Click on Undo button. Issue: 1. The `o_catch_attention class` is repeatedly added and removed, creating unnecessary history steps in the editor. 2. No actual changes occur in the wrap area, yet the editor records history steps. 3. This leads to an infinite bounce loop when using Undo/Redo. Expected behavior: 1. The Undo button should not be activated. 2. Infinite bouncing should not occur. This PR prevents unnecessary history steps by disabling history tracking during this phase using `observerUnactive` and `observerActive`. This ensures that the editor does not record redundant changes, preventing infinite bounce loops. > Commit 2: [FIX] website_payment: fix donation amount not updating issue Steps to Reproduce: 1. Go to Website → Add a Donation snippet. 2. Enter a custom amount and click "Donate". You will be redirected to the donation/pay page. 3. Use the browser's back button to return to the previous page. 4. Change the amount in the custom amount field. 5. Click "Donate" again. - The old amount is still used instead of the new one. Expected Behavior: The donation amount should update correctly when changed. The issue occurs because clicking the "Donate Now" button appends a hidden value to the form snippet, which is then used in payment_form. When navigating back and selecting "Donate Now" again, a duplicate hidden value is added instead of replacing the previous one. This PR ensures that if a value already exists, it is replaced instead of being appended, resolving the issue. > Commit 3: [FIX] web_editor: fix dropdown options value Steps to reproduce: 1. Go to the website and drag and drop the form snippet. 2. Change the action to 'Subscribe to Newsletter'. 3. Click on multi-checkbox field to view its options. - Even after selecting an option, it remains in the dropdown, allowing multiple selections of the same option. Expected behaviour: - Once an option is selected, it should be removed from the dropdown. Solution: This PR removes the count from the display name, ensuring correct form behavior. task-4583314 Forward-Port-Of: odoo/odoo#234513 Forward-Port-Of: odoo/odoo#203454
This update resolves issues preventing Odoo IoT boxes from successfully upgrading to newer database versions. Specifically, the system now waits after the upgrade script before attempting a git checkout, and includes necessary packages like 'geoip2' to ensure a smooth Odoo service startup. This improves upgrade reliability and stability.
Original PR description
This commit fixes two issues with upgrading from old IoT box images to 19.1+ DBs: - The IoT box would try and start checking out with git at the same time as the upgrade script rebooted the system. This would leave the git branch as the DB version (e.g. 19.2) but with the files still being at 19.1. To fix this, we sleep after the script until we reboot. - On reboot, the IoT box would then git checkout to the new version anyways. However, it would not install apt packages, leaving the Odoo service unable to start because of a missing 'geoip2' package. To fix this, we simply include this package in the upgrade script. task-6217972 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264737
This update ensures Odoo correctly sets the `toStateCode` field for SEZ transactions when generating e-waybills. Previously, this was missing, causing API errors related to export and supply transactions. This fix ensures compliance with e-waybill regulations and prevents disruptions to these key business processes.
Original PR description
For SEZ transactions, the e-waybill API requires `toStateCode` to be set to 99. Previously, this value was not enforced, leading to API errors: - 373 for export transactions - 641 for supply and CKD/SKD/lots supply This fix updates the logic to derive `toStateCode` based on the invoice's GST treatment. When the transaction is identified as SEZ, `toStateCode` is correctly set to 99, ensuring compliance with e-waybill requirements and preventing API failures. task-6117694 Forward-Port-Of: odoo/odoo#259327
This update fixes an issue where HR leave requests with dual approval ('both') didn't send notifications to the designated responsible parties (e.g., Time Off Officer). The change ensures that notifications are consistently sent as intended, improving the accuracy and reliability of the leave request process. This prevents delays and ensures proper communication regarding leave approvals.
Original PR description
…cer') no fallback for responsible_ids
Issue:
When ('both','By Employee's Approver and Time Off Officer') is selected on a new HR Leave Type it does not fall back to the responsible_ids or “Notify HR”.
Steps:
1) Setup a neutralized outgoing mail server
2) install hr_holidays
3) make a new hr.leave.Type (Approval) with ('both','By Employee's Approver and Time Off Officer') and select a 'Notified Time Off Officer'(responsible_ids) 4) select an emplyee with a reelated user and remove the coach, manager, and responsible 'Time Off'. 5) save
6) Sign in as the employee, make a time off request under the new Type 7) No email
Fix:
Add a conditional with the lowest priority to fall back to responsible_ids
opw-6101637
Forward-Port-Of: odoo/odoo#263399
Forward-Port-Of: odoo/odoo#261853This update resolves a recurring error that prevented accurate reconciliation of inventory transactions involving kit components. The issue stemmed from how the system processed valuation adjustments, leading to duplicate reconciliation attempts. This fix ensures correct accounting and reporting for sales and purchases of kits containing components.
Original PR description
Steps to reproduce ----- - Modules: Sale, Purchase, Mrp, Accounting - Enable automatic accounting & anglo-saxon valuation - Create an AVCO Product category (AVCO automatic valuation) - Create a Kit…
Steps to reproduce
-----
- Modules: Sale, Purchase, Mrp, Accounting
- Enable automatic accounting & anglo-saxon valuation
- Create an AVCO Product category (AVCO automatic valuation)
- Create a Kit product storable & AVCO
- Kit bom
- Comp as a component (storable & AVCO)
- Settings > Decimal Accuracy > Product Price > set to 4 digits
- Purchase 3 units of Comp at 3.3333 piece & validate reception
- Make 2 sales for 1 unit of Comp each & validate both deliveries
- Create a SO for 1 Kit and 1 Comp & confirm
- Create & confirm invoice
- Go to the delivery, force quantity on the component and try to validate delivery
> Error message: "You are trying to reconcile some entries that are already reconciled."
/!\ Fun(?) fact: this error doesn't occur if the order of the moves is inverted.
Cause
-----
When the purchase delivery is validated, a stock valuation layer is created for 3 units with a value of 10. As they are sold individually, these 3 units generate a valuation layer for 3.33 per unit summing to 9.99.
When we validate the last delivery, the 0.01 difference is detected and an adjustment is made on the valuation layer in `_prepare_out_svl_vals`.
However this adjustment is made for the product when the invoice line concerns the kit. As a result, the first reconciliation fails and the line is added to the list to be reconciled later.
Then, when handling the line for COMP2, it will successfully reconcile the lines while it is still in the pool to be reconciled, resulting in an error when attempting to reconcile it later.
This is caused by `_stock_account_anglo_saxon_reconcile_valuation` where the `product_stock_moves` only contains the kit move when called with the kit product as argument, but it contains both moves when called with the component itself as argument. This leads to the same AML being reconciled twice.
https://github.com/odoo/odoo/blob/f0b9f4c234cd0101f5cb259e58620e1cf65bb2b7/addons/stock_account/models/account_move.py#L222-L225
-----
Ticket:
opw-5722072
Forward-Port-Of: odoo/odoo#263418
Forward-Port-Of: odoo/odoo#258013This update resolves an error that occurred when generating the SD Worx report due to a missing employee record. The fix ensures the report correctly handles public holidays without schedules, preventing a critical error and ensuring accurate report generation. This improves the reliability of payroll reporting.
Original PR description
## Steps to reproduce: - Install l10n_be_hr_payroll_sd_worx module - Create a public holiday in one company without a working schedule - Create an employee that doesn't have a working schedule nor a contract - Try to generate the sd worx report - A traceback will pop-up ## Cause: Since we fetch all employees if we have a public holiday with no schedule, this puts us in a scenario where we try to access a key in that doesn't exist and it will trigger a KeyError ## Fix: Make sure we fallback on an empty recordset in case we don't have the employee in the key list of the dict we are checking opw-5500070 Forward-Port-Of: odoo/enterprise#117268
This update resolves an issue where newly created product categories weren't automatically using the latest expense account settings. The fix ensures that changes to company expense accounts are correctly reflected in new product categories, maintaining accurate financial reporting. This improves the consistency and reliability of product costing.
Original PR description
**Steps to reproduce:** - Accounting > Configuration > Settings > Default Accounts > Product Accounts - Change the default expense account (and income account) - Create a new product category -…
**Steps to reproduce:** - Accounting > Configuration > Settings > Default Accounts > Product Accounts - Change the default expense account (and income account) - Create a new product category - category still proposed the old accounts Affected versions: from 18.2 till 19.2 **Cause:** `ir.default` for `product.category` (`property_account_expense_categ_id` and `property_account_income_categ_id`) was not updated when `res.company.expense_account_id` / `income_account_id` changed, so new categories kept using stale defaults. and in 19.0 https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/account/models/company.py#L490 and https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/account/models/company.py#L753 calls https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/account/models/company.py#L1136-L1139 However, when stock_account is installed https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/stock_account/models/res_company.py#L361-L366 this gets called, without calling super, that's why it didn't work although the fix is there, we will need to adapt another fix in 19.0+ **Solution:** Call `_set_category_defaults()` in `res.company.write()` so `ir.default` stays aligned with the company's current product default accounts. opw-6145491 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261594
This update fixes an error in the Italian Annual VAT Report that was incorrectly mixing tax and balance amounts on line VF25. The change ensures the report accurately reflects the total taxable base as required by Italian tax regulations, aligning with the official Agenzia delle Entrate guidelines. This correction guarantees accurate VAT reporting for Italian businesses.
Original PR description
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive…
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive operations, the report erroneously mixes tax amounts into the balance column. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to Tax Report and visualize the Annual Tax Report (IT) 3. Go to VF VAT Report 4. See the VF25 is mixing taxes and balances ### Cause of the issue: The root cause lies in the aggregation_formula definition for the tax_annual_report_line_VF25 record. The formula was incorrectly configured to aggregate the .tax expressions for lines VF1 to VF13 (VF1.tax + VF2.tax + ...) instead of their respective .balance expressions, while correctly using .balance for the remaining lines (VF17 to VF24). https://github.com/odoo/odoo/blob/878c08cf522a3278b4e6ff5f3d18444989e9998d/addons/l10n_it/data/tax_report/annual_report_sections/vf.xml#L286-L299 It's just a typo in this commit: https://github.com/odoo/odoo/pull/164064/changes/f292ba119d6376dbfb3c1fac4960c9c56a74d938 ### Reason to introduce the fix: From documentation https://www.agenziaentrate.gov.it/portale/documents/20143/9602686/IVA_ANNUALE_2026_istr.pdf/2a42fb92-1b76-229a-d0f5-06069d79b514?t=1768504755711 : > Rigo VF25, colonna 1, va indicato il totale degli imponibili determinato sommando gli importi riportati ai righi da VF1 a VF23, colonna 1, diminuito dell’importo di cui al rigo VF24. In colonna 2 va indicato il totale delle imposte determinato sommando gli importi delle colonne 2 dei righi da VF1 a VF13. opw-6172791 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264379
This update fixes a validation error that occurred when using cash basis accounting with payable or receivable accounts. The change restricts users from selecting these account types as transition accounts, ensuring consistent and accurate accounting configurations. This prevents errors during invoice creation and move generation.
Original PR description
## **Issue** When a cash basis tax is configured with a payable/receivable transition account, tax journal items are generated on that account without a due date. Since payable/receivable accounts…
## **Issue** When a cash basis tax is configured with a payable/receivable transition account, tax journal items are generated on that account without a due date. Since payable/receivable accounts require a due date on journal items, this leads to a validation error during move creation: "Any journal item on a payable account must have a due date and vice versa." ## **Steps to reproduce:** 1. Install the Accounting and Inter-Company modules. 2. Create an additional company so that there are a total of two companies, then switch to Company 1. 3. Create a product with a price and assign a tax to it. 4. Navigate to Accounting → Configuration → Settings and enable Cash Basis accounting. 5. Go to Accounting → Configuration → Taxes and open the purchase tax (or the tax assigned to the product). 6. In the Tax Computation section, ensure that Group of Taxes is not selected. 7. Under the Advanced Options tab, set Tax Exigibility to Based on Payment. 8. Set the Cash Basis Transition Account to a payable account. 9. Open Company Settings, select Company 1, go to the Inter-Company Transactions section, and enable Synchronize invoices/bills. 10. Switch to Company 2 and create an invoice using the same product. Select the contact that is the partner of Company 1. 11. Confirm the invoice. The following error is raised: "Any journal item on a payable account must have a due date and vice versa." ## **With This Commit:** Added a domain on the Cash Basis Transition Account field to prevent users from selecting payable or receivable accounts, avoiding invalid configurations and runtime validation errors. opw-6189615 Forward-Port-Of: odoo/odoo#263792
This update clarifies error messages when sending invoices via Peppol. Previously, users received a generic "no VAT" error, which was confusing. Now, the system accurately identifies the missing required Peppol VAT information (like a Belgian Company Registry or French SIRET), guiding users to correct the data and ensure successful invoice delivery.
Original PR description
When a user sends a move via Peppol to a customer that has a VAT number set but not a Peppol endpoint, we show the user a generic error ("no VAT").
This makes the user confused, as he already filled the VAT field of his customer, It's the Peppol VAT that is missing (it could be: Belgian Company Registry, France SIRET, ...etc, depending on the customer's country)
This PR makes the error message more accurate by showing exactly the missing required field.
task-5499707
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#263685
Forward-Port-Of: odoo/odoo#245915This update resolves an issue causing the FatturaPA import in the Italian tax module to fail when the necessary account module isn't installed. The fix duplicates helper functions from another Odoo module to ensure compatibility and stability, preventing errors related to missing dependencies.
Original PR description
The FatturaPA import in `l10n_it_edi/models/account_move.py` calls `self.env['account.edi.common']` for the partner and the bank account. That model belongs to `account_edi_ubl_cii`, which `l10n_it_edi` does not depend on. Without that module installed, the import dies with a `KeyError`. It is not correct to add that dependency. PR #254505 (`63926d9d`) introduced the two calls and removed the search-only lookups that lived there before. ### Fix Copied `account.edi.common._import_partner` to `_l10n_it_edi_import_partner` Copied `account.edi.common._import_partner_bank` to `_l10n_it_edi_import_partner_bank` Fixes: https://github.com/odoo/odoo/issues/264306 Forward-Port-Of: odoo/odoo#264478 Forward-Port-Of: odoo/odoo#264326
This update resolves issues where custom product attributes weren't displaying correctly in the POS kiosk mode. Specifically, it prevents the 'Add to Cart' button from being disabled when a product has a single custom attribute value. The fix ensures consistent behavior across different product configurations within the kiosk environment.
Original PR description
this pr fixes 3 bug, as all are closely related. Step to reproduce (hide is_custom attr in kiosk mode): - have two attributes A and B - A has only 1 attribute value with is_custom = True - B can have…
this pr fixes 3 bug, as all are closely related.
Step to reproduce (hide is_custom attr in kiosk mode):
- have two attributes A and B
- A has only 1 attribute value with is_custom = True
- B can have any two value ( ex. gender: male/female)
- use it on a product and make it available in POS for kiosk
- start kiosk and open that product
Observation:
- we do not get option to select option from A but the heading is visible
- when we select from B, Add to cart is disabled.
Cause:
- we do not allow attribute values with is_custom = True in kiosk
- but we display the attribute regardless
- the Add to cart btn depends on `selectedValues`, which requires
value from each attribute, in this case, we are not seletion anything from A
- so it is disabled
Fix:
- we introduced `attributesToDisplay` which will hide heading in case of single
custom value for any attribute
- for Add to cart, wenow do not expect value from `is_custom` attribute values.
Allow product with 1 attr which is `is_custom` to be configurable in configs other than kiosk: correct fix for [commit](https://github.com/odoo/odoo/commit/5155c77a03ed2ff6c914eac41cc81ccb34b1f3c7)
Step to reproduce
- have attributes A
- A has only 1 attribute value with is_custom = True
- use it on a product and make it available in POS
- start pos and open that product
Observation:
- we do not get option to select add text for A
Cause:
- in pos, we consider product to be configurable only it has more than 1
attributes, which misses is_custom attr
Fix:
- we backport [commit](https://github.com/odoo/odoo/commit/5155c77a03ed2ff6c914eac41cc81ccb34b1f3c7) and also considers its side effect by introducing
`isProductConfigurable` for pos_self_order, which will still avoid
`is_custom` attrs for kiosk
Empty page is displayed if product has only `is_custom` attribute value
and other attribute with type other then 'no_variant' for combo item
Step to reproduce
- have attributes A and B
- A has only 1 attribute value with is_custom = True
- B has two values with type "always"
- use it on a product and add that product in combo item and make it available
in Kisok
- start kiosk and open that combo and select that product
Observation:
- we do not get option to select
Cause:
- `availableAttributeValue` only show `no_variant` and non `is_custom` attribute
values in attributeSelection component.
Fix:
- before mounting Attributeselection component, we check if product has required
attribute or not.
[1] https://github.com/odoo/odoo/commit/5155c77a03ed2ff6c914eac41cc81ccb34b1f3c7
opw-6100965This update resolves a discrepancy between Odoo and Mexican SAT regulations. Previously, credit notes (out-of-policy payments) couldn't be processed through the SAT portal. This change now allows credit notes with 'out_refund' move types to utilize payment policies, aligning with SAT requirements and enabling proper processing of refunds.
Original PR description
Currently, credit notes cannot be PPD (payment_policy), however, SAT portal allows it. **STEP TO REPRODUCE** 1. Install the l10n_mx_edi module. 2. Create an invoice with PPD (either changing it or through payment terms). 3. After send CFDI, generate a credit note and try to set PPD **FIX** Allow move_type = 'out_refund' to be PPD. Task-6049654 Forward-Port-Of: odoo/enterprise#114886
2 changes
Resolved issues and error corrections
This update fixes a problem where users accessing bank reconciliation within a child company couldn't correctly determine the currency. The fix adds a temporary 'sudo' command to access the necessary currency information, ensuring accurate bank reconciliation functionality for all company setups, including those with child companies.
Original PR description
The bug is easy to reproduce, but niche. 1. Have a company set up with a child company 2. Have a non admin user with administration rights for accounting 3. Create a bank statement in a journal with no set currency_id and fully reconcile it 4. While only in the child company, try to access the bank reconciliation widget -> access error The error occurs because of how journal_currency_id is computed on the bank rec widget. The fallback value for the currency is derived from the journal_id.company_id.currency_id which is inaccessible from the child company. To circumvent this, we just add sudo() to the call. Forward-Port-Of: odoo/enterprise#117005
This update resolves a restriction in the l10n_mx_edi module, allowing credit notes (out-of-funds) to be configured with the Payment Policy (PPD) setting, as required by the Mexican SAT portal. Previously, this functionality was unavailable, causing potential compliance issues. This change ensures accurate CFDI generation and reporting for Mexican businesses.
Original PR description
Currently, credit notes cannot be PPD (payment_policy), however, SAT portal allows it. **STEP TO REPRODUCE** 1. Install the l10n_mx_edi module. 2. Create an invoice with PPD (either changing it or through payment terms). 3. After send CFDI, generate a credit note and try to set PPD **FIX** Allow move_type = 'out_refund' to be PPD. Task-6049654 Forward-Port-Of: odoo/enterprise#114886
8 changes
New functionality added to Odoo
This update establishes the foundational setup for processing payroll in Oman, aligning with local labor laws. It includes a demo company, employee data, a standard working schedule, and a new salary structure with rules for bonuses, allowances, and social contributions. This provides a base for future payroll enhancements and testing within the Omani market.
Original PR description
[ADD] l10n_om_hr_payroll: base setup for Oman payroll localization [ADD] l10n_om_hr_payroll: accrual plan, SPF, Overtime, & EOS salary rules Introduce the foundational setup for the Oman payroll…
[ADD] l10n_om_hr_payroll: base setup for Oman payroll localization
[ADD] l10n_om_hr_payroll: accrual plan, SPF, Overtime, & EOS salary rules
Introduce the foundational setup for the Oman payroll localization based on Oman's Labor Law. This serves as the base for subsequent enhancements and related tasks.
The setup includes demo data, a standard working schedule, and an Omani salary structure with standard and specific rules aligned with local requirements.
The goal of this change is to establish an initial framework for the Omani localization, enabling consistent development and functional testing. Providing demo data for the company and employees facilitates immediate use and demonstration of payroll features, while the defined 9–5 working schedule (Sunday–Thursday, Asia/Oman timezone) reflects local business practices.
Technical summary:
- **Added demo company:** “My Omani Company”.
- **Added demo employees:** Linked to the company with localized education and contract data.
- **Defined standard working schedule:** (9:00–17:00, split morning/afternoon, Sunday–Thursday, Asia/Oman timezone).
- **Introduced salary structure “Oman: Monthly Pay”:** Includes standard salary rules and the following additions:
- **Bonus:** Added as an Other Input.
- **Other Allowance:** Salary input at employee level with a corresponding rule under category “Allowances”.
- **Total Wage:** New parent category grouping “Allowances” and “Basic Salary”.
- **Expenses Reimbursement:** Added as an Other Input.
- **Renamed “Taxable Salary” to “Gross”:** To align with local terminology.
- **Social Protection Fund (SPF):** Added fields and logic for Employee and Employer contributions covering Old Age, Disability and Death , Unemployment, Work Injury, Sick Leave, and Maternity.
- **End of Service (EOS):** Introduced an EOS eligibility toggle on the employee record and a "Provision Payout" salary rule category.
- **Leave Accrual:** Added an "Oman Employee Plan" with a monthly accrual of and annual sick leaves.
- **Overtime Rules:** Defined rules for Daytime, Nighttime, and Rest Day overtime within the attendance and work entry.
task-5189116
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prEnhancements to existing features
This update simplifies the generation of 281.XX payroll reports by centralizing the process and improving the user interface. The changes consolidate report creation, standardize data formats, and enhance error handling, resulting in a more efficient and reliable payroll reporting system.
Original PR description
**Container, Mixin & Generation** * 281_xx is now the single entry point for all 281.xx reports. * Introduced a shared mixin (`l10n_be.281.mixin`) to centralize common logic (employee validation,…
**Container, Mixin & Generation** * 281_xx is now the single entry point for all 281.xx reports. * Introduced a shared mixin (`l10n_be.281.mixin`) to centralize common logic (employee validation, payslip filtering) and enforce a standard structure across all 281.xx forms. * Child reports (281.10, 281.45) are systematically created and linked to the container. * Forms are only generated for employees who require them (e.g., skipping 281.45 if the employee has no IP). * XML generation is centralized at the container level: subreports provide data, while the container defines header-level information. * Record names are adapted to include the year and a suffix sequence (e.g., `YEAR_281_suffix`). **UI & View Simplification** * Removed dedicated 281.10 and 281.45 form views, consolidating them into a unified container using tabs instead of smart buttons. * Updated list view to display the year as the first column, and expose reference, form types, sending type, treatment type, and state. * Introduced a shared employee declaration list view used across all 281 report types. **Sequence, Error Handling & Finalization** * The container holds the state (Draft, Error, Ready, Done). Draft state allows generating test XML; Ready state corresponds to final XML. * Validation errors from subreports are aggregated and set the container to an "Error" state, blocking the XML generation. * Confirmation wizard sets the final Belcotax reference, triggers the PDF generation, and sends the documents to the employees. Task: 5911065
This update introduces a new report required by the Slovak Financial Administration, enabling businesses to accurately file their VAT Control Statement (KVDPH). The report covers key sales and purchase data, automating calculations and ensuring compliance with Slovak tax regulations. It includes features like XML export and bad debt flagging for improved accuracy and efficiency.
Original PR description
*=l10n_eu_oss_reports This commit introduces the VAT Control Statement report (Kontrolný výkaz DPH) as required by the Slovak Financial Administration. The report covers all eight sections of the…
*=l10n_eu_oss_reports This commit introduces the VAT Control Statement report (Kontrolný výkaz DPH) as required by the Slovak Financial Administration. The report covers all eight sections of the KVDPH: - A.1: standard issued invoices to registered entities - A.2: domestic reverse-charge sales (§69) with commodity codes - B.1: reverse-charge purchases (EU acquisitions, triangular, imports) - B.2: standard domestic purchases with VAT deduction - B.3.1/B.3.2: simplified invoices (split by €3,000 threshold) - C.1/C.2: corrections to issued/received supplies (credit & debit notes) - D.1/D.2: e-KASA aggregates and other supplies (manual entry) Each section uses a custom SQL engine that handles grouping by move, partner, tax rate, and commodity tag depending on the section context. Sections A.2 and C.1 resolve product commodity codes (TK) and goods types (TD) from account tags defined in XML data. Also adds: - XML export following the KVDPH_2025 XSD schema - `l10n_sk_is_bad_debt` field on `account.move` for bad debt flagging - `l10n_sk_uom` selection on account.move.line for KVDPH unit of measure - product tag data for 54 commodity codes and 2 goods types - views to expose the new fields on invoices, journal items and products - Added dedicated return type and submission wizard with direct XML download Documentation: https://www.financnasprava.sk/sk/podnikatelia/dane/dan-z-pridanej-hodnoty/kontrolny-vykaz-dph Related: https://github.com/odoo/odoo/pull/241860 Related: https://github.com/odoo/upgrade/pull/9102 task-5213902
This update allows administrators to exclude specific employees from payruns directly within the payrun version list. When an employee's payslip is excluded from a payrun version, the payslip itself is also removed, providing greater control over payroll processing and ensuring accurate reporting.
Original PR description
This commits adds a button to the versions list in payruns to allow users to exclude employees from the payrun. If the employee has a payslip for that payrun, the payslip will also be excluded. Task-5955126
This update streamlines the calculation of prices on the website, particularly for subscription-based products. By directly using recurring plan prices when available, the system now computes prices faster and more accurately, leading to a better customer experience. The changes also incorporate updates from the Odoo community.
Original PR description
* website_sale_subscription: speed up prices computation when the plan is known When the cart already holds a recurring product (and therefore a recurring plan), it can be forwarded to the price computation logic to directly compute the right unit price (instead of the sales price). * Adapt to community changes
This update ensures compliance with UAE minimum wage laws for Emirati employees within the Odoo Enterprise HR payroll system. A warning is now displayed on payslips and the payroll dashboard if an employee's wage doesn't meet the minimum wage requirements or if their contract starts after January 1, 2026, promoting accurate payroll processing.
Original PR description
[IMP] l10n_ae_hr_payroll: minimum wage for Emirati employees Warning is added to the payslip of Emirati Employees when their wage does not satisfy minimum wage conditions and when their contract starts after 01/01/2026. task - 6110277
Resolved issues and error corrections
This update resolves discrepancies in order totals between Odoo and Shopee/Lazada due to rounding differences when handling marketplace discounts. The changes ensure accurate tax calculations and total amounts, improving order reconciliation and preventing financial inaccuracies.
Original PR description
Marketplace orders with discounted tax-exclusive lines could not match the platform total: Odoo accumulated a small rounding residue vs Shopee's total_amount / Lazada's order price. sale_shopee…
Marketplace orders with discounted tax-exclusive lines could not match the platform total: Odoo accumulated a small rounding residue vs Shopee's total_amount / Lazada's order price. sale_shopee ----------- - Use model_discounted_price as price_unit (discount=0) instead of a percentage discount. - Rename _recompute_subtotal to _compute_subtotal to derive tax-exclusive subtotals from tax-inclusive totals (aligned with sale_lazada). - Add _compute_reconciled_line_specs: price-include taxes keep the discounted unit price; tax-exclusive taxes use the nominal rounded tax-exclusive unit. - In _create_order_from_data, append a tax-free "Shopee Amount Adjustment" line for any residue vs Shopee total_amount. - Add a dedicated shipping line with fiscal-position-mapped taxes. - Structure SO line descriptions (SKU, promotion, original price) via _build_item_description. - Consolidate tests with build_order_mock(**extra); tax fixtures use an explicit tax group where required (Odoo 19+). sale_lazada ----------- - Port the same reconciliation model: reconciled line specs, discount=0 with discounted unit from paid_price, shipping line from shipping_fee, order-level tax-free "Lazada Amount Adjustment" vs order price. - Group by SKU: _build_item_description (SKU, voucher, original price); skip all-canceled SKU buckets. - Tests: build_order_mock(), same tax fixture pattern as sale_shopee. task-6112062
This update corrects a problem in the French Intrastat export process. Previously, the system was missing crucial quantity data related to supplementary units when generating the DEBWEB2 XML file. This fix ensures that all relevant data is included, improving the accuracy of Intrastat reporting for French companies.
Original PR description
Steps to reproduce 1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set…
Steps to reproduce
1. In a French company with Intrastat enabled, set up a product whose commodity code has a CN supplementary unit (e.g. 8802 30 00, "p/st") and set `intrastat_supplementary_unit_amount` on it.
2. Post EU customer invoices for that product.
3. Export the DEBWEB2 XML from the Intrastat report.
Issue
The FR export collapses engine rows a second time in `_group_items`, because the DEBWEB2 format groups more aggressively than the SQL. The aggregator only declares `value` and `weight`: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/models/account_intrastat_report.py#L308-L313 Items are then rebuilt as `dict(zip(grouping_key, key_tuple)) | grouped_item_values`. `SU_code` survives (it is in the grouping key), but the numeric `supplementary_units` is in neither side and is silently dropped as soon as two engine rows merge. The template then skips the element because of its `t-if="item.get('supplementary_units')"` guard: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/l10n_fr_intrastat/data/intrastat_export.xml#L61
opw-6139657
Forward-Port-Of: odoo/enterprise#117357
Forward-Port-Of: odoo/enterprise#1170334 changes
New functionality added to Odoo
This update implements the required Belgian fiscal reporting specifications for certified POS restaurant systems, ensuring compliance with FPS Finance regulations. It manages communication with the blackbox device, automatically generates fiscal receipts, and provides robust error handling for accurate transaction recording. The module includes features for training mode, debugging, and handling network outages to maintain data integrity.
Original PR description
Implement the Belgian Registered Cash Register (Caisse Enregistreuse Certifiée) v2 specification as required by FPS Finance for certified POS restaurant systems. The implementation is split into a…
Implement the Belgian Registered Cash Register (Caisse Enregistreuse Certifiée) v2 specification as required by FPS Finance for certified POS restaurant systems. The implementation is split into a core module and five bridge modules: l10n_be_pos_blackbox (main module): - FDM (Fiscal Data Module) communication layer that signs every fiscal event by sending a structured message to the blackbox device and receiving a hash + VSC counter in return. M110 (sale), M111 (refund), M112 (partial refund), M121 (order), M122 (cost-centre change), M123 (pre-bill), M130 (money in/out), M131 (drawer open), M140/M141 (work in/out), M150 (invoice), M160 (copy), M180/M181 (X/Z turnover report), M182/M183 (user X/Z report), UC230 (sale correction). M160 (copy), M180/M181 (X/Z turnover report), M182/M183 (user X/Z report), UC230 (sale correction). - Input generator that encodes all line-level fiscal data (PLU hash, VAT groups, price rounding, grouping IDs) according to the spec. - Fiscal receipt template (XML) that renders the blackbox hash, VSC counter, POS system identifier, and event sequence number on every printed receipt. - X/Z daily report views with fiscal totals per VAT category. - Training-mode support: activates the FDM training flag so the device does not count test transactions. - Inspect popup (debug) for examining raw FDM messages. - Error/warning popup system with traceback messages from the device. - LocalStorage queue to replay pending mutations after a network outage. - pos_config / pos_session overrides: enforce blackbox constraints (only EUR, no rounding, mandatory restaurant mode, etc.), manage device pairing, and accumulate per-session fiscal counters. - Extensive unit-test suite: >6 000 lines covering the input generator's grouping-ID logic, price-consistency rules, and every mutation type against golden JSON fixtures. - Browser tour tests (oracle + regression tours). l10n_be_pos_blackbox_hr: - Clock-in / clock-out flows for employees trigger M140/M141 work in/out mutations; employee INSZ/NISS number is required and stored on hr.employee; pos_session accumulates per-employee work records. l10n_be_pos_blackbox_loyalty: - Gift-card and discount reward lines are mapped to the correct MPV fiscal codes (UC260/UC261); loyalty products are flagged so the input generator can calculate their contribution to the signed total correctly. l10n_be_pos_blackbox_self_order: - Intercepts self-order confirmation on kiosk screens to sign the order with the FDM before the confirmation page is shown; adds a controller to expose the required blackbox data to the kiosk frontend. l10n_be_pos_blackbox_settle_due: - Handles the "settle due" payment flow: products used to represent deferred payments are flagged and treated as zero-VAT lines in the signed message. l10n_be_pos_blackbox_urban_piper: - Patches the Urban Piper ticket-screen and pos_store so that online orders routed through Urban Piper are also signed before finalisation. task-id: 5864870 community PR: https://github.com/odoo/odoo/pull/229692
Resolved issues and error corrections
This update corrects a bug where managers weren't seeing all their direct reports in the 'My Team' filter within the HR appraisal module. The fix utilizes a more accurate method for determining hierarchical relationships, ensuring managers correctly see all subordinates. This improves the usability and accuracy of the appraisal process.
Original PR description
Before this commit: If A is a manager of B and B is a manager of C, A cannot see C under My Team filter. Fix: Use is_subordinate. task-6204754
This update fixes an issue where tax return entries incorrectly included taxes from multiple regions (like British Columbia) instead of filtering for the specific tax return type (e.g., Manitoba PST). The change ensures that tax return entries accurately reflect the taxes owed based on the return type, improving the accuracy of VAT reporting across Canada, Ecuador, Egypt, Pakistan, Saudi Arabia, and Kenya.
Original PR description
Issue: Validating a tax return creates an entry with all the tax aml from the company instead of filtering them according to the tax return type. Steps to reproduce: - In a company in Canada - Invoice a Customer from British Columbia in the previous month (A) - Confirm - Go to tax report -> Return - Review and Validate tax return for "Manitoba PST Return (CA)" for month A - Click on the 3 dots -> View Entry Current Behavior: - Entry has lines for PST in British-Columbia and GST taxes Expected behavior: - Entry has lines for PST in Manitoba only Cause: https://github.com/odoo/enterprise/pull/98158 introduces method `_get_vat_closing_entry_additional_domain` in the wrong class. opw-6065838 Forward-Port-Of: odoo/enterprise#116366
This update fixes a problem where the POS feedback screen displayed incorrect order totals. The change ensures that order prices are calculated and displayed accurately, even when requests are delayed. It also prevents the POS from finalizing orders with errors, improving the overall transaction process.
Original PR description
We now call manually `setOrderPrices` on order validation to ensure `amount_total` is set on the order before displaying the feedback screen which depends on it. The issue is that requests to the FdM delay the call to this method, making the PoS display `0` as the amount is `undefined` in the meantime. We also ensure the PoS doesn't finalize the validation if an error occurs. see odoo/odoo#244298
11 changes
Resolved issues and error corrections
This update resolves issues preventing Odoo IoT boxes from successfully upgrading to newer database versions. The fix ensures the system waits after the upgrade script before attempting a new git checkout, and now includes the necessary 'geoip2' package during the upgrade process. This improves the stability and reliability of Odoo deployments on IoT boxes.
Original PR description
This commit fixes two issues with upgrading from old IoT box images to 19.1+ DBs: - The IoT box would try and start checking out with git at the same time as the upgrade script rebooted the system. This would leave the git branch as the DB version (e.g. 19.2) but with the files still being at 19.1. To fix this, we sleep after the script until we reboot. - On reboot, the IoT box would then git checkout to the new version anyways. However, it would not install apt packages, leaving the Odoo service unable to start because of a missing 'geoip2' package. To fix this, we simply include this package in the upgrade script. task-6217972 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264737
This update resolves an issue where customers ordering 'Pick up in store' without logging in weren't receiving confirmation emails. The fix ensures that the customer's email is correctly subscribed to the delivery order, triggering the necessary notification. This improves the customer experience and reduces potential order confusion.
Original PR description
Customers placing an order without logging in and with the "Pick up in store" delivery method are not notified when the delivery is confirmed 1. Install eCommerce and Sales 2. Go to Settings >…
Customers placing an order without logging in and with the "Pick up in store" delivery method are not notified when the delivery is confirmed 1. Install eCommerce and Sales 2. Go to Settings > Website > Delivery and enable "Click & Collect" 3. Go to Settings > Inventory > Shipping and enable "Email Confirmation" 4. Go to Website > Configuration > Payment Providers and Install Demo 5. Go to Website > Configuration > Delivery Methods and open "Pick up in store", set YourCompany as warehouse and publish it 6. Go to Sales > Products, open product "Office Lamp", click on "Update Quantity" in the status bar and add 5 units 7. Log out 8. Go to the shop, add product "Office Lamp" to the cart and checkout 9. Fill in the address form and continue checkout 10. Select "Pick up in store" as delivery method and select a location 11. Confirm the order and pay with Demo 12. As user Mitchell Admin, go to Sales, remove the default filter and open the newly created sale order 13. Open the related delivery with the smart button and validate it 14. No delivery order confirmation was sent to the customer (check emails) Issue: Confirming an order with a "Pick up in store" delivery method replaces the `partner_shipping_id` of the sale order with an archived partner https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/delivery/models/sale_order.py#L178-L192 which updates the `partner_id` of the related `stock.picking` with the archived partner https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/sale_stock/models/sale_order.py#L130-L132 This will unsubscribe the old `partner_id` on the `stock.picking` and try to subscribe the archived partner https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/stock/models/stock_picking.py#L1120-L1125 Because the partner we want to subscribe is archived, he will be filtered out and the subscribe action will have no effect, preventing him from receiving the delivery confirmation https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/mail/models/mail_thread.py#L4367-L4369 Solution: Subscribe the parent of the archived partner when we write a `partner_id` on pickings with "in_store" `delivery_type`. This ensures the unarchived partner is subscribed to the picking allowing him to receive the mail confirmation. opw-6095396
This update fixes an issue where refunds processed with card payments didn't correctly reverse the accounting entries. The fix prevents a double accounting swap, ensuring that credit and debit values are properly inverted during refund processing, leading to accurate financial records. This improves the reliability of our Point of Sale accounting.
Original PR description
**Steps to reproduce:** - Open the PoS, make a sale and pay by card - Close the PoS - Open the PoS, refund that sale with card again - Close the PoS - Go to the accounting app -> accounting -> journal entries - Check the jounal entries created with Combine Card POS payments - They will basically be the same, only the order of the account move lines is swapped They credit/debit should be inverted **Why the fix:** This is due to a double swap, as we swapped the accounts and swapped the payment type, meaning we were basically inverting it twice, and that's why only the order changed but not the values. We now stop changing the payment_type manually to avoid this situation. opw-6074455
This update resolves a memory issue that could cause Odoo to crash when importing invoices or bills with a large number of products. The fix uses a more efficient batch processing method to reduce unnecessary calculations and memory usage, resulting in improved performance and stability.
Original PR description
Before this commit, for DBs with a very large number of products it was possible for the thread to run out of memory when importing an invoice or a bill. The reason is that the name on…
Before this commit, for DBs with a very large number of products it was possible for the thread to run out of memory when importing an invoice or a bill. The reason is that the name on product.product is non stored and computed. This leads to tons of recomputes, which in turn leads to reads and stores in cache of the underlying `product.product`, which down the line uses up all of the available memory for the thread. The proposed method uses batches instead of a `search_fetch` as the latter would not solve the recompute problem and hence the underlying memory problem. Another alternative approach could be going straight for the `product.template.name`, but that approach might introduce a loss of precision or functionality when searching for products at invoice import. Here is the memory graph from memray before the fix: <img width="1106" height="450" alt="opw-6168737-memray-pre-fix" src="https://github.com/user-attachments/assets/f971dc4d-aa09-41e3-a8c5-e5ca53f9786d" /> And here is the same graph after the fix: <img width="1106" height="450" alt="opw-6168737-memray-post-fix" src="https://github.com/user-attachments/assets/0a784cdc-9b40-498b-bbcb-89114eec1ec9" /> We can see a much lower peak memory usage after the fix. We an also observe that the memory complexity shifts from `O(n)` to `O(1)`, with `n` being the number of `product.product` records stored in the DB. For both presented graphs, the same, unaltered database was tested. The database contains 389 467 `product.product` records. opw-6168737 Forward-Port-Of: odoo/odoo#262591
This update resolves an issue where combo products weren't opening their configurator dialogs when viewed on mobile devices. The fix utilizes a different widget to enable configurator logic and barcode scanning, ensuring a seamless experience for mobile users creating quotations with combo products. This improves usability and allows mobile sales teams to accurately configure complex product combinations.
Original PR description
Steps to reproduce 1. Create a Combo Product with some combo items. 2. Open Odoo on a mobile device or simulate mobile view (isSmall=true). 3. Create a new Quotation and add the Combo Product via the…
Steps to reproduce
1. Create a Combo Product with some combo items.
2. Open Odoo on a mobile device or simulate mobile view (isSmall=true).
3. Create a new Quotation and add the Combo Product via the "Add product"
button in the order lines kanban.
Issue
The combo product is added directly to the order lines with a price of
0.00, and the Combo Configurator dialog never opens.
On mobile, the 'product_id' field in the 'sale.order.line' inline form
view uses the generic 'many2one_barcode' widget. This widget is a
standard Many2one with barcode support but lacks the specific logic in
'SaleOrderLineProductField'
(https://github.com/odoo/odoo/blob/d1ab74aebc356537dd2a7df43fb40150580802ea/addons/sale/static/src/js/sale_product_field.js#L74-L92)
that detects combo/configurable products and opens the appropriate
configurator dialog. On desktop, the 'sol_product_many2one' widget
handles this, but it was not used on mobile because it lacks barcode
scanning features.
Solution
The inline form view now uses 'sol_product_many2one' with
options="{'can_scan_barcode': True}" instead of 'many2one_barcode'.
This leverages the existing 'can_scan_barcode' option on Many2OneField
(https://github.com/odoo/odoo/blob/7ba46d2cea7f522e17ffe04c4051469fb0320a76/addons/web/static/src/views/fields/many2one/many2one_field.js#L390),
giving the field both configurator logic and barcode support. The fields
needed for combo state ('selected_combo_items', 'virtual_id') are also
added to the mobile views.
opw-6062731This update resolves an issue where incorrect tax rates were being applied when importing invoices in the account_edi_ubl_cii module. Specifically, it ensures that only taxes matching the invoice's fiscal position are considered, improving the accuracy of financial reporting. This change was backported from a previous issue.
Original PR description
Backport of #263872 OPW-6022540 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes a potential error in Odoo's cash basis accounting setup. Previously, using a payable or receivable account as a transition account for taxes could cause validation errors. This change restricts users from selecting these account types, ensuring accurate accounting configurations and preventing runtime issues.
Original PR description
## **Issue** When a cash basis tax is configured with a payable/receivable transition account, tax journal items are generated on that account without a due date. Since payable/receivable accounts…
## **Issue** When a cash basis tax is configured with a payable/receivable transition account, tax journal items are generated on that account without a due date. Since payable/receivable accounts require a due date on journal items, this leads to a validation error during move creation: "Any journal item on a payable account must have a due date and vice versa." ## **Steps to reproduce:** 1. Install the Accounting and Inter-Company modules. 2. Create an additional company so that there are a total of two companies, then switch to Company 1. 3. Create a product with a price and assign a tax to it. 4. Navigate to Accounting → Configuration → Settings and enable Cash Basis accounting. 5. Go to Accounting → Configuration → Taxes and open the purchase tax (or the tax assigned to the product). 6. In the Tax Computation section, ensure that Group of Taxes is not selected. 7. Under the Advanced Options tab, set Tax Exigibility to Based on Payment. 8. Set the Cash Basis Transition Account to a payable account. 9. Open Company Settings, select Company 1, go to the Inter-Company Transactions section, and enable Synchronize invoices/bills. 10. Switch to Company 2 and create an invoice using the same product. Select the contact that is the partner of Company 1. 11. Confirm the invoice. The following error is raised: "Any journal item on a payable account must have a due date and vice versa." ## **With This Commit:** Added a domain on the Cash Basis Transition Account field to prevent users from selecting payable or receivable accounts, avoiding invalid configurations and runtime validation errors. opw-6189615 Forward-Port-Of: odoo/odoo#263792
This update resolves a restriction in the l10n_mx_edi module, allowing credit notes (out-refunds) to be configured with Payment Policy Details (PPD) as required by the Mexican SAT portal. Previously, this functionality was unavailable, creating a discrepancy between Odoo and SAT regulations. This change ensures accurate VAT refund processing for Mexican businesses.
Original PR description
Currently, credit notes cannot be PPD (payment_policy), however, SAT portal allows it. **STEP TO REPRODUCE** 1. Install the l10n_mx_edi module. 2. Create an invoice with PPD (either changing it or through payment terms). 3. After send CFDI, generate a credit note and try to set PPD **FIX** Allow move_type = 'out_refund' to be PPD. Task-6049654 Forward-Port-Of: odoo/enterprise#114886
This update fixes an issue where invoices generated for non-Polish customers incorrectly included the country code in the VAT number field. This ensures compliance with KSeF regulations, preventing potential errors and delays in invoice processing. The change ensures the correct format is used for all invoices, regardless of the customer's location.
Original PR description
Currently, an incorrect VAT format is used in the generated `FA3 XML` for non-Polish partners, where the VAT number includes the country code. **Steps to reproduce:** - Install the `l10n_pl_edi`…
Currently, an incorrect VAT format is used in the generated `FA3 XML` for non-Polish partners, where the VAT number includes the country code. **Steps to reproduce:** - Install the `l10n_pl_edi` module and switch to a `PL Company`. - Go to Settings and enable `Allow KSeF integration` (refer to [1]). - Create and confirm an invoice for a customer (e.g., Azure Interior). - Send the invoice using `by KSeF (e-Faktura)`. **Observation:** In the generated XML file, the `NrID` field contains the VAT number `with the country code` for non-Polish partners. **Root Cause:** At [2], `get_vat_number` sets the VAT number using `compact` from `stdnum.pl.nip`, which only works for Polish VAT numbers. At [3], `get_vat_number` correctly formats Polish VAT numbers without the country code in the `if condition`. However, in the fallback (else) case, it returns the VAT number as it is, including the country code. **Fix:** This commit ensures that for non-Polish VAT numbers, the country code is removed before setting the `NrID` or `NrVatUE` values in the XML, aligning the format with KSeF requirements. Ref: https://ksef.podatki.gov.pl/media/4u1bmhx4/information-sheet-on-the-fa-3-logical-structure.pdf (Page no.: 19) [1]: https://www.odoo.com/mail/message/1057847327 [2]: https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/l10n_pl_edi/models/account_move.py#L257 [3]: https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/l10n_pl_edi/data/fa3_template.xml#L67-L82 opw-6120118
This update fixes an error in the Italian Annual VAT Report that was incorrectly calculating the balance amount for line VF25. The fix ensures the report accurately reflects the total taxable base as required by Italian tax regulations, preventing potential discrepancies with tax authorities. This ensures compliance and accurate reporting for Italian businesses using Odoo.
Original PR description
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive…
### Issue before this commit: In the Italian Annual VAT Report, the balance (base amount) for line VF25 displays incorrect values. Instead of computing the sum of the taxable bases for the passive operations, the report erroneously mixes tax amounts into the balance column. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to Tax Report and visualize the Annual Tax Report (IT) 3. Go to VF VAT Report 4. See the VF25 is mixing taxes and balances ### Cause of the issue: The root cause lies in the aggregation_formula definition for the tax_annual_report_line_VF25 record. The formula was incorrectly configured to aggregate the .tax expressions for lines VF1 to VF13 (VF1.tax + VF2.tax + ...) instead of their respective .balance expressions, while correctly using .balance for the remaining lines (VF17 to VF24). https://github.com/odoo/odoo/blob/878c08cf522a3278b4e6ff5f3d18444989e9998d/addons/l10n_it/data/tax_report/annual_report_sections/vf.xml#L286-L299 It's just a typo in this commit: https://github.com/odoo/odoo/pull/164064/changes/f292ba119d6376dbfb3c1fac4960c9c56a74d938 ### Reason to introduce the fix: From documentation https://www.agenziaentrate.gov.it/portale/documents/20143/9602686/IVA_ANNUALE_2026_istr.pdf/2a42fb92-1b76-229a-d0f5-06069d79b514?t=1768504755711 : > Rigo VF25, colonna 1, va indicato il totale degli imponibili determinato sommando gli importi riportati ai righi da VF1 a VF23, colonna 1, diminuito dell’importo di cui al rigo VF24. In colonna 2 va indicato il totale delle imposte determinato sommando gli importi delle colonne 2 dei righi da VF1 a VF13. opw-6172791 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264379
This update corrects a bug where the delivered quantity for dropship products was incorrectly set to 1 in certain sales order scenarios. The fix ensures that the delivered quantity accurately reflects stock availability and is calculated correctly after the purchase order is confirmed. This resolves an issue impacting dropship fulfillment accuracy.
Original PR description
### Steps to reproduce: - In the settings enable dropshipping - Create a storable product P, enable the dropshipping and set a vendor - Create and confirm a sale order for a field service - Open the…
### Steps to reproduce: - In the settings enable dropshipping - Create a storable product P, enable the dropshipping and set a vendor - Create and confirm a sale order for a field service - Open the related task > Products > Add 1 unit of P - Go back to the sale order > an RFQ has been created #### > The delivered quantity of P is set to 1 ### Cause of the issue: Since 2361368acfe7fecbffde2ca26392eb89aecdc9e1 the `_inverse_fsm_quantity` method manually adapts the delivered quantity based on the fact that the `product.service_type` is `manual` rather than the `qty_delivered_method` of the line or future line is. In particular, because these lines: https://github.com/odoo/enterprise/blob/8f4fe902cb71c49bdb3caf9915f9a5abfe6f237f/industry_fsm_sale/models/product_product.py#L82-L83 provide a value of the `qty_delivered` to the created purchase order line and since the `qty_delivered_method` is a precomputed field: https://github.com/odoo/odoo/blob/fdfd9851393ff82a265997478886bcad6da357d0/addons/sale/models/sale_order_line.py#L225-L237 The fact that the purchase order line will be created with a `stock_move` `qty_delivered_method` and that the generated PO does not generate any move prior to confirmation will not trigger the dependency of the `qty_delivered` to retrigger a computation of the `delivered_qty` of the product which is suppose to be based on stock pickings: https://github.com/odoo/odoo/blob/fdfd9851393ff82a265997478886bcad6da357d0/addons/sale/models/sale_order_line.py#L871-L876 https://github.com/odoo/odoo/blob/fdfd9851393ff82a265997478886bcad6da357d0/addons/sale_stock/models/sale_order_line.py#L193-L198 Leaving the created sol with a delivered quantity of 1 prior to confirmation of the PO (which will generate move_ids related to the sol and trigger the compute). Fix: The changes of 2361368acfe7fecbffde2ca26392eb89aecdc9e1 regarding the `_inverse_fsm_quantity` appears unjustified with respect to the purpose of the fix. In addition, the `qty_delivered` and changes are already expected to be properly computed when the `qty_delivered_method` is not manual, particularly since the '`manual'` `service_type` is actually the default `service_type` corresponding to any 'consu' product and looks unrelated by any mean to the `delivered_qty` computation: https://github.com/odoo/odoo/blob/fdfd9851393ff82a265997478886bcad6da357d0/addons/sale/models/product_template.py#L165-L167 opw-6104326
2 changes
Resolved issues and error corrections
This update fixes an error in the Luxembourg Annual VAT Declaration report that resulted in incorrect calculations for Appendix E 1a. The fix ensures that key financial data is accurately included in the report, improving the reliability of VAT reporting for Luxembourg businesses. This resolves a discrepancy in the reported total.
Original PR description
### Issue: The formula `L10N_LU_TAX_163` in the Luxembourg Annual VAT Declaration was incorrect: - `L10N_LU_TAX_791.year_start` was added twice - `L10N_LU_TAX_993.year_start` was missing As a result, the computed total in Appendix E 1a was incorrect ### Steps to reproduce: - Install `l10n_lu_reports` - Open the `Report: Annual VAT Declaration (LU)` - Go to `Appendix E` - Use the `Start of Financial year` pencil icons to manually set values for fields `791` and `993` - Check the computed value of field `163` After the fix, both values are included exactly once in the formula opw-6158950
This update resolves a critical issue causing OOM crashes when generating the Swedish SIE 4 report for large datasets. By optimizing the database query and data processing, the report now runs significantly faster and with reduced memory usage, improving overall system stability and efficiency.
Original PR description
### Description of the issue/feature this PR addresses: Prevent Out of Memory (OOM) crashes and drastically improve execution speed when generating the Swedish SIE4 verification export for massive…
### Description of the issue/feature this PR addresses: Prevent Out of Memory (OOM) crashes and drastically improve execution speed when generating the Swedish SIE4 verification export for massive datasets. ### Current behavior before PR: When exporting a large volume of journal entries (e.g., 190,000+ account moves), the `_export_l10n_se_sie4_verification` method relies on iterating through heavy ORM recordsets and accessing relational child fields (move.line_ids) inside a loop. This triggers a severe N+1 query problem, maxing out server RAM and causing an OOM crash. ### Desired behavior after PR is merged: The method now utilizes a hybrid data extraction approach: - The ORM is used strictly to safely evaluate domains (multi-company rules, dates, states) and fetch a lightweight list of valid move_ids. - A single SQL query with JOIN statements fetches all parent moves, child lines, and account codes in exactly one database query. - itertools.groupby chunks the flat, lightweight dictionary results back into their respective journal entries. The export now handles massive datasets in seconds with minimal memory overhead, while remaining perfectly secure. ### Benchmark: For Memory: | # Input Data | Before PR | After PR | | -------- | -------- | -------- | | ~190,000 moves | MemoryError | 407MB| | ~200,000 moves | 1.8GB | 174.8 MB| For Speed: | # Input Data | Before PR | After PR | | -------- | -------- | -------- | | ~190,000 moves | MemoryError | 5.10s | | ~200,000 moves | 1m29s| 5.3s| ### Reference: opw-6067999