Daily updates from Odoo
Tuesday, July 28, 2026
41 changes · saas-19.1
Enhancements to existing features
Pakistan payroll rules have been updated to apply the latest 2026 income tax brackets. The previous extra tax surcharge mechanism has been removed, helping payroll calculations stay aligned with current tax requirements.
Original PR description
[IMP] l10n_pk_hr_payroll: update 2026 tax brackets . tax brackets are updated . extra tax surcharge mechanism is deleted task-6401729 Forward-Port-Of: odoo/enterprise#124988
Bank reconciliation now alerts users when they reconcile a transaction with a partner different from the one already linked to the bank statement line. This helps users decide whether to move the saved bank account to the newly selected partner, reducing accidental partner/account mismatches.
Original PR description
Add a new notification in the bank reco widget when a user do a reconciliation with a partner different from the one on the st_line. The idea is to let the user chose if he wants to move the bank account from the st_line partner to the move he tries to reconcile. task-6303397 Forward-Port-Of: odoo/enterprise#120900
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Chan
Original PR description
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Change Password URL specification by exposing a public route that redirects to `/web/reset_password`. Reference: https://wicg.github.io/change-password-url/ --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277575
Resolved issues and error corrections
AI-generated replacements now preserve separate lines when updating checklist or list content, so translated or rewritten items do not get merged into one entry. The change also improves how AI remembers selected text without adding hidden layout elements, reducing visual glitches when working with longer selections.
Original PR description
When replacing text within a list, text is inserted as a sequence of text nodes. Because of this, all lines end up inside the same list item. This commit puts further lines of the AI response into paragraphs in order to have them end up in distinct list items. Steps to reproduce: - Go to the default "To Do" note - Select a few lines of the checkbox list - Click on the AI button in the toolbar - Ask to "translate to French" - Use this => All translated lines ended up on a single line. task-6364282
This update prevents occasional errors when the Sign document preview closes or reloads at the same time it is being prepared. It improves reliability in automated testing and reduces the chance of users encountering intermittent failures while opening signing requests.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
Ecuador branch users can now create customer invoices without being blocked by an access error. The fix avoids requiring access to the parent company when checking the journal country, keeping normal invoicing workflows working in branch setups.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
The expense Stripe cardholder field now uses the standard setup for selecting related records. This ensures any selection rules configured in the view are applied correctly, helping users see the right cardholder options.
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 Forward-Port-Of: odoo/enterprise#125346
The Twitter integration now disables the reply option when Twitter rules do not allow a response, such as when the account was not mentioned or the post does not quote one of its tweets. This helps prevent failed or inappropriate replies and reduces the risk of automated messages being sent where they are not permitted.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#123214 Forward-Port-Of: odoo/enterprise#112161
The AI assistant guidance was cleaned up to remove misleading labels that could cause it to request a non-existent search action. This reduces avoidable agent failures and helps AI features behave more consistently.
Original PR description
Purpose: -------- Agents occasionally fail by trying to call a `search` tool that does not exist. This seems to come from the `Tool Name: search` header in the tool description, which can be confused with the actual tool name used by the LLM, i.e. the tool xmlid. This commit removes these headers from the search and read group tool descriptions. They were missed in [this commit](https://github.com/odoo/enterprise/commit/912bce43a98d45e90dbd24328fa2f46caba4c887 ), which removed the same headers from the other tools. Task-6401285 Forward-Port-Of: odoo/enterprise#125110
The Belgian Partner VAT Listing now always covers the required civil calendar year, from January 1 to December 31. This prevents incorrect reporting periods for companies whose fiscal year does not match the calendar year, helping improve compliance accuracy.
Original PR description
The Belgian Partner VAT Listing must always report on the civil calendar year (01/01/N to 12/31/N). Previously, the report was relying on the company's fiscal year configuration, which caused incorrect reporting periods for companies with non-calendar fiscal years. This commit overrides `_custom_options_initializer` to strictly enforce a civil year date range based on the selected year, entirely ignoring custom fiscal year boundaries. Task-6086513 Forward-Port-Of: odoo/enterprise#114337
The barcode app now shows the package type selection prompt when users choose Put in Pack and the delivery operation requires a package type. This prevents warehouse users from creating packages without the expected type and keeps barcode workflows aligned with standard inventory behavior.
Original PR description
### Steps to reproduce: - In the settings enable: Packages - On the operation type `Delivery Order` set "Set Package Type" - Create and confirm a delivery for 1 unit of a product P + reserve it - Got…
### Steps to reproduce: - In the settings enable: Packages - On the operation type `Delivery Order` set "Set Package Type" - Create and confirm a delivery for 1 unit of a product P + reserve it - Got to the barcode app to process the delivery - Scan your product and click "put in pack" #### > The put in pack wizard allowing you to set a package type on the new package does not pop up. ### Cause of the issue: As a general rule of thumb the wizard is suppose to be displayed when the option is enabled and when a package/package type is not already provided to the call: https://github.com/odoo/odoo/blob/5dbc448d336c7ff22803ae91d5014eb6d0a07234/addons/stock/models/stock_package.py#L332-L341 https://github.com/odoo/odoo/blob/5dbc448d336c7ff22803ae91d5014eb6d0a07234/addons/stock/models/stock_move_line.py#L1236-L1238 However an override was added to the barcode module so that the wizard is never displayed when the action is launched from the barcode app: https://github.com/odoo/enterprise/blob/673d449f38cd3eff27c44270c8f7edf91d0ecd02/stock_barcode/models/stock_move_line.py#L193-L196 The idea behind this override was that you could provide the package type id via scans and hence that is was not necessary. However, if you click directly on the put in pack button, the wizard still make sense and should therefore be displayed under the same conditions. opw-6325092 Forward-Port-Of: odoo/enterprise#122308
This fixes an error that could occur when workers proposed adding a step from the Shop Floor for manufacturing orders with very similar operations. The change helps ensure improvement suggestions can be submitted reliably in Product Lifecycle Management workflows.
Original PR description
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback…
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback when proposing an improvement from the Shop Floor. **Steps to reproduce** - Install the Product Lifecycle Management app. - Create a BOM for any product with two operations that: - Have the same name and work center - Have no variant - Create and confirm a Manufacturing Order for that product. - Open the Shop Floor view. - Click the gear icon -> Update Instructions -> Improvement Suggestion -> Add a Step -> Propose a Change. -> A traceback occurs **Cause** When adding a step: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L10 It tries to find the corresponding operation in the ECO's new BoM. This relies on `_get_sync_values()`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_plm/models/mrp_routing.py#L9-L13 Because two operations share the same name, work center, and no variant, both match the filter: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L39 This results in a singleton error when accessing `operation.id`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L42 opw-6241880 Forward-Port-Of: odoo/enterprise#119404
Guatemalan credit notes now reference the original invoice’s actual issue date instead of a technical processing timestamp. This helps prevent tax authority rejections and keeps electronic documents aligned with SAT validation requirements.
Original PR description
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification…
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification date instead of the original invoice's emission date. This causes the SAT to reject the document. ### Steps to reproduce the issue: 1. Download Accounting and l10n_gt 2. Revert an invoice (credit note) inserting a different date than the one of the invoice 3. See that FechaEmisionDocumentoOrigen report the date of the credit note instead of the one of the invoice ### Cause of the issue: The _l10n_gt_edi_add_reference_values method extracted the date from original_document.datetime (the technical timestamp of when the XML was generated) rather than using the actual accounting date of the original invoice. ### Reason to introduce the fix: SAT validation rules strictly require the reference date to match the exact commercial emission date of the original invoice. Fetching invoice_date directly ensures compliance, avoids timezone conversion errors, and prevents the XML from being rejected. Source: https://www.lawinsider.com/es/contracts/dJXl4Vo79L2 <img width="730" height="205" alt="2026-07-17_10-19" src="https://github.com/user-attachments/assets/802e7bb3-fcf9-48db-b86f-227b494001b6" /> opw-6394409 Forward-Port-Of: odoo/enterprise#124794
Deleting a quality check in the middle of a manufacturing work order now keeps the remaining checks connected. This prevents later quality checks from disappearing from the shop floor, helping operators complete all required inspections.
Original PR description
Steps to reproduce the bug: - Create a BOM for product P1 with one work order WO1 - Create 3 quality points linked to WO1 via the `operation_id` field - Confirm a manufacturing order for P1: - 3…
Steps to reproduce the bug:
- Create a BOM for product P1 with one work order WO1
- Create 3 quality points linked to WO1 via the `operation_id` field
- Confirm a manufacturing order for P1:
- 3 quality checks A → B → C are generated
- Open the shop floor for the work order:
- Observe that all 3 quality checks are displayed
- Delete quality check B (the middle one)
- come back to the shop floor for the work order:
- Observe that quality check C is no longer displayed in the shop floor
Problem:
After deleting check B, check C disappeared from the shop floor. Quality checks are stored as a doubly-linked list via the `next_check_id` and `previous_check_id` fields on `quality.check`. The shop floor JS (`mrp_display_record.js`) traverses this list starting from the check with no `previous_check_id`, then follows `next_check_id` until the chain ends. When check B was deleted, it nullified the FK references pointing to it, leaving check A with `next_check_id = False` and check C with `previous_check_id = False`. The traversal from A therefore stopped immediately, and C was never reached.
No `unlink` override existed on `quality.check` to repair the chain before deletion.
Solution:
Added an `unlink` override that, before deleting each check, reconnects its predecessor and successor: if the deleted check has both a previous and a next, `prev.next_check_id` is set to `next` and `next.previous_check_id` is set to `prev`, preserving a valid chain for the remaining checks.
opw-6369298
Forward-Port-Of: odoo/enterprise#124118Malaysia Statement of Account reports now calculate total and overdue amounts using the selected statement date. This ensures the PDF totals match the displayed balance lines, improving accuracy for past-date customer account reporting.
Original PR description
## Current behavior: In Malaysia's Statement of Account, the total and total overdue amounts dont consider the selected Statement Date, and will calculate all the balances up until today in the…
## Current behavior: In Malaysia's Statement of Account, the total and total overdue amounts dont consider the selected Statement Date, and will calculate all the balances up until today in the generated PDF report ## Expected behavior: The total and total overdue amounts should only sum the balances included in the report up until the selected Statement Date ## Steps to reproduce: 1. Install l10n_my_reports module, switch to Malaysian company 2. Go inside Invoicing > Report > Aged receivable 3. Select a specific date in the past 4. Observe that the total amounts dont match with the balance column, and wont change regardless of the date selected ## Cause of the issue: The template used o.total_overdue which ignores the report domain and statement date ## Fix: Accumulate overdue_total in the template loop with the same domain and date_to cutoff as the balance lines, so it always matches the displayed Balance lines for the selected Statement Date opw-6332970 Forward-Port-Of: odoo/enterprise#123694
The US payroll localization now installs through the standard automatic installation process instead of a later setup hook. This prevents upgrade timing issues where payroll localization modules could be treated as not installed until payroll finished loading.
Original PR description
In a [previous PR], a test was introduced to reject any `l10n_xx_hr_*` module that has a `countries` key in its manifest and depends on a module that also has that country key. This test was too…
In a [previous PR], a test was introduced to reject any `l10n_xx_hr_*` module that has a `countries` key in its manifest and depends on a module that also has that country key. This test was too broad and rejected some valid cases: 1. A non-auto-install module can have a country key defined to add flags in the apps kanban view. ([src]) 2. A module that has a country-specific regular dependency, but not as an auto-install condition. The second case is illustrated by [l10n_us_hr_payroll], which should auto-install when `hr_payroll` is installed and a US company exists. With the old test, achieving this required adding `l10n_us` to its auto-install dependencies. But, since `l10n_us` is not auto-installable, `l10n_us_hr_payroll` would not be installed if you create a DB with a US company and only install `hr_payroll`. In practice, that module was still being installed via a [post-init hook] in `hr_payroll`. This hook was installing all `l10n_XX_hr_payroll` modules for each country where a company is located, which is the behavior of the `countries` parameter in the manifest. This caused issues during upgrades as this runs late in the process: after the auto-discovery phase. Modules installed by this hook would be considered as `uninstalled` until `hr_payroll` is loaded. This commit narrows the check to only fail if: - A module has a `country` key in its manifest, and - It has a country-specific module in its **auto-install** dependencies. Moreover, it modifies `l10n_us_hr_payroll` to correctly rely on the auto_install mechanism instead of the post-init hook. [previous PR]: https://github.com/odoo/enterprise/pull/101843 [src]: https://github.com/odoo/odoo/blob/6df9f92a537aa4bb4ee5dc946fe31c4e56e6dfea/odoo/addons/base/models/ir_module.py#L271-L273 [l10n_us_hr_payroll]: https://github.com/odoo/enterprise/blob/24a33ffb769557be498d61328522bb77f68d3a5a/l10n_us_hr_payroll/__manifest__.py [post-init hook]: https://github.com/odoo/enterprise/blob/85185595cfd1ee5310ceb9dc80c0589accad2f19/hr_payroll/__init__.py#L21
The scheduled payroll data update for Australian payroll now restores required salary rule category data before updating salary rules. This prevents an error when users have deleted payroll rule categories, keeping routine payroll maintenance actions running reliably.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the `Australian Company`. - Go to `Scheduled Actions` and run `Payroll: Update Data`. `ValueError: External ID not found in the system: l10n_au_hr_payroll.rule_category_ote` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], an error is raised due to the missing rule category. This commit ensures that when updating the salary rule data, it updates the category data beforehand as like [here] [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1] https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_au_hr_payroll/models/hr_payslip.py#L76-L83 [here]: https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_ch_hr_payroll/models/hr_payslip.py#L1074-L1087 sentry-7349905716
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solu
Original PR description
Steps to reproduce: - Install `l10n_cl` module - Create one branch of the CL company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, temporary `sudo()` usage is required in specific places. opw-6087460 Forward-Port-Of: odoo/odoo#259299
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 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.odo
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278123
Steps to reproduce the bug: - Load a database without demo data - Install `auth_ldap` - Run the `TestAuthLDAP.test_auth_ldap` test Problem: The test failed with a 404 error on `POST /web/login`: `requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://127.0.0.1:8069/web/login`. The mocked `_get_ldap_dicts` hardcoded the LDAP config's template `user` as `(6, "Marc Demo")`, assuming the demo user `base.user_demo` exists with that id. Without demo data, `res.users(6,)`
Original PR description
Steps to reproduce the bug: - Load a database without demo data - Install `auth_ldap` - Run the `TestAuthLDAP.test_auth_ldap` test Problem: The test failed with a 404 error on `POST /web/login`: `requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: http://127.0.0.1:8069/web/login`. The mocked `_get_ldap_dicts` hardcoded the LDAP config's template `user` as `(6, "Marc Demo")`, assuming the demo user `base.user_demo` exists with that id. Without demo data, `res.users(6,)` does not exist, so `_get_or_create_user`'s `SudoUser.browse(conf['user'][0]).copy(...)` raised a `MissingError`, which Odoo's HTTP dispatcher turns into a 404. Solution: Create a dedicated "user template" at the start of the test and use it as the LDAP template user, instead of hardcoding a demo-data record id. This makes the test self-contained and independent of whether demo data is loaded. runbot-243648 Forward-Port-Of: odoo/odoo#277463
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the return
Original PR description
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the returned combination was correct. The 0.5s threshold is an arbitrary sanity check meant to catch a gross algorithmic regression (e.g. loss of early pruning of invalid combinations), not a strict performance SLA, so it is too tight to survive normal CI load variance. Solution: Raise the threshold to 2 seconds, keeping enough margin to absorb CI load variance while still catching a real performance regression, which would take far longer than the current computation. runbot-243606
You'll need two users : - Internal User A that can create projects - User B with a granted portal access Optionnal third user to compare the flows : - Internal User B that can create tasks in a porject - With User A, create a new project with atleast a single stage - Go to the project settings - Make sure that Visibility is set to : "All internal users and invited portal users" - Click on Share Project - Add User B as a new Collaborator with the Edit acess mode - Confirm by clic
Original PR description
You'll need two users : - Internal User A that can create projects - User B with a granted portal access Optionnal third user to compare the flows : - Internal User B that can create tasks in a…
You'll need two users : - Internal User A that can create projects - User B with a granted portal access Optionnal third user to compare the flows : - Internal User B that can create tasks in a porject - With User A, create a new project with atleast a single stage - Go to the project settings - Make sure that Visibility is set to : "All internal users and invited portal users" - Click on Share Project - Add User B as a new Collaborator with the Edit acess mode - Confirm by clicking on Share Project - Still in the project settings, click on the blue user icon in the top right to edit the Followers : - Make sure you are following the project - Click on the edit button and make sure Task Created is checked Optionnal for easiness of testing : - Go to the User A settings and in Preferences > Notifications : In Odoo - Log in with User B (in a new incognito tab on the side is best) - Go to Projects > The project that has been shared - Create a new task No notification is sent to User A. If the same flow is done using User C, then a notification is correctly sent. The fields that determine to which users the notifications are sent to is `message_follower_ids`. In our case, the value of that field does not contain User A, so no notifcation is sent to them. The method responsible for assigning values to that field is `_message_auto_subscribe()` which adds follower using subtypes parent relationship. The parent subtype of tasks are projects. So, essentially, we look for followers of the parent project, and see if we can add them to our task. Before proceeding with the assignation, we check that the parent subtype's field was actually edited : https://github.com/odoo/odoo/blob/ea18f34a48d61350f80c79894bef66bf02840bfc/addons/mail/models/mail_thread.py#L4778-L4781 So we look that `updated_values` contains "project_id". `updated_values` is created by the the `mail_thread` create method by joining the values in `vals_list` and the context default variables. In our case, this should be enough since `default_project_id` is provided when creating a task : https://github.com/odoo/odoo/blob/ea18f34a48d61350f80c79894bef66bf02840bfc/addons/mail/models/mail_thread.py#L340-L344 But, a bit before this, the task create method edits the context to replace 'default_project_id' by 'default_create_in_project_id' : https://github.com/odoo/odoo/blob/ea18f34a48d61350f80c79894bef66bf02840bfc/addons/project/models/project_task.py#L1102-L1109 So we do not detect that `project_id` has been changed and don't actually add the followers. We remove the custom 'default_create_in_project_id` context opw-6026932 Forward-Port-Of: odoo/odoo#278353
When a POS order is invoiced after its session has been closed, `_create_misc_reversal_move` builds a misc entry that reverses the portion of the closing entry corresponding to that order. It does so by negating `balance` and `amount_currency` on every prepared line, but leaves `tax_base_amount` on tax lines untouched. As a result the reversal move ends up with tax lines whose `balance` sign is flipped relative to the source order while `tax_base_amount` keeps the source sign, breaking the in
Original PR description
When a POS order is invoiced after its session has been closed, `_create_misc_reversal_move` builds a misc entry that reverses the portion of the closing entry corresponding to that order. It does so…
When a POS order is invoiced after its session has been closed, `_create_misc_reversal_move` builds a misc entry that reverses the portion of the closing entry corresponding to that order. It does so by negating `balance` and `amount_currency` on every prepared line, but leaves `tax_base_amount` on tax lines untouched. As a result the reversal move ends up with tax lines whose `balance` sign is flipped relative to the source order while `tax_base_amount` keeps the source sign, breaking the invariant `sign(balance) == sign(tax_base_amount)` that holds for every other correctly-generated tax line in the system. Downstream, any report reading `tax_base_amount` directly (Audit view from the Tax Report, Journal Items XLSX export, custom exports) shows a base amount signed for the wrong direction alongside a debit/credit of the opposite sign, which is confusing and, for tax returns computed from `tax_base_amount`, incorrect. Negate `tax_base_amount` alongside `balance` and `amount_currency` so the reversal move stays internally consistent. opw-5975658 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276534
A deferred toolbar update can still fire after the ToolbarPlugin has been destroyed. The global "mouseup" handler re-arms `updateToolbar` through a raw setTimeout that is not cancelled by `destroy`, so `_updateToolbar` runs on a plugin whose editable document has been detached. At that point `this.document.defaultView` is null and `getFilteredTargetedNodes` crashes with: TypeError: Cannot read properties of null (reading 'getComputedStyle') Cancelling the debounced updates in `destroy`
Original PR description
A deferred toolbar update can still fire after the ToolbarPlugin has been destroyed. The global "mouseup" handler re-arms `updateToolbar` through a raw setTimeout that is not cancelled by `destroy`, so `_updateToolbar` runs on a plugin whose editable document has been detached. At that point `this.document.defaultView` is null and `getFilteredTargetedNodes` crashes with:
TypeError: Cannot read properties of null (reading 'getComputedStyle')
Cancelling the debounced updates in `destroy` is not enough: `cancel()` only clears the currently pending timer, it does not disable the debounced function, so the post-destroy `updateToolbar()` call re-schedules it.
Guard `_updateToolbar` with the plugin's `isDestroyed` flag instead, which covers every deferred entry point.
Forward-Port-Of: odoo/odoo#278244When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get matched to the first PO line only. The remaining PO line(s) stay unmatched and are then added back to the bill as new (duplicate) lines. Steps: - Create a purchase order with two lines for the same product and confirm - Create a draft bill with the same configuration and same partner - From the PO,
Original PR description
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get…
When matching Purchase Order lines with Vendor Bill lines from the Bill Matching view, if a PO and its vendor bill each contain several lines for the same product, all bill lines of that product get matched to the first PO line only. The remaining PO line(s) stay unmatched and are then added back to the bill as new (duplicate) lines. Steps: - Create a purchase order with two lines for the same product and confirm - Create a draft bill with the same configuration and same partner - From the PO, click on "Bill matching" button - Select the 4 lines and click on the "Match" button -> On the purchase order, first line has qty_invoiced == 2 and the second one 0 -> On the bill, there is an additional line with 0 quantity This is because we only match the first order line in case of having more than one line with the same product. Then we add the remaining order lines to the bill. With this commit we match each line that need to be matched and we add lines to the bill only if all order lines have been invoiced. opw-6279755 Forward-Port-Of: odoo/odoo#277067 Forward-Port-Of: odoo/odoo#269496
Steps to reproduce the bug: - Install l10n_ke_edi_oscu_stock - Run Test_sale_mrp_kit_bom_cogs Problem: ```self.assertAlmostEqual(stock_out_aml.credit, 1.53, msg="Should not include the value of consumable component") AssertionError: 3.07 != 1.53 within 7 places (1.5399999999999998 difference) : Should not include the value of consumable component ``` The test delivered 1 whole unit of every component of Kit A regardless of the fractional quantity actually needed to produce a single kit
Original PR description
Steps to reproduce the bug: - Install l10n_ke_edi_oscu_stock - Run Test_sale_mrp_kit_bom_cogs Problem: ```self.assertAlmostEqual(stock_out_aml.credit, 1.53, msg="Should not include the value of…
Steps to reproduce the bug: - Install l10n_ke_edi_oscu_stock - Run Test_sale_mrp_kit_bom_cogs Problem: ```self.assertAlmostEqual(stock_out_aml.credit, 1.53, msg="Should not include the value of consumable component") AssertionError: 3.07 != 1.53 within 7 places (1.5399999999999998 difference) : Should not include the value of consumable component ``` The test delivered 1 whole unit of every component of Kit A regardless of the fractional quantity actually needed to produce a single kit (0.34/0.14/0.2 units for Component A/B/BB respectively). This went unnoticed under the default invoice_policy 'order', since qty_delivered never drives the invoiced quantity in that case. l10n_ke_edi_oscu_stock forces invoice_policy to 'delivery' for storable products that have no explicit company_id, which is the case for the products created in this test. With invoice_policy 'delivery', _compute_kit_quantities() correctly reads the over-delivered components as enough stock to form 2 complete kits (min ratio 2.94, floored to 2) instead of 1, doubling the invoiced quantity and the resulting COGS (3.07 instead of 1.53). runbot-243633 Forward-Port-Of: odoo/odoo#277519
Some partners were registered on Peppol with EAS 9925 (Belgian VAT) but have since moved to 0208. They became unreachable via Peppol because we never check if they exist on the network with EAS 0208, which makes their status `not_valid`. This fix forces the re-checking of the status with EAS 0208 for partners having EAS 9925 and a `not_valid` status. task-6296017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276879
Original PR description
Some partners were registered on Peppol with EAS 9925 (Belgian VAT) but have since moved to 0208. They became unreachable via Peppol because we never check if they exist on the network with EAS 0208, which makes their status `not_valid`. This fix forces the re-checking of the status with EAS 0208 for partners having EAS 9925 and a `not_valid` status. task-6296017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276879 Forward-Port-Of: odoo/odoo#270742
The image crop tests could fail non-deterministically because the cropper bundle is not yet loaded. As a result, waiting for the cropper does not guarantee that the cropper has finished initializing. Introduce a `waitForCropperReady()` helper that resolves once `ImageCrop.show()` has completed, ensuring that the cropper is fully initialized before the tests continue. runbot- 937826 Forward-Port-Of: odoo/odoo#278037
Original PR description
The image crop tests could fail non-deterministically because the cropper bundle is not yet loaded. As a result, waiting for the cropper does not guarantee that the cropper has finished initializing. Introduce a `waitForCropperReady()` helper that resolves once `ImageCrop.show()` has completed, ensuring that the cropper is fully initialized before the tests continue. runbot- 937826 Forward-Port-Of: odoo/odoo#278037
Following odoo/odoo#230736, the function now includes in its count the leaves that have no calendar, regardless of the company. This commit fixes this by grouping them by company as well, and including that count. 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
Original PR description
Following odoo/odoo#230736, the function now includes in its count the leaves that have no calendar, regardless of the company. This commit fixes this by grouping them by company as well, and including that count. 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
Steps to reproduce the bug: - Create a purchase requisition: - add any storable product and vendor - From it, create a purchase order and confirm it -> a picking is created - Cancel the "purchase.requisition" Problem: The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it. In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs,
Original PR description
Steps to reproduce the bug:
- Create a purchase requisition:
- add any storable product and vendor
- From it, create a purchase order and confirm it -> a picking is created
- Cancel the "purchase.requisition"
Problem:
The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it.
In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs, with no check on their current state or on whether picking or invoices existed.
Solution:
Only cancel linked purchase orders that are still in 'draft' state. Once
outside of that state, the purchase process might be too far engaged to
simply cancel the purchase order without notice.
opw-6329742
Forward-Port-Of: odoo/odoo#272190### Issue: In the tax report, lines linked to the T section show 0 and a danger warning is displayed after posting an invoice with a tax using a `T_base` tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The T formulas were not updated accordingly, causing their values to be negative instead of positive `_customize_warnings` compares the sum of `08+09+9B+10+11+T1->T7` against `A1+A2+A3+B2+B3+B4` With incorrect signs on T lines, the sums no longe
Original PR description
### Issue: In the tax report, lines linked to the T section show 0 and a danger warning is displayed after posting an invoice with a tax using a `T_base` tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The T formulas were not updated accordingly, causing their values to be negative instead of positive `_customize_warnings` compares the sum of `08+09+9B+10+11+T1->T7` against `A1+A2+A3+B2+B3+B4` With incorrect signs on T lines, the sums no longer match and a danger warning is displayed above the report ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: A1 and T1_base, 100 of tax: T1_taxe) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, a red warning is raised: Sum of 08+09+9B+10+11+T1->T7 is not equal to sum of A1+A2+A3+B2+B3+B4 opw-6357703 Forward-Port-Of: odoo/odoo#276446
[FIX] website_hr_recruitment: fix country filter Bug reproduction: 1 - Recruitment, you need to have 1 remote and 1 US jobs at least. 2 - Go to job page in website, activate country filter. 3 - Select US jobs and search for the remote job. 4 - All countries filter is readonly and it is not pressable. Bug cause: 1 - Check is done with jobs value 1.1 - If no matching, readonly button is displayed. Bug solution: 1 - count_per_filter is used instead of
Original PR description
[FIX] website_hr_recruitment: fix country filter Bug reproduction: 1 - Recruitment, you need to have 1 remote and 1 US jobs at least. 2 - Go to job page in website, activate country filter. 3 -…
[FIX] website_hr_recruitment: fix country filter
Bug reproduction:
1 - Recruitment, you need to have 1 remote and 1 US jobs at least.
2 - Go to job page in website, activate country filter.
3 - Select US jobs and search for the remote job.
4 - All countries filter is readonly and it is not pressable.
Bug cause:
1 - Check is done with jobs value
1.1 - If no matching, readonly button is displayed.
Bug solution:
1 - count_per_filter is used instead of jobs
1.1 - Even there are matchings for other countries, it shows.
2 - Also, searched keyword is added to filter url
2.1 - When there is search in other country and we click to it:
2.2 - The searched keyword will be still there.
task-6284436
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#277726### Steps to reproduce: - Create 2 companies: c1, c2 - Create 2 storable products: P, Comp - In c1 update the available qty of P to 10 units and its cost to 50 - In c2 create a kit bom for P: 1 x Comp - With c1 > Accounting > Review > inventory > Inventory Valuation #### > The total value of Super product is 0 instead of 500 ### Cause of the issue: The total value of the product will be set to 0 since the `qty_available` of the product is incorrectly computed to be 0: https://gith
Original PR description
### Steps to reproduce: - Create 2 companies: c1, c2 - Create 2 storable products: P, Comp - In c1 update the available qty of P to 10 units and its cost to 50 - In c2 create a kit bom for P: 1 x…
### Steps to reproduce: - Create 2 companies: c1, c2 - Create 2 storable products: P, Comp - In c1 update the available qty of P to 10 units and its cost to 50 - In c2 create a kit bom for P: 1 x Comp - With c1 > Accounting > Review > inventory > Inventory Valuation #### > The total value of Super product is 0 instead of 500 ### Cause of the issue: The total value of the product will be set to 0 since the `qty_available` of the product is incorrectly computed to be 0: https://github.com/odoo/odoo/blob/cb7b3de6cea07464bcadd1325f52533d34ce09bc/addons/stock_account/models/product.py#L240-L243 This happens because the `_find_bom` used in the override of the `_compute_quantities_dict` in mrp does not consider take the contextual company into account: https://github.com/odoo/odoo/blob/cb7b3de6cea07464bcadd1325f52533d34ce09bc/addons/mrp/models/product.py#L271-L289 and hence considers incorrectly that the product is a kit. ### Note: We make the same company dependency as in the `is_kits` computation: https://github.com/odoo/odoo/blob/cb7b3de6cea07464bcadd1325f52533d34ce09bc/addons/mrp/models/product.py#L41-L47 opw-6361690 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276306
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist" snippet at the bottom of the page and click on a column. - Scroll up so the footer and the bottom of the snippet are not visible, and add a pricelist item with the "Add Product" option. - => The page scrolls to the new item, but a big white space appears at the bottom of the screen, as if we scrol
Original PR description
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist"…
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist" snippet at the bottom of the page and click on a column. - Scroll up so the footer and the bottom of the snippet are not visible, and add a pricelist item with the "Add Product" option. - => The page scrolls to the new item, but a big white space appears at the bottom of the screen, as if we scrolled too far. The same issue happens with similar steps in the following cases: - When using any option using the `addItem` action. - When undoing/redoing a step that was done in an element not in the viewport (the screen will scroll to it and we will have the issue). - When showing an invisible element (the screen will scroll to it if not in the viewport) - Adding a grid item with the "Add Elements" option. - Adding a new card in the "Floating Cards" snippet. The common point to all these cases is that they all scroll to the added or shown element with the `scrollIntoView` built-in function, which scrolls everything, including the viewport. It also doesn't take into account the header that changes during the scroll, often ending with the element hidden by the header. This commit fixes these issues by using the builder `scrollTo` util, which takes the header into account and only scrolls what needs to be. This function should always be preferred when scrolling in the builder. task-6314322 Forward-Port-Of: odoo/odoo#275686
e39bf6c6ab31e57d472a552cb9b902496e6323ae introduced a blacklist to email sending, to filter out "alias emails" (catchall...) & the root partner email (odoobot) from being sent certain emails, such as mailings. By default, odoobot email is odoobot@example.com. However, there are cases where users will have a legitimate partner that matches the odoobot email; an example of this is saas config, which automatically changes the odoobot email to the admin email set on database spin-up. This
Original PR description
e39bf6c6ab31e57d472a552cb9b902496e6323ae introduced a blacklist to email sending, to filter out "alias emails" (catchall...) & the root partner email (odoobot) from being sent certain emails, such as mailings. By default, odoobot email is odoobot@example.com. However, there are cases where users will have a legitimate partner that matches the odoobot email; an example of this is saas config, which automatically changes the odoobot email to the admin email set on database spin-up. This prevents the database admin from receiving their own mailings. To fix this, the root partner email is now only added to the blacklist if no active partner has the same email. Steps to reproduce: - Add a mailing contact with the same email as the root partner - Send a mailing to that mailing contact task-4893615 Forward-Port-Of: odoo/odoo#278122 Forward-Port-Of: odoo/odoo#264112
**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content bel
Original PR description
**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content below to be pushed down. **Fix:** Moved the banner inside the call window, but only when it is not compact (not in smaller chat window or mobile). Could fix with css but we probably don't want to show the banner in these cases anyway (as it would take too much space in the chat window, or not be relevant to mobile users). [1] https://github.com/odoo/odoo/commit/d45c92eb07cd16cc45b0e9c8bf9422fe974f0c62 opw-6250056 Forward-Port-Of: odoo/odoo#277982
When receiving a Peppol/UBL XML file containing an embedded PDF via an email alias, the PDF is not extracted and attached to the resulting vendor bill. Steps to reproduce: - Set up a BE Company - Configure an incoming mail server - Set up an email alias for the Vendor Bill journal - Receive a Peppol XML with embedded PDF via alias - Check the created Bill Issue: PDF has not been extracted from the xml This occurs because the received xml is set as main attachment for the record a
Original PR description
When receiving a Peppol/UBL XML file containing an embedded PDF via an email alias, the PDF is not extracted and attached to the resulting vendor bill. Steps to reproduce: - Set up a BE Company - Configure an incoming mail server - Set up an email alias for the Vendor Bill journal - Receive a Peppol XML with embedded PDF via alias - Check the created Bill Issue: PDF has not been extracted from the xml This occurs because the received xml is set as main attachment for the record and in this case we skip extraction opw-6075250 Forward-Port-Of: odoo/odoo#278428 Forward-Port-Of: odoo/odoo#262047
The mock server was computing the reaction sequence with `Math.min(reactionGroup.map(...))` instead of `Math.min(...reactionGroup.map(...))`. This returned `NaN`, making the sort order non-deterministic and causing the 'Reactions are ordered by id' test to be flaky. Fixes runbot error https://runbot.odoo.com/odoo/error/944188
Original PR description
The mock server was computing the reaction sequence with `Math.min(reactionGroup.map(...))` instead of `Math.min(...reactionGroup.map(...))`. This returned `NaN`, making the sort order non-deterministic and causing the 'Reactions are ordered by id' test to be flaky. Fixes runbot error https://runbot.odoo.com/odoo/error/944188
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Original PR description
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Miscellaneous changes
On a production-sized database the `hr.leave.attendance.report` SQL view took over three hours to run. This caused a significant load on the upgrade platform when processing databases that have a large number of `hr.employee` records. Specifically, when running `test_mock_crawl` and mocking the `Attendances > Reporting > Time Off Ledger` menu. PostgreSQL mis-estimated the row counts produced by the view: - The public-holiday check combined an `OR` with a function-wrapped `BETWEEN` (
Original PR description
On a production-sized database the `hr.leave.attendance.report` SQL view took over three hours to run. This caused a significant load on the upgrade platform when processing databases that have a…
On a production-sized database the `hr.leave.attendance.report` SQL view took over three hours to run. This caused a significant load on the upgrade platform when processing databases that have a large number of `hr.employee` records. Specifically, when running `test_mock_crawl` and mocking the `Attendances > Reporting > Time Off Ledger` menu. PostgreSQL mis-estimated the row counts produced by the view: - The public-holiday check combined an `OR` with a function-wrapped `BETWEEN` (`... AT TIME ZONE ... ::date`), which the planner cannot estimate; it predicted ~1 surviving row (actual: 29.4M) and chose nested loops that re-aggregated whole tables once per output row. - The attendance sub-query aggregated the entire `hr_attendance` table with no date bound, and was re-executed per output row. - The working schedule was resolved with a per-(employee, day) `LIMIT 1` lookup into `hr_version` (29.4M index probes). Rewrite the view as a set of CTEs: every heavy table is scanned once, joins use plain equality keys (hash-joinable), public holidays are pre-expanded so their exclusion stays an anti-join, the attendance aggregate is bounded to the report window, and hr_version is resolved by expanding each version over the days it covers. None of the CTEs are explicitly materialized: left to its own heuristic, PostgreSQL inlines a CTE referenced only once as a plain subquery and materializes the ones referenced more than once, which benchmarked faster than forcing materialization everywhere. This rewrites the body of the SQL view only: no schema change, no new field, no index, no migration. The report output is unchanged. Measured with EXPLAIN (ANALYZE, BUFFERS) on the same database: | metric | before | after | factor | |----------------|---------------|----------|--------| | execution time | 11 852 235 ms | 1 834 ms | ~6500x | | buffer hits | 115 311 556 | 71 890 | ~1600x | upg-4288902 Forward-Port-Of: odoo/odoo#266108
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the batching is done on the moves per product, meaning batches can be very small relative to the limit, and this causes unecessary queries compared to batching per all moves to process. **Solution:** Iterate through all moves rather than per product, and use/save the per product results direct
Original PR description
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the…
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the batching is done on the moves per product, meaning batches can be very small relative to the limit, and this causes unecessary queries compared to batching per all moves to process. **Solution:** Iterate through all moves rather than per product, and use/save the per product results directly in the relevant dicts. --- ### Batch and prefetch for initial product std_price **Problem:** When initializing products' standard price before replaying valuation, the first stock.move is read. This happens before any prefetching or batching occurs, so a query is made per move and contributes to performance issues. **Solution:** Batch and prefetch the products' first moves, then initialize the standard price. --- ### Use cached is_in and is_out values **Problem:** In `_get_valued_qty()`, `_is_in()` and `_is_out()` are called for each move, but these methods are already called for these moves and cached as `is_in` and `is_out`. **Solution:** Replace the method calls with the cached fields. If the move is not done, we fallback to the methods as the cached fields will be false for not done moves. --- **Perf Tables:** Record: product.template, each with AVCO automated valuation and a done in move Today: |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |1k |1.08s |264 |697ms |235 | |5k |2.74s |864 |2.23s |864 | |10k |4.83s |1375 |4.56s |1870 | At Date: |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |1k |3.10s |6109 |925ms |386 | |5k |14.68s |30299 |3.50s |1564 | |10k |26.98s |59173 |7.16s |3590 | opw-6134244 Forward-Port-Of: odoo/odoo#261624