Daily updates from Odoo
Friday, November 7, 2025
27 changes · saas-18.4
Resolved issues and error corrections
The replenishment list now updates the quantity to order whenever the visibility horizon is changed. This keeps the displayed stock planning figures aligned with the expected replenishment needs and avoids confusion for users.
Original PR description
## **Issue Before This PR:** When the `horizon (visibility days)` is updated from the left panel, the `quantity to order` for orderpoints was not automatically recomputed. This caused an…
## **Issue Before This PR:** When the `horizon (visibility days)` is updated from the left panel, the `quantity to order` for orderpoints was not automatically recomputed. This caused an inconsistency between the expected replenishment quantity and the value displayed in the orderpoint list, leading to confusion in stock planning. ## **Steps to Reproduce:** - Install `Inventory (stock)` and `Sales (sale_management)` module, - Add a product with 0 on-hand quantity, - Create a replenishment rule for this product with manual trigger, - Create a sale order with the same product with delivery date 10 days later, - Confirm the sale order, - Open the replenishment menu in Inventory, - Change the horizon (visibility days) to 10, - Observe that qty_to_order is not updated automatically, causing inconsistency. ## **Cause of the Issue:** This bug was introduced in PR #213745, where `qty_to_order_computed` was made `store=True` and `qty_forecast` was removed from its `depends`. As a result, the compute method is not called on relevant changes and the value does not get updated. ## **With This PR:** The `_compute_qty_to_order_computed` is now manually called which updates the value each time the horizon is updated. This ensures that the `qty_to_order` field reflects the correct values and resolves the inconsistency in replenishment quantities. TaskID: [4988468](https://www.odoo.com/odoo/project/966/tasks/4988468)
This change prevents an unnecessary validation error during database migration when a tax distribution total is zero. It ensures the system only flags invalid totals when that check is actually meaningful, helping upgrades complete smoothly.
Original PR description
``` File "/home/odoo/src/odoo/19.0/addons/account/models/account_tax.py", line 611, in _validate_repartition_lines raise ValidationError(_("Invoice and credit note distribution should have a total…
```
File "/home/odoo/src/odoo/19.0/addons/account/models/account_tax.py", line 611, in _validate_repartition_lines
raise ValidationError(_("Invoice and credit note distribution should have a total factor (+) equals to 100."))
odoo.exceptions.ValidationError: Invoice and credit note distribution should have a total factor (+) equals to 100.
```
- During the database migration, a traceback occurs because the [total_pos_factor](https://github.com/odoo/odoo/blob/18.0/addons/account/models/account_tax.py#L558) is being calculated as 0. When this happens, the float_compare [function](https://github.com/odoo/odoo/blob/18.0/addons/account/models/account_tax.py#L559) returns -1, which incorrectly satisfies the validation condition and triggers a ValidationError.
- To resolve this, we need to add an additional condition to check whether total_pos_factor is 0, similar to the condition already implemented [here](https://github.com/odoo/odoo/blob/18.0/addons/account/models/account_tax.py#L562) in the code.
tbg-1970
opw-5228357
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#234334This change prevents an error that could appear when users open payment-related invoice lists from batch payments. The system now applies a specific view option only where it is relevant, avoiding a mismatch between invoice and payment records and keeping the workflow smooth.
Original PR description
Repro: - Create DDM for a client - Create 4+ invoices for him - Pay with SEPA - Go to batch payment set it with SEPA - Add all the invoices and set the date to any date <5 days from today. - A yellow line will appear along with (View All).. / click it - From the view click on any payment. - Exception arises saying made_sequence_gap not found in account.payment Issue: made_sequence_gap belongs to 'account.move' incompatible with 'account.payment' causing the exception. Solution: Here the view_duplicated_moves_tree_js view is intended for account.move elements not for account.payment ones, So I included it only when the resModel is account.move. opw-5149260 Forward-Port-Of: odoo/odoo#233450
This update prevents certain spreadsheet actions from failing when they are run outside the normal calculation flow, such as in version history. It improves stability by avoiding unexpected errors when a currency setting is not available.
Original PR description
Some getters are (too) tied with the evaluation and sometimes take the liberty to throw evaluation-related errors. This can only work if the said getter is called exclusively in the within the…
Some getters are (too) tied with the evaluation and sometimes take the liberty to throw evaluation-related errors. This can only work if the said getter is called exclusively in the within the context of the evaluation (which has a splendid try/catch statement to this effect). Issues start to appear when we start using the said getters outside the evaluation and this is what happens. Since https://github.com/odoo/o-spreadsheet/issues/6083, we call the getter `getPivotCellFromPosition` which in specific cases call `getCompanyCurrencyFormat` and the latter will throw errors when starting and RPC. However, its effect was hidden by the sortcut added in https://github.com/odoo/odoo/pull/151725. The effect could only be seen in a version history action where we did not provide a default currency to the model config. This commit fixes the symptom but not the original cause: having getters that throw and are not handled in the components life-cycle. Such getters should probably disappear in a future refactoring. Task-5187293 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update stops website forms from saving temporary Turnstile loading states, such as the spinner and disabled button styling. It ensures forms stay clean and continue working normally even if the Turnstile module is later removed.
Original PR description
Steps to reproduce: 1. Install the `website_cf_turnstile` module. 2. Enter valid Cloudflare Turnstile credentials in the configuration. 3. Go to the Website Editor. 4. Add or edit a form (e.g.…
Steps to reproduce: 1. Install the `website_cf_turnstile` module. 2. Enter valid Cloudflare Turnstile credentials in the configuration. 3. Go to the Website Editor. 4. Add or edit a form (e.g. contact form) and save the page. 5. Notice that the form’s submit button temporarily shows a spinner and gets a 'disabled' class while Turnstile is initializing. 6. After saving the page, these temporary elements and classes (e.g. .turnstile-spinner and 'disabled') are incorrectly saved into the form’s HTML. 7. If you later remove or uninstall the website_cf_turnstile module, the submit button remains disabled and the spinner icon still appears, even though Turnstile is no longer active. After this commit: Now, when you save a website form in the editor, any temporary classes or elements added by Cloudflare Turnstile are removed. This prevents unwanted changes from being saved to forms. task-4951470 Forward-Port-Of: odoo/odoo#234730 Forward-Port-Of: odoo/odoo#221841
This update corrects how payment amounts are written in words on Philippine checks when there is a decimal part. It removes the trailing “ONLY” in those cases and standardizes the wording so checks follow the expected local format.
Original PR description
In phillipines, if any amount has centovas (decimal amount), the amount in words cannot contain 'ONLY' in the end. Additionally, changed 'And' -> 'and' for decimal amount. **task**-5155953 Forward-Port-Of: odoo/enterprise#98535
The search feature now measures text length after accents and similar marks are removed, so it no longer reads past the end of the cleaned-up text. This prevents incorrect search results and reduces the risk of errors for languages that use these marks, such as Thai.
Original PR description
The fuzzy search mechanism (specifically the _match utility) calculates the length of the string before normalizing it (e.g., with `unaccent`). However, `unaccent` can remove non-spacing marks (like Thai tone marks or vowels), which changes the length of the string. This mismatch caused the search loop to iterate past the end of the normalized string, leading to incorrect behavior or potential errors. This commit moves the length calculation to after the string has been unaccented, ensuring the loop has the correct bounds. opw-5189276 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234616 Forward-Port-Of: odoo/odoo#233249
Creating a new employee version now copies all relevant version details, so the new record keeps the same information as the original. The Group S duplicate check was also adjusted to validate per employee instead of per version, preventing overly strict errors when multiple versions belong to the same person.
Original PR description
## [FIX] hr*: make sure copy of a version copy all version fields This commit makes sure all the information of a version is completely duplicated when the user creates a new version from an existing version of an employee. ## [FIX] l10n_be_hr_payroll_group_s: move group S unicity constraint per employee Before this commit, the group S unicity constraint were per versions since before it was per contract. Now, since we no longer any contract model and more than version could represent the same contract, that constraint is a bit too restrictive. Moreover, the group S is more stored on the employee, so it would surely make more sense to trigger an error if 2 different employees have the same group S code. This commit moves the group S unicity constraint in hr.employee model to make sure we check per employee instead of per version.
This update fixes how employee version changes are recorded so edits made by users are correctly tracked, even when creating a new version at the same time. It also ensures all version details are copied consistently, preventing missing information or unintended side effects during version creation.
Original PR description
## [FIX] hr: track the fields updated when creating new version Before this commit, when the user alters an employee form view and then create a new version, if a version exists on that employee…
## [FIX] hr: track the fields updated when creating new version Before this commit, when the user alters an employee form view and then create a new version, if a version exists on that employee altered, it will copy the version with the changes made by the user at the same time and so no tracking values on the values changed by the user are created. This commit makes sure the changes made by the user are correctly tracked when a new version is created with some values given in parameter. ## [FIX] hr: add explanation how to change group on version fields in employee model ## [FIX] hr*: make sure copy of a version copy all version fields This commit makes sure all the information of a version is completely duplicated when the user creates a new version from an existing version of an employee. ## [FIX] hr: protect fields copied in create_version to avoid recomputing Before this commit, since now we do a write after the copy of a new version to be able to track the changes made by the user. We cannot guarantee the vals given to the write will trigger a compute method from a field copied. This commit makes sure the version fields copied will never be invalidated and only the fields inside the write (that is, the fields altered by the user) will be altered.
Sales orders will now be marked as invoiced when no further stock operations are expected on the delivery, even if the full ordered quantity was not shipped. This avoids orders staying open unnecessarily and better matches the actual delivery status seen by the business.
Original PR description
If no other operations are expected on the picking, even if the full quantity wasn't delivered, the order should be marked as invoiced. task-4607401 Fixes #144485 Partial revert of #115871 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234412 Forward-Port-Of: odoo/odoo#218322
This change makes sure tax templates are loaded only for root companies, not for branch subsidiaries. It prevents duplicate tax records from being created during setup, which helps keep tax data clean and avoids confusion later.
Original PR description
Adds parent_id check on the domain to ensure taxes are only loaded for root companies. This prevents duplicate tax creation on branch (child) companies when initializing tax templates. task-5176333 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#232679
This update fixes an issue that prevented PIN codes from being encoded correctly in the Belgian POS blackbox flow. It also improves error handling so the system responds more reliably when something goes wrong or succeeds after a retry.
Original PR description
Since the introduction of the queue mechanism in blackbox, the PIN encoding was not working. This was due to the fact that the blackbox driver trying to access some non-existing data. This is now solved and improved to better handle the error and subsequent error or success.
Pricelist rules created on a product variant are now saved correctly when you click Save. This prevents users from losing pricing changes and makes pricelist setup reliable.
Original PR description
steps to reproduce: ------------------- 1. Install sales 2. Enable Product Variants and Pricelists under Sales > Configuration 3. Open a product variant and create a pricelist rule 4. Save it issue:…
steps to reproduce: ------------------- 1. Install sales 2. Enable Product Variants and Pricelists under Sales > Configuration 3. Open a product variant and create a pricelist rule 4. Save it issue: ----- The pricelist rules are not saved. cause: ------ The field `pricelist_rule_ids` on `product.product` is a non-stored One2many. https://github.com/odoo/odoo/blob/b1041951d436b4b6adc90d8b8dd7b8c88cc69a46/addons/product/models/product_product.py#L62-L68 In the ORM, such fields are handled in the else part of [write_real()](https://github.com/odoo/odoo/blob/b1041951d436b4b6adc90d8b8dd7b8c88cc69a46/odoo/orm/fields_relational.py#L1033-L1049), Since this field is non-stored, it has no corresponding column in the database to persist changes. As a result, any updates made to it are lost after saving. solution: --------- Add an inverse method to make the field writable. opw-5097909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change prevents the messaging menu from crashing when a user opens the chat tab with a large number of conversations. It improves stability and responsiveness by simplifying how chat items are loaded and sorted.
Original PR description
Accessing the chat tab in the messaging menu with many chats causes a max call stack error. Threads in the messaging menu rely on the `menuThreads` store field, which depends on `thread.displayName`. - Thread display name is a getter which accesses `correspondent.name`, a computed field. - Accessing `thread.displayName` in a loop repeatedly triggers recomputation of `menuThreads`, eventually reaching max call stack size. - Additionally, `menuThreads` computation is inefficient due to sorting and reactive proxy access. To solve this issue: - Update `menuThreads` to use the inverse relation instead of a complex compute. - Debounce the array sort so it executes only once when the relation is fully filled. task-4794325 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When creating a new employee in a company, the default work address now comes from the active company instead of the current user's company. This prevents employees from being assigned the wrong company address when users work across multiple companies.
Original PR description
Steps to reproduce: - Open the Employee app. - Create a new employee in a company different from the current user's company. Issue: - The default address is taken from the current user's company instead of the active company's address. Fix: - Default address now uses the active company's address instead of the user's company. task-5138714 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures incoming emails are marked as read even when they cannot be matched to an Odoo record. As a result, the system will not keep reprocessing the same failing emails, which saves time and helps new messages be fetched normally.
Original PR description
# CONTEXT The refactor PR https://github.com/odoo/odoo/pull/191911 introduced a nice/needed refactor of the fetchmail methods. But in doing so a small logic error sneaked in. More specifically: This…
# CONTEXT The refactor PR https://github.com/odoo/odoo/pull/191911 introduced a nice/needed refactor of the fetchmail methods. But in doing so a small logic error sneaked in. More specifically: This try/except/else block https://github.com/odoo/odoo/blob/1f672b95a145b32d1ef2da9e83d82cd950045b5d/addons/mail/models/fetchmail.py#L305-L313 fails to account for the fact that in certain conditions a exception is expected while the `message_process` methods try to match the mail content with Odoo records. One example: If you fetch an email in the inbox that is addressed to an email address that is **not** an email alias in the database, it will raise a ValueError. Example: ``` ValueError: No possible route found for incoming message from "John Doe" <john@example.com> to "Josephine" <mon_amour@odoolove.com> (Message-Id <shrekislove@odoo.com>:). Create an appropriate mail.alias or force the destination model. ``` It follows that the `else` block is never triggered and `handled_message` will not be called, which would have marked the email in question as "READ". This means, that the next time the fetchmail CRON job runs, it will retry to refetch the same (failing) emails, which A) means lost time and processing time for a non relevant email B) if the backlog of failing emails is important enough, it will clog the mail fetching and we will never reach new emails. ## Proposed fix: Remove the else block, meaning that the `handled_message` get's called even after an exception. A this level of the stack we presume that any exception is either expected or the results of a misconfiguration (mail flows or Odoo configuration). So the mail was handled and should be marked a read in the mailbox being fetched. OPW-5122869 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The invoice synchronization process could use the wrong company when handling invoices, which could lead to incorrect processing. This update separates invoices by company and syncs each group independently, helping ensure each invoice is handled in the right company context.
Original PR description
The sync process previously used the wrong company when synchronizing invoices. This fix groups invoices by their respective companies and performs the sync for each company individually. task-5207338 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Time Off dashboard now correctly shows an employee’s Extra Hours allocation when attendance generates overtime. This fixes a visibility issue so managers and employees can see the full balance they are entitled to.
Original PR description
### Steps to reproduce: - Install Attendance and Time off apps - Create some attendance with extra hours for the employee - Go to the employee's time off dashboard - Notice Extra Hours allocation is not shown ### Cause: When we are getting the allocation data we check for the leave types that require allocation https://github.com/odoo/odoo/blob/5f6d2afa8c09fe72c01d056ebef01214567a4a99/addons/hr_holidays/models/hr_leave_type.py#L473 And then when checking the types that doesn't require allocation we are looping on the res that we got from the super which already excluded those types https://github.com/odoo/odoo/blob/5f6d2afa8c09fe72c01d056ebef01214567a4a99/addons/hr_holidays_attendance/models/hr_leave_type.py#L41-L43 ### Fix: We loop over the self leave types to make sure we are getting all of the employee's leave data whether the type requires allocation or not. opw-5042325 Forward-Port-Of: odoo/odoo#234426 Forward-Port-Of: odoo/odoo#225015
When a chat window is opened, the chat hub now resets to a safe position and cannot be dragged while chat windows are open. This prevents the hub from being covered up and makes it consistently accessible to users.
Original PR description
Prior to this commit, moving the chat hub could cause newly opened chat windows to appear on top of it, rendering the hub invisible and unusable. This commit fixes the issue by resetting the chat hub's position whenever a chat window opens and disabling its drag functionality while any chat window remains open. task-5227499 Forward-Port-Of: odoo/odoo#234367
This fix ensures customers receive the expected email when an order status update comes back from Gelato. It prevents missed notifications so order communication stays consistent and customers are kept informed.
Original PR description
Fix not sending the email to customer, when order status update was received from Gelato. opw-4962878 Forward-Port-Of: odoo/odoo#234017 Forward-Port-Of: odoo/odoo#233587
This update prevents a crash when tracking changes on linked records that do not have a display name. Instead of failing, the system now falls back to a safe default, matching the behavior already used in similar situations.
Original PR description
Description of the issue/feature this PR addresses: Addresses: https://github.com/odoo/odoo/issues/178883 Same issue is also in 18.0. Is there a separate PR necessary or will this be ported forward? Current behavior before PR: An error is displayed when tracking is activated on one2many and many2many with records without display_name. Desired behavior after PR is merged: Should not crash and use fallback like in other cases. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#214121
The live chat dashboard now excludes unrated sessions when calculating the rating percentage. This makes the displayed score match the reporting view more closely and gives managers a more reliable view of customer satisfaction.
Original PR description
**Description of the issue this PR addresses:** ------------------------------------------------ Before this change, the live chat rating percentage in the dashboard included sessions that were not rated, which made the overall rating misleading. While the sessions reporting view allowed filtering on "rating is set", the dashboard did not provide this option. **Current behavior before PR:** --------------------------------- - Unrated sessions are included in the dashboard rating percentage - The percentage is misleading compared to the sessions reporting view **Desired behavior after PR is merged:** ----------------------------------------- - The dashboard rating percentage only considers sessions with a rating - Unrated sessions are excluded, resulting in a more accurate rating display **Task:** 5048700 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227474
This update fixes an error that could happen when opening very large Excel files and converting them into Odoo spreadsheets. It helps users work with big documents more reliably, avoiding unexpected crashes during import.
Original PR description
Steps to reproduce: - upload a large xlsx file (e.g. with >1000 sheets) - open it and convert it to o-spreadsheet => traceback Task: 5222481 Forward-Port-Of: odoo/enterprise#98482 Forward-Port-Of: odoo/enterprise#98443
This change resolves an error that could block confirming or adjusting a manufacturing order created from the Bill of Materials overview when the product has a two-level BoM. Users can now proceed normally with the manufacturing order, without being interrupted by this issue.
Original PR description
This PR fixes the error that occurs when confirming an MO from the BoM overview for a product with a 2 level BoM.
Bug Reproduction:
1- Create BoM for a Main Product.
2- Create a child BoM for any component in the main Product's BoM and make that component have an MTO route.
3- Navigate to the BoM Overview of the Main Product.
4- Click "Manufacture" to create an MO for the Main Product.
5- Click the save icon in the MO.
6- There are two scenarios to reproduce the error now:
a- Confirm the MO form.
b- Or update the quantity to produce in the MO.
= The confirmation or update of the MO is blocked, it should be allowed.
The Issue:
A dirty context is being passed from the BoM overview. it sets the `default_product_qty` to be set in the MO. However, when creating the moves necessary for the MO, this makes an issue as `product_qty` should never be set in stock moves, we set `product_uom_qty` instead.
Task-4795105
Forward-Port-Of: odoo/odoo#214305This change prevents repeated IoT event requests from staying open when users switch in and out of a device view. It helps avoid browser connection limits being reached, so the IoT screen remains reliable during normal use.
Original PR description
Steps to reproduce: 1. Pair an IoT box 2. In the IoT form view, click on any device, then click back to return to the IoT form view. 3. Repeat this step multiple times. If you have devtools open, you can see a `/event` fetch request every time you open the device form. Expected behaviour: - When a new request is made, the previous request is cancelled. Actual behaviour: - The previous requests remain active, and eventually no further requests are possible due to browser limits. This behaviour was broken when the longpolling was changed to use the `fetch` method instead of Odoo's `rpc` method. This commit restores the behaviour by using an `AbortController` instance which is aborted when `stopPolling` is called. Manual Forward Port of Enterprise PR: https://github.com/odoo/enterprise/pull/98985 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#234872
This update makes VAT return checks faster by removing a slow validation and replacing it with a clearer warning when negative amounts are present. It also fixes access issues for companies with branches, so users can refresh and submit returns only when they have the right company access, and the report now uses the correct company currency.
Original PR description
The "No negative amount in VAT report" return check was too slow, we removed it and clean the database. On the other hand, refreshing checks had issues with the access rights when there was company branches. task-id: 5145537 Forward-Port-Of: odoo/enterprise#97125
When a contact has more than one email address, the chatter now correctly matches the existing contact instead of treating the extra address as a new person. This prevents duplicate contact creation when users send a message from the Contacts app.
Original PR description
**Steps to reproduce:** - Go to the `Contacts` app - Create a new contact - Add multiple emails in the email field (e.g. `"test1@example.com,test2@example.com"`) - Click on `Send Message` button in…
**Steps to reproduce:** - Go to the `Contacts` app - Create a new contact - Add multiple emails in the email field (e.g. `"test1@example.com,test2@example.com"`) - Click on `Send Message` button in the chatter - Default recipients are computed for each email - One of them match the contact, the other doesn't but still pass to the badges list - When sending a message, the second mail is considered as a new contact to create **Issue:** Emails coming from an email field with multiple emails are considered separately when added in the chatter recipients. The partner only match the first one which means that the second one creates a duplicate. This seems to be the default behavior when receiving an email from the additional email address of a partner (`If an email is not unique (e.g. multi-email input), only the first found valid email in input is considered.`), but automatically filling the recipients badges in this way seemed unintended. **Fix:** Properly parsed the email field of recipients to match the partner and avoid creating a duplicate when sending a message on a contact page. opw-4929564 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220593