Monday, February 23, 2026
22 changes · saas-18.3
Resolved issues and error corrections
This update resolves an issue where task descriptions were being duplicated within the project form. The root cause was a default field content being incorrectly appended. This change ensures that task descriptions are displayed accurately and consistently in the project app, improving the user experience.
Original PR description
Steps to reproduce: =================== 1. Go to website > contact us page 2. Submit a new task with description. 3. View the Description in the project app. -> The description field is already shown in the form by default. You will find another time it is repeated. Cause: ====== The default field content is always appended to the form content. Solution: ========= Avoid adding description to the description field content. opw-5868382 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#246952
This update resolves an issue where event registration records didn't display attendee information after order processing. The fix ensures that registration answers are correctly linked, allowing attendee details to be accurately recorded in the system. This improves the accuracy of event attendance tracking.
Original PR description
Currently when event only have questions of type text, the field `registration_answer_ids` is empty after the order is synced to the backend. Steps to reproduce: ------------------- * Create an event…
Currently when event only have questions of type text, the field `registration_answer_ids` is empty after the order is synced to the backend. Steps to reproduce: ------------------- * Create an event for which you anloy have questions of type text: name, phone, email * Open a shop * Sell a ticket for the event and answer all 3 questions * Validate order * Check event registrations > Observe that although attendee's corresponding fields have been populated, the question' list is empty. Why is the issue happening: --------------------------- In the model EventRegistration there are two fields `registration_answer_ids` and `registration_answer_choice_ids`. Those two fields share the same relation table. https://github.com/odoo/odoo/blob/7c93b869a97f30a5b75d603b5973bf37b91bd63e/addons/event/models/event_registration.py#L83-L84 The registration is created here: https://github.com/odoo/odoo/blob/ef92cf5b33a3e55e801feea71bdbdd212da59adb/addons/pos_event/static/src/app/screens/product_screen/product_screen.js#L246 For context, when calling the create method `registration_answer_ids` has 3 values and `registration_answer_choice_ids` is empty (since no selection question). During the creation process we call the `_update` function. We first see what's happening with `registration_answer_ids`. Since there are some values we'll use the `create` part. https://github.com/odoo/odoo/blob/ef92cf5b33a3e55e801feea71bdbdd212da59adb/addons/point_of_sale/static/src/app/models/related_models/index.js#L394-L398 The `_connect` method will call itself on the inverse of the field. https://github.com/odoo/odoo/blob/ef92cf5b33a3e55e801feea71bdbdd212da59adb/addons/point_of_sale/static/src/app/models/related_models/index.js#L684 We'll finally try to get the inverse of this inverse. The first problem can be seen here because the inverse of the inverse points toward `registration_answer_choice_ids`. When we look at the field `registration_answer_choice_ids` since it is empty it will use the `clear` method. This also end up calling the `_connect` method on its inverse. Since the inverse of the inverse of `registration_answer_choice_ids` also points out to `registration_answer_choice_ids` thus it deletes the records that were added with `registration_answer_ids` This all happens because in the inversMap bot fields point toward the same value but the inverse of this value can only point to one value. In this case, ´registration_answer_choice_ids`. Why the fix: ------------ Touching the inverseMap or the related model is too risky at this point. So instead we focus on avoiding to clear all records. This can be achieved by creating the record empty of the two fields and creating the records for `registration_answer_ids` and `registration_answer_choice_ids` separately to link them later. opw-58966712
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 consistently displayed for this group, 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 prevents unnecessary errors from being triggered when the Codabox sync process (CRON) encounters temporary issues. Previously, repeated errors would halt the process, even if the servers were later restored. Now, errors are only reported when manually triggering the sync, ensuring a smoother and more reliable operation.
Original PR description
In case of a failure/downtime from the IAP/Codabox servers, an error is currently being raised. Although this is useful when manually clicking the Fetch button to see what happens, in the context of a CRON it's much less desirable as multiple failures from a CRON will automatically disable it which is not useful as the servers might be back up later on. Now, instead, we only raise if we're not in a CRON environment. opw-5922549 Forward-Port-Of: odoo/enterprise#107798
This update resolves an issue where accrual plans were incorrectly blocking the ability to take future leave, even with remaining balances below the cap. The fix prevents the system from over-calculating accrued leave, ensuring users can accurately plan and take future leave as intended. This improves the usability of the time-off management feature.
Original PR description
Accrual plan for leave days gets blocked, even when the remaining leave balance is below the cap. As a result, no additional leaves are accrued beyond a certain point, even though they should be. #…
Accrual plan for leave days gets blocked, even when the remaining leave balance is below the cap. As a result, no additional leaves are accrued beyond a certain point, even though they should be.
# Steps to reproduce:
Go to time off app
* Create a new leave type.
* Create a new accrual plan with:
- one milestone :
- 2 days accrued per month
- Cap: 10 days
- start accruing 1 days after
- No expiration
- Carry over: All
* Create and validate a leave allocation
- 1 year ago
- new leave type
- new accrual plan
* Take the maximum number of leaves available.
* Advance the computer calendar by 1 year.
* Again, take the maximum number of leaves.
* Advance the computer calendar by another year.
* Try to take a future leave.
-> Issue: It’s not possible to take a future leave, the number of accrued days has stopped increasing. The accrual plan appears blocked.
Objective : The accrual plan should continue to allocate leave days even if leaves have been consumed regularly, as long as the remaining leaves are under the cap.
## Issue
Before going further: the property `leaves_taken` of the `hr.leave.allocation` is supposed to contain the number of leaves this allocation cover until "today".
In the `_test_get_allocation_future_leaves1` added test, in the last line of the test :
`assert_virtual_leaves_equal(self, leave_type_day, 2, self.employee_emp, date='2023-02-01')`
When calling `get_allocation_data` with a `target_date` set in the future, the result is wrong. Here is how it works :
`get_allocation_data`
...
.....`_get_consumed_leaves` (1)
...........`_get_future_leaves_on` (2)
...............`_process_accrual_plans` (3)
....................`_compute_leaves` (4)
.........................`_get_consumed_leaves` (5)
..............................`get_future_leaves_on` (6)
...................................`process_accrual_plans` (7)
**A)** The method **(2)** try to calculate the added number of days each allocation will have on `target_date`. So it creates a copy of the allocation in memory using the 'new' method:
`fake_allocation = self.env['hr.leave.allocation'].with_context(default_date_from=accrual_date).new(origin=self)`
It will then update it to `target_date` using `_process_accrual_plans` and will return the difference of days between the
updated `fake_allocation` and the current allocation (`self`)
**B)** Before iterating over each accrual date, the `_process_accrual_plans` **(3)** will get the `leaves_taken` property which is a computed field. It will trigger `_compute_leaves`.
**C)** The method **(4)** will call `_get_consumed_leaves`, and so the nightmare begins.
**D)** The method **(6)** will create a second `fake_allocation` based on the origin of the first `fake_allocation` (see **A)**).
**E)** This time, `_process_accrual_plans` **(7)** will also look at the `leaves_taken`, but won't trigger the `_compute_leaves` probably because the current allocation is a `fake_allocation` of a `fake_allocation`, and one property of the `new` method is that `Two new records with the same origin record are considered equal.`. Therefore, the `leaves_taken` is considered to be already computed (but it's not).
So `_process_accrual_plans` read the `leaves_taken` which is 0 (probably the default value of `leaves_taken`), but it should be 20 !
**F)** As the value of `leaves_taken` is wrong, the fake_allocation n°2 is also wrong, and its `number_of_day` is 10 but the `number_of_days` of the origin allocation is 20. So `get_future_leaves_on` **(6)** will return -10 which makes no sense, and all the previous calls computations will be wrong. And the final `virtual_remaining_leaves` value will be 0 instead of 2.
## Source of the issue
In the `_process_accrual_plans` method, for each allocation, `leaves_taken` is only computed once at the start of the loop over the allocation "important" dates (see `nextcall` property of `hr.leave.allocation`). At this moment, the method calculates the `leaves_taken` the allocation will have on the `accrual_date` parameter. Yet, this property can change depending on the date the allocation is on (`nextcall` property) which leads to some issues in the computation of the `allocation.number_of_days`.
## Solution
For each allocation, compute the `leaves_taken` at every iteration trough the values of `nextcall`. BUT, this can trigger an infinite loop as computing `leaves_taken` calls `_get_consumed_leaves` which calls `_get_future_leaves_on`, which calls `_process_accrual_plans` ... To avoid this, this PR add the context variable `precomputed_allocations` (will be converted into a function parameter in master) which will prevent `_get_consumed_leaves` from calling `_get_future_leaves_on` for the allocations already up to date (contained by this very `precomputed_allocations` context variable).
opw-4934391
opw-5226806
Forward-Port-Of: odoo/odoo#239836
Forward-Port-Of: odoo/odoo#249190
Forward-Port-Of: odoo/odoo#243812This update ensures that all event registration answers, including free-text responses, are correctly synchronized during the payment process. Previously, only selection-based answers were sent, leading to data loss. This fix corrects a technical issue related to how event registration data is handled, improving the reliability of event ticket sales through POS.
Original PR description
## Steps to reproduce: - Configure event registration with only free-text fields (no selection field). - Open the POS, add an event ticket product, and fill in the registration form. - Click Payment…
## Steps to reproduce: - Configure event registration with only free-text fields (no selection field). - Open the POS, add an event ticket product, and fill in the registration form. - Click Payment and validate the order. ## Issue: - Registration answers were only sent to the backend when at least one selection-type question was filled. - When no selection field was present, free-text answers were not synced at all. ## Reason: - The `registration_answer_ids` and `registration_answer_choice_ids` One2many fields on EventRegistration both point to the same `registration_id` Many2one field on EventRegistrationAnswer. https://github.com/odoo/odoo/blob/c738d049fe09101bd14dce0710c2659a4a6eca39/addons/event/models/event_registration.py#L83-L85 - This caused data loss during the POS model synchronization, as entries were overwritten in the `inverseMap`. https://github.com/odoo/odoo/blob/c738d049fe09101bd14dce0710c2659a4a6eca39/addons/point_of_sale/static/src/app/models/related_models/model_defs.js#L59-L75 ## Fix: - Send all registration answers (free-text and selection-based) exclusively via `registration_answer_choice_ids`. task-5438565
This update corrects a minor oversight in the system's invoice matching tolerance settings. The change ensures accurate reconciliation of bank statements with invoices, preventing potential discrepancies and improving financial reporting. This fix addresses a technical detail that could have impacted data accuracy.
Original PR description
During this commit:https://github.com/odoo/enterprise/commit/15d26e62f14bb0224712a1712b47ebe16c3b8702 we forgot to change one part of the hardcoded tolerance. task-5952881
This update prevents test instability caused by unintentionally adding methods to models during testing. The change ensures that tests run reliably by enforcing the use of patchers for test-specific method modifications, avoiding conflicts between tests. This improves overall system stability and reduces the risk of unexpected behavior.
Original PR description
Setting methods on models during tests and not removing them afterwards can cause misbehaviour of other tests. Setting mock or test-specific methods is not an issue but it should be done via patchers. https://runbot.odoo.com/odoo/error/237983 Forward-Port-Of: odoo/odoo#249005 Forward-Port-Of: odoo/odoo#247151
This update resolves an issue where test patches within Odoo models were causing instability. The team has moved these patches to the instance level, aligning with best practices and addressing a detection error. This improves the reliability of our testing process.
Original PR description
Otherwise they trip the on-test-side-effect-detector (at least in its current incarnation). Forward-Port-Of: odoo/enterprise#107653 Forward-Port-Of: odoo/enterprise#106948
This update resolves a problem where products weren't loading correctly when switching between companies within the POS Loyalty module. The fix prevents errors caused by trying to load products directly, ensuring all products are accessible regardless of the company setting. This improves the reliability of the POS Loyalty system.
Original PR description
Step to reproduce - install `pos_loyalty` and have two companies - for this record: `loyalty.gift_card_product_50` set company_id = company1 - switch to company b and start pos Observation: - no products are loaded Cause: - `browse()` was used to load records `gift_card_product_50` and `ewallet_product_50` - when any of them is restricted on one company it fails to load whole model Fix: - Instead of directly loading them, we use `search()` to avoid `AccessError` so that rest of the products can be loaded. - Gift card is still not shown as expected opw-5449466 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes a previous issue where searching for archived accounts didn't display their associated journal entries. Now, users can view all journal items, regardless of whether an account is archived, providing a more complete financial record. This improves reporting and analysis accuracy.
Original PR description
This commit makes it possible to see the journal items for archived account when searching for the account. Previously, when searching for an account that is archived, its journal items weren't shown. task-5905559 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a bug where internal users were incorrectly assigned as suppliers when forwarding supplier invoices. This issue was causing disruptions in the OCR (Optical Character Recognition) process, which relies on automatic data population from invoices. The fix ensures invoices are correctly linked to existing suppliers, maintaining the integrity of the OCR workflow.
Original PR description
Currently we have an issue with OCR flow, where if internal users forward an email from an internal email address, the internal user is added as vendor Steps to reproduce: - Setup email alias for journal "Purchases" - From an internal user email, forward a supplier bill to the vendor bill alias Issue: If the supplier is not already a registered partner, the bill will be created with the internal user set as partner. This will break OCR flow where the missing document fields will be auto populated from the bill opw-5487368
This update resolves an issue where stock quantities were being rounded incorrectly when scanning barcodes on delivery orders. Specifically, the system was adding too little stock, leading to discrepancies in order fulfillment. This ensures more accurate stock tracking and reduces the risk of order errors.
Original PR description
To reproduce the issue: - Create a stock quantity of product1 for example of 275.84 kg in PACK1 - Create a delivery order of 3.6 kg - Go to the delivery order on stock barcode - Scan PACK1 - The new line is created as 272.2399999999 Forward-Port-Of: odoo/enterprise#107933 Forward-Port-Of: odoo/enterprise#89300
This update resolves an issue preventing custom fields from being added to attendee registration forms. Previously, a change in the system required a specific data type for registration fields, causing errors. This fix allows for more flexible customization of the registration process, enabling developers to easily add and manage additional attendee information without impacting core functionality.
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#244378This update fixes an issue where the phone number input field on mobile devices was difficult to edit due to overlapping buttons. The fix hides the utility button labels, allowing the input field to take up the full screen width and improving the user experience. This ensures consistent and easy phone number entry on mobile.
Original PR description
Steps to reproduce: 1. Install `contacts` 2. Create an individual contact with a phone number 3. Try to edit the phone number on the mobile Issue: - Unable to edit in mobile view Cause: - On mobile…
Steps to reproduce:
1. Install `contacts`
2. Create an individual contact with a phone number
3. Try to edit the phone number on the mobile
Issue:
- Unable to edit in mobile view
Cause:
- On mobile devices, the utility buttons (Call, SMS, WhatsApp) inside the phone widget consume significant horizontal space. Due to the flex layout, this forces the actual phone input field to shrink too much, making it hard/impossible to view or edit the number.
Solution:
- Hide the text labels of the utility buttons to save space, showing only the icons
- make input's width 100% on mobile screens in partner form
<table>
<thead>
<tr>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">
<img
src="https://github.com/user-attachments/assets/a620d417-119e-4e28-a62b-f63031e72598"
alt="Before"
width="500"
/>
</td>
<td align="center">
<img width="500" height="354" alt="image" src="https://github.com/user-attachments/assets/6adc4c77-767d-491d-a468-8463c0f77666" />
</td>
</tr>
</tbody>
</table>
opw-5489021This update ensures inactive taxes are accurately displayed in fiscal position mappings. Previously, inactive taxes were inconsistently shown, causing potential reporting issues. The fix corrects a discrepancy in how tax information is accessed, ensuring accurate fiscal position calculations.
Original PR description
Observed issue: inactive taxes are shown in "Replaces" `original_tax_ids` field if the form view of a tax is opened through "Configuration"->"Taxes", but not shown under "Replaces" in a fiscal position tree view, nor are they shown in the same "Replaces" field of the tax form view when opened from the fiscal position tree view. Cause: the fiscal position link calls `action_open_related_taxes` on partner (path `/account.tax/[id]`), while the "Configuration"->"Taxes" calls `action_tax_form` on tax (path `/taxes/[id]`), which has additional context element `'active_test': False` among others. Solution: adding the context to the fiscal position action produces the desired behavior, but it might break something else as it affects the whole view. task-5917667 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves a bug where the AI Composer was incorrectly displaying an out-of-office banner when the user was on leave. The fix prevents the AI thread from defaulting to the user as a correspondent, ensuring the banner only appears when a real person is unavailable.
Original PR description
**Purpose of this PR:** `ai_composer` threads were falling back to self-chat correspondent logic, - `if 0 correspondents and channel_member_ids.length === 1 -> return that only member (self-chat fallback)`. so `thread.correspondent` became the current user. this made _**out-of-office banner appear**_ on AI conversations when self is on leave. before: <img width="406" height="162" alt="image" src="https://github.com/user-attachments/assets/bb45a084-5de1-4eea-8f72-a3cf5a9012c8" /> after: <img width="391" height="192" alt="image" src="https://github.com/user-attachments/assets/743b12d8-465f-419f-83e3-b92df78af3c4" /> task-4882415
This update ensures that internal users viewing message links within slides are consistently directed to the backend form view, aligning with other portal documents. Previously, internal users were incorrectly redirected to the website page. This change maintains a unified user experience across all portal content.
Original PR description
Since #202555, a message link in slides redirects internal users to the website page if it's published. To ensure consistency with other documents in the portal, this commit redirects internal users to the backend form view of the slides. Portal and public users continue to be redirected to the published website page. Forward-Port-Of: odoo/odoo#249720
This update corrects a previous issue where the system incorrectly predicted taxes on imported invoices. Now, the system accurately uses the tax information directly from the XML invoice file, ensuring correct tax calculations. This improves the reliability of our invoicing process.
Original PR description
Context: When importing an XML invoice or vendor bill, the tax prediction was based on the customer’s invoice history. Example: if the imported invoice contains an item found in the history with two taxes (6% and 21%), the prediction would return both taxes (6% and 21%), even though only one tax is present in the XML file. The actual tax data present in the imported XML was not taken into account. After this commit, the prediction is more rigorous and correctly relies on the tax information provided in the XML (restricted search domain) task-5503126 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#249307 Forward-Port-Of: odoo/odoo#246308
This update resolves a crash in the Delivery Slip report when printed in languages other than English. The issue stemmed from the report using English labels for key fields. The fix now correctly uses the technical field names for tracking information, ensuring the report functions reliably across all supported languages.
Original PR description
Steps to reproduce: 1. Switch the partner language to Spanish. 2. Print the Delivery Slip. 3. The report crashes due to translated XPath anchors. Cause: XPath targeted hardcoded English strings 'Tracking Number' and 'Total Weight'. Solution: Target technical fields o.carrier_tracking_ref and o.shipping_weight instead of text labels. opw-5493498 Forward-Port-Of: odoo/odoo#248679
This update resolves an issue where automatic digitization of split expenses in Odoo Enterprise triggered redundant and costly OCR requests. This was impacting users' IAP credit consumption, particularly when automatic digitization was enabled. The fix ensures OCR is only performed on the original expense document.
Original PR description
OCR should only be performed on the original document. Enabling it on splits leads to redundant OCR requests and unnecessary IAP credit consumption. This is particularly important when automatic digitization is enabled, as it triggers a paid request for every split generated, leading to unexpected costs for the user. The same bug was fixed in version 19.0 and up (commit 0688575), but it couldn't be backported as the `split_expense_origin_id` field doesn't exist in version 18.0. opw-[5930791](https://www.odoo.com/odoo/project/2068/tasks/5930791) Forward-Port-Of: odoo/enterprise#107992 Forward-Port-Of: odoo/enterprise#107789
This update fixes an issue where invoices weren't correctly using product category accounts. Now, Odoo automatically checks the entire category hierarchy (parent to child) to find an available account, ensuring invoices accurately reflect the intended income or expense. This improves financial reporting accuracy.
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