Monday, February 23, 2026
11 changes · saas-18.4
Resolved issues and error corrections
Restaurant point-of-sale orders now keep quantity changes made after reopening an order. This prevents staff from seeing outdated quantities on the ticket screen and helps ensure orders are accurate before checkout or service.
Original PR description
Currently, modifying a loaded order (e.g., changing product quantity) does not save the changes, and the old order without modifications is shown on the ticket screen. ### **Steps to Reproduce:** 1)…
Currently, modifying a loaded order (e.g., changing product quantity) does not save the changes, and the old order without modifications is shown on the ticket screen. ### **Steps to Reproduce:** 1) Install the POS Restaurant app with demo data. 2) Open a Restaurant Session. 3) Click on 'Register' to create a Direct Sale. 4) Add a product (e.g., Water with Qty 2) and a customer (e.g., 'Billy Fox'). 5) Click on 'Orders' from the navbar and load the recently created order. 6) Update the quantity of Water from 2 to 5 and click on 'Orders' again. ### **Error:** The quantity of Water is not updated, the order line still shows a quantity of 2. Ref video: https://drive.google.com/file/d/1XR5W5Klyyll3KujirKb3UuAELjMcA7yD/view ### **Root Cause:** Clicking on 'Orders' calls `syncAllOrders` (see [1]), which is responsible for updating the orders. However, `this.getPendingOrder()` returns null in this scenario, causing the orders array to be empty and the function to return early without syncing. ### **Fix:** Override `updateSelectedOrderline` in `OrderSummary`. This method is invoked whenever the Numpad modifies an orderline. By calling `addPendingOrder` within this method, we ensure that Numpad modifications are correctly registered. This allows `syncAllOrders` to properly sync the updated order with the server when navigating away. [1]- https://github.com/odoo/odoo/blob/7fd5f90fe8fce4de49ec10c683f92e7a3557981a/addons/point_of_sale/static/src/app/services/pos_store.js#L1485-L1512 opw-5405402
Fixes an error that could prevent users with only Invoicing installed from setting an accounting period for tax returns. The required onboarding setup now runs in the correct module, making the tax return setup flow work as expected.
Original PR description
Currently, an error occurs when a user tries to set the accounting period. **Step to Reproduce:** 1. Install Invoicing without demo data and log-in as a super user. (from v19.0, no need to log-in as super user) 2. Invoicing > Accounting > Tax Returns. 3. Set an Opening Date in the wizard and try to apply the accounting period. **Error:** `ValueError - Expected singleton: onboarding.progress()` **Cause:** PR 1, added `_initiate_account_onboardings()` in the accountant (**accounting**) module. However, the onboarding progress should be initialized in the account (**invoicing**) module. **Fix:** This commit ensures that `_initiate_account_onboardings()` is called from the `account` module instead of the `accountant` module. [1] - odoo/enterprise#101442 Enterprise PR: https://github.com/odoo/enterprise/pull/107476 sentry-7064593163 Forward-Port-Of: odoo/odoo#248790
Receipts for purchased kits with components measured in different unit categories no longer fail when the purchase order uses a foreign currency. This helps businesses validate inventory receipts and related accounting entries reliably for kit products under automated valuation.
Original PR description
Steps to reproduce ------------------ 1. Enable Units of Measure and Automatic Valuation. 2. Create: Product KIT, stockable, UoM category Unit, UoM = Units. BoM for KIT with at least one component…
Steps to reproduce
------------------
1. Enable Units of Measure and Automatic Valuation.
2. Create:
Product KIT, stockable, UoM category Unit, UoM = Units.
BoM for KIT with at least one component whose UoM is in a different
category (e.g. m from Length).
3. Go to the product's category and set the Costing Method to Average
Cost (AVCO) and the Inventory Valuation to Automated.
4. Create a PO for KIT in a currency different from the company currency.
5. Confirm the PO and validate the receipt.
Issue
-----
Validating the receipt raises:
> The unit of measure m defined on the order line doesn't belong to the
> same category as the unit of measure kit defined on the product…
If you keep the PO currency equal to the company currency, the same kit
and BoM work and the receipt posts correctly.
Cause of the issue
------------------
Validating the receipt will call the `_action_done` of stock.move's and generate the related accounting entries. During this call and the currency of the PO is different from the company currency the `_generate_valuation_lines_data` will call the `_get_currency_convert_date` method:
https://github.com/odoo/odoo/blob/751d54207c6214a25a5a1def57137e2f2f9106e3/addons/purchase_stock/models/stock_move.py#L134-L140
This call will in turn call the `_get_qty_received_without_self`:
https://github.com/odoo/odoo/blob/751d54207c6214a25a5a1def57137e2f2f9106e3/addons/purchase_stock/models/stock_move.py#L121-L122
which was not written to handle kit products since it assumes that the product of the PO is the same as the one of the related move:
https://github.com/odoo/odoo/blob/751d54207c6214a25a5a1def57137e2f2f9106e3/addons/purchase_stock/models/stock_move.py#L102-L108
Fix
---
The qty_received is relevant to the _get_currency_convert_date as the method compares the qty_invoiced with the qty_received to determine whether to use the Invoice Date (when qty_invoiced > qty_received) or the Receipt Date.
https://github.com/odoo/odoo/blob/888e086dc6c7823b07993e90f70e2849e988fa7a/addons/purchase_stock/models/stock_move.py#L122-L126
For kits, `qty_received` must be calculated by aggregating component
moves to accurately determine this status. Since the standard logic
crashes due to UoM mismatch, the override in `purchase_mrp` is
necessary to provide the correct quantity for this date selection.
opw-5030761
Forward-Port-Of: odoo/odoo#248719
Forward-Port-Of: odoo/odoo#236276Odoo now uses Estonia's new 24% standard VAT rate as the default for sales and purchases, replacing the outdated 22% rate. This helps businesses create new products and tax configurations that match Estonia's tax rules effective July 1, 2025, including EU OSS destination VAT calculations.
Original PR description
Issue: Estonia increased its standard VAT rate from 22% to 24% effective July 1, 2025. Existing Odoo installations and new databases created with older templates still default to the outdated 22%…
Issue: Estonia increased its standard VAT rate from 22% to 24% effective July 1, 2025. Existing Odoo installations and new databases created with older templates still default to the outdated 22% rate for sales and purchases. Steps to Reproduce: 1. Install l10n_ee on a fresh database. 2. Go to Accounting > Configuration > Settings. 3. Observe that the default Sales and Purchase taxes are set to 22%. 4. Create a new product; observe it automatically assigns the 22% tax. Solution: - Updated account.tax-ee.csv to set active=False for 22% tax templates and ensure 24% templates are active. - Modified template_ee.py to update account_sale_tax_id and account_purchase_tax_id to point to the new 24% tax IDs. - Updated EU_TAX_MAP in l10n_eu_oss to reflect the 24% destination rate for Estonia across all EU member states. backport of: https://github.com/odoo/odoo/commit/55e3853313969918005757203fc63ee1bd0a3b43 opw-5407921 Forward-Port-Of: odoo/odoo#249539 Forward-Port-Of: odoo/odoo#248156
This fixes an issue where answers entered during event ticket registration in Point of Sale could disappear after payment when no selection-type questions were used. Attendee records now keep the registration details businesses need for event management and follow-up.
Original PR description
In [1], a refactoring of the POS framework was done, but in the process some overlooked behaviors induced a complete loss of the answers given in the registration process, as long as they do not…
In [1], a refactoring of the POS framework was done, but in the process some overlooked behaviors induced a complete loss of the answers given in the registration process, as long as they do not include an answer to a 'selection' question. STEPS ===== 0. Create a new event with a few questions (no 'selection' one) 1. Add tickets so that you can buy one in the POS 2. Go in the POS (reload data if needed) 3. Buy a ticket and fill the attendee form (answer to all questions) 4. Continue the POS flow and pay for your ticket. 5. Go back to the back-end and event > attendees 6. Check your new attendee: no answers are linked to the record. ISSUE ===== TLDR - Two fields have the same comodel on event.registration. This breaks the use of inverseMap as both are loaded in the pos. As they are treated sequentially when connecting related records, hidden side effects occur when both are not set. Details: This effect is due to two main issues. First, after [1], we compute the whole model reference relations using processModelDefs method, that accounts for inverse relations of o2m, m2o fields and provides an inverseMap to be used in several places, notably on creation or deletion of relational records from the POS. However, pos_event presents a peculiar situation, as registrations have two o2m fields, both loaded in _load_pos_data_fields, that are linked to the model event.registration.answer: registration_answer_ids and registration_answer_choice_ids, a subset of the first, just with a domain to only include answers of 'selection' questions. Meaning that the inverseMap will only use one of the two, in this case registration_answer_choice_ids. In turn, this means that any update of registration_id on the answer model will update that field, even if the original update was done on registration_answer_ids... Secondly, one could notice that this should still work, as the inverseMap is used in all places, we should just update the records through the field registration_answer_choice_ids. So why does it not work and why are all answers removed? Because both fields are loaded in _load_pos_data_fields, and in _sanitazeRawData we use getFields to know which fields to update and to connect (for relations on the model), both being returned. This means that independantly of the create values for the registration in addProductToOrder in pos_event, the 'framework' will still have two fields to connect and will do so sequentially, one field at the time. But in the _connect logic, if a field has no value given at creation, then the 'CLEAR' command is used, as this would mean we remove the content of the relational field. But in this case, this means that as both answer fields try to update registration_id through registration_answer_choice_ids, if no value is given at creation in that field, then we clear existing ones, for instance those we just linked through the creation values in the first field registration_answer_ids, as we basically empty registration_id on those records. The answers will also be deleted of the indexedDB because of the condition in databaseTable (no linked registration -> can be removed) FIX === Remove registration_answer_choice_ids from the loaded data, as it is not used anywhere except in the registration creation values. As it is a subset of the other field registration_answer_ids, only keep that one instead. Update the creation values to only use that field. Note that this seems to highlight a limitation when it comes to having more than one o2m field on a model loaded at the same time in POS. [1] odoo/odoo@a80a39f2ad16baf474553574c79d55948f86c453 Task-4919080 Forward-Port-Of: odoo/odoo#231293
This fix restores support for custom fields on event attendee registration forms, such as address fields added by customizations. It prevents registration errors when those fields contain normal text instead of numeric values, helping customized event websites continue to work reliably.
Original PR description
Before the addition of identification questions like "name", "email", and "phone" in the commit [1] as event questions instead of having them static, we could add custom data, such as fields for the address, with static inputs in the form. After that addition, it's no longer possible because the registration gives us the following error when trying to convert data that isn't a M2o ID or an Integer value:
invalid literal for int() with base 10
By adding the check for the field's type, we can still add custom fields with static fields in the template, as an alternative, given that there's no question type for other fields.
[1]: https://github.com/odoo/odoo/commit/6b8daa880c
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#244378Odoo now looks up the full product category hierarchy when choosing income or expense accounts for invoice lines. This helps invoices use the intended category accounts instead of falling back to default accounting settings when an intermediate category has no account configured.
Original PR description
**Steps to reproduce:** * Install the **Accounting** module. * Create a product category hierarchy (grandparent → parent → child). * Set an **income account** on the grandparent category. * Set an…
**Steps to reproduce:** * Install the **Accounting** module. * Create a product category hierarchy (grandparent → parent → child). * Set an **income account** on the grandparent category. * Set an **expense account** on the child category. * Leave the parent category without any accounts. * Create a product assigned to the child category. * Create a customer invoice using this product. **Observed behavior:** * The invoice line uses the **default income account** from settings instead of the grandparent category’s income account. * The category hierarchy is not checked to retrieve parent accounts. **Expected behavior:** * If no account is defined on a category, Odoo should traverse the **parent categories** to find one. * Only if no account exists in the hierarchy should it fall back to journal or default accounts. **Cause:** * Account lookup only checked the **immediate category**. * Parent categories were not considered. **Fix:** * Traverse the product category hierarchy when searching for accounts. * Use the first account found in the parent chain. opw-5869592 Forward-Port-Of: odoo/odoo#249909 Forward-Port-Of: odoo/odoo#248389
This update resolves an issue where users within the 'Planning / User' group couldn't take open shifts. The fix ensures that the 'I Take It' button is displayed correctly for these users, allowing them to seamlessly accept shifts within the Planning app. This improves the usability of the Planning feature for all users.
Original PR description
## Issue In the Planning app, users within the *Planning / User* groups could not take open shifts. The button *"I Take It"* would not be displayed when clicking on the shift. ## Steps to reproduce…
## Issue
In the Planning app, users within the *Planning / User* groups could not take open shifts. The button *"I Take It"* would not be displayed when clicking on the shift.
## Steps to reproduce
1. Install the *Planning* (`planning`) app
2. In the Planning app, as an admin, create and publish an open shift
3. Log in as a *User*, open the *Planning* app, and click on the open shift
4. **The _"I Take It"_ button is not displayed**
When logging in as a user who is **not** part of the *Planning / User* group, the *I Take It* button is displayed.
## Cause
The condition for the *I Take It* button to be displayed is the following:
https://github.com/odoo/enterprise/blob/301e3c40c3272a6ae89a1eb4387d7d244e1dc52c/planning/views/planning_views.xml#L282-L283
The condition that makes the button invisible is `not context.get('my_planning_action')`. When the user is part of *Planning / User*, the schedule they see when opening the *Planning* app is the *"Schedule by Resource"*, which has the following context:
https://github.com/odoo/enterprise/blob/301e3c40c3272a6ae89a1eb4387d7d244e1dc52c/planning/views/planning_views.xml#L716
When a user who **is not** part of the *Plannig / User* group opens the *Planning* app, they see their own schedule, where the context is different than in the first case:
https://github.com/odoo/enterprise/blob/301e3c40c3272a6ae89a1eb4387d7d244e1dc52c/planning/views/planning_views.xml#L636
Because the `my_planning_action` property is in the context (and all the other conditions are respected), the button is displayed.
opw-5451282
Forward-Port-Of: odoo/enterprise#104919This update corrects a previous issue where GL reports were incorrectly filtering based on AML labels instead of account names. Previously, searching for an account wouldn't always return the correct lines. This change ensures GL reports accurately filter by the specified account name, improving report accuracy and usability.
Original PR description
Since 235a5160d13296328b79e4092a8b88a733628268, the GL reports line names are set from the amls name instead of the account name. This leads to wrong behavior when trying to filter the GL, either by using the search bar or opening the GL from a P&L line. Steps: - Create a move with a line using account 442000 for example - Create another move with no line using 442000 account - Set label of one line to be containing "442000" - Go to GL and input '442000' in the search bar -> The line with label '442000' in displayed This commit set the report line's name from the account name instead of the aml's name opw-5070801
This update resolves an issue where data related to Dian tax calculations (l10n_co_dian) was being reset unexpectedly. The fix ensures that key data elements are properly flushed, maintaining accurate accounting records for users in Colombia. This improves the reliability of financial reporting.
Original PR description
task-5500236
This update resolves a validation error occurring during invoice tax calculation with the Avatax service. The issue stemmed from incorrect tax data being sent, leading to calculation discrepancies. This fix ensures accurate tax calculations for BR localization invoices.
Original PR description
Steps to reproduce: - Set up a Company with BR localization - Create a product as follows: - [General Information] Product Type: Service - [Sales] LC116 Code: 14.01 - [Sales] Purpose of Use: Not applicable - [Sales] Service Code Origin: 14.01.3/168061/1524 - [Sales] Service Codes: 14.01.3/168061/1524 - Create an Invoice with Document Type "Electronic Service Invoice - NFS-e" - Add the product on the line - Compute taxes - Compute taxes again Issue: Action will be blocked by a validation error resulting from the external taxes call ``` odoo.exceptions.ValidationError: Odoo could not fetch the taxes related to Draft Invoice. Errors: Rejection: Total Installments doesnt match Total Lines ∑ installments[m]grossValue - ∑ (lines[n].lineAmount-line[n].lineTaxedDiscount) <> 0 ``` It occurs because during the call the system is considering the existing taxes on the line and it will send to the avatax service wrong amounts opw-5412456 opw-5409735