Daily updates from Odoo
Thursday, August 14, 2025
65 changes
20 changes
Resolved issues and error corrections
This fixes an error that occurred when users duplicated several Point of Sale configuration records at once. Businesses can now copy multiple POS setups from the list view without interruption, making setup and administration smoother.
Original PR description
### Steps to reproduce the issue: 1) In the Point of Sale app, when trying to duplicate more than two records from the list view, it gives a singleton error. The implementation was added to the master branch from commit [1]. [1]: https://github.com/odoo/odoo/pull/92664/files#diff-4c6e412c7d8f4df2a05831547e7df93d0b91f510d03b7b3ed0d689a18f5dae44R360-R361 opw-4969713 ### Description of the issue/feature this PR addresses: #### Issue Previously, when duplicating more than one pos.config record, it would give a singleton error. #### Solution Added a for loop to iterate over the config records individually. ### Current behavior before PR: https://github.com/user-attachments/assets/ba5a3969-7647-4943-a0b1-12b1961f26cd ### Desired behavior after PR is merged: https://github.com/user-attachments/assets/b952b711-7782-4e9d-b05a-e4019ab79d87 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220452
This update stabilizes an automated Point of Sale test that could occasionally select the wrong product variant during barcode searches. It helps ensure future changes are validated reliably without false test failures, supporting smoother releases.
Original PR description
This fixes a random runbot failure in the barcode search test involving product variants. The issue was caused by timing problems when selecting a second variant of a product with the same template…
This fixes a random runbot failure in the barcode
search test involving product variants.
The issue was caused by timing problems when selecting a second variant of a product with the same template name. Due to UI delays, the wrong variant could be selected.
The issue happened in this sequence:
- The test searched the first barcode (12341357), which correctly
displayed the product template "Product with Attributes" with the
variant (Value 1, 3, 5, 7) preselected.
- The product was added successfully.
- Then the second barcode (12342468) was searched. But before the UI
had time to update
and reflect the new variant (Value 2, 4, 6, 8), the test clicked
again on the same product template — which still had the *first*
variant preselected.
- As a result, the first variant was added twice, and the expected
second variant was missing.
To prevent this, a distinct product template ("Product without Attributes") was introduced between the two variant searches to give the UI enough time to refresh. The tour was also updated to properly wait for the correct product to appear and to avoid triggering the configurator on products without attributes.
runbot-230339
Forward-Port-Of: odoo/odoo#222713
Forward-Port-Of: odoo/odoo#222335Portal users can now open purchase orders that include products without images. The purchase order page skips missing product images instead of showing an error, improving reliability for customers and vendors using the portal.
Original PR description
In the purchase order portal template (`purchase.purchase_order_portal_content`), `image_data_uri(line.product_id.image_128)` was called without checking if the product had an image, leading to a rendering error when `image_128` is False. Steps to reproduce the bug: - create a product without an image - create a purchase order with that product - partner: portal user (e.g joel) - connect as portal user - go to the purchase order - the portal view will raise an error because it tries to render an image Solution: Added a conditional check to only render the `<img>` tag if the product image exists, preventing template evaluation errors. opw-5013230 Forward-Port-Of: odoo/odoo#222769
The HR time off test setup now archives existing leave types instead of deleting them. This prevents automated test failures when demo data includes related leave records, improving reliability of nightly builds without changing user-facing behavior.
Original PR description
### Root cause: - We were using .unlink() before, but it throws error if a hr.leave.type is linked with any hr.leave. ### Fix: - Instead of unlink we will archive the record task: 4925370 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217728
The recruitment module’s automated test data is now isolated from demo records by using the correct company context. This prevents unrelated demo applicants from affecting test results, improving reliability of quality checks without changing user-facing behavior.
Original PR description
Problem ---------- Runbot Error : With demo data, other applicants appear in the `_search_is_applicant_in_pool`. Test data should be separated. Objective ---------- Isolate test data by creating a company test. Solution ---------- Create/Set the good env company Add this to the search domain of applicant in the test. task-4970599
This update fixes a failing automated test in the Time Off area by ensuring date-based test logic runs with a fixed date. It helps prevent false failures caused by the current calendar date, improving confidence in release checks without changing user-facing behavior.
Original PR description
Given that accrual plans are related to dates, all the testcase logic has to be inside 'with freezetime' to avoid date related errors Runbot-error: https://runbot.odoo.com/odoo/runbot.build.error/230722 Forward-Port-Of: odoo/odoo#222854
This update prevents some Odoo web templates from failing when running on newer Python versions. It allows longer template expressions to be processed correctly, improving compatibility and avoiding unexpected page rendering errors.
Original PR description
Not entirely clear why it was apparently excluded, but apparently in 3.13 some qweb expressions require the use of `EXTENDED_ARG`. Specifically [1] makes the expression long enough that it needs at least one "long jump" which then requires an `EXTENDED_ARGUMENT`, here's the sizes for the expression in question in various Python versions: - 3.10: 102 bytes - 3.11: 188 bytes - 3.12: 214 bytes - 3.13: 272 bytes Thus it makes sense at at some point the earliest jumps in the expression (and `and`/`or` *are* jumps, since they're short-circuiting) would become "long". These increases in size can be due to a multitude of factors e.g. changes in inline cache details (3.11 and above), jumps becoming strictly typed and requiring `TO_BOOL` instructions (3.13), ... [1]: https://github.com/odoo/odoo/commit/cc68a012649f9eb331265deba3197abaf1700d97#diff-92dda03d204cc6ea8b7aacd0c07939843c83b1841f4a3049903844777d83c07bL154-R223 Forward-Port-Of: odoo/odoo#222939
This update adjusts an automated test used for public mail discussion channels so it checks the page in a more consistent way. It helps reduce false test failures during development and release validation, without changing the product experience for users.
Original PR description
This test suspiciously fails in various ways in all versions before the following PR: https://github.com/odoo/odoo/pull/214358 The race condition is not present starting from 18.4, just adapt to selector to be the same as previous versions for consistency, https://runbot.odoo.com/odoo/error/111051 https://runbot.odoo.com/odoo/error/223165 https://runbot.odoo.com/odoo/error/227755 https://runbot.odoo.com/odoo/error/227756 https://runbot.odoo.com/odoo/error/227757 https://runbot.odoo.com/odoo/error/227758 https://runbot.odoo.com/odoo/error/229657 https://runbot.odoo.com/odoo/error/229724 https://runbot.odoo.com/odoo/error/229745 https://runbot.odoo.com/odoo/error/229817 https://runbot.odoo.com/odoo/error/230901 Forward-Port-Of: odoo/odoo#222876 Forward-Port-Of: odoo/odoo#222825
This fix ensures simulated time changes used during testing are applied only to the selected database. It prevents unintended effects on related databases, improving reliability and reducing confusing test side effects.
Original PR description
Filtering the postgres database was not enough, the log_db was also affected. Since only the order was impacted, this was creating strange side effect in databases like the log-db where it was only modified when the function exists. Checking the -d is more reliable and safer to avoid any side effect when testing with faketime. Forward-Port-Of: odoo/odoo#222805
This update fixes an intermittent automated test failure in the bus notification system. It improves confidence in the test suite by ensuring the test waits for the notification listener to be ready before continuing, without changing customer-facing behavior.
Original PR description
This commit fixes the `test_postcommit` that fails in a non deterministic fashion. This test ensures bus notifications created in the post commit hook result in only one batch. To do so, the test listens on the connection with a selector. However, the main thread doesn't wait for the selector to be register before triggering the postcommit hook. This commit ensures the test waits for the selector to register the database connection before going further. runbot-77470 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#222810
This fix prevents an unnecessary payment provider card widget from appearing when a POS payment method is marked for online payments. It keeps the setup form clearer and avoids confusion for users configuring point-of-sale payment methods.
Original PR description
Before this commit, when the `is_online_payment` field was set to `True` the widget `pos_payment_provider_cards` was not properly hidden in the form view of the POS payment method. This commit ensures that the widget is correctly hidden when the field is set to `True` by resetting the `payment_method_type` to 'none'. Thanks to @elierwclik for the report and initial PR #222142 Forward-Port-Of: odoo/odoo#222356
Employees without a fixed working schedule can now have leave validated without causing an error. The system uses the employee resource timezone when no schedule timezone is available, helping managers process absences reliably.
Original PR description
Currently, if we try to validate a leave for a fully flexible employee (employee without a working schedule), we get a traceback when fetching the timezone from the working schedule. To rectify this issue, we default to the timezone of the resource. opw-4979974 Forward-Port-Of: odoo/odoo#222781 Forward-Port-Of: odoo/odoo#222634
The update adds pm.me addresses to the list of generic email providers. This helps Odoo better classify email domains, supporting more accurate handling of contact or lead information.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#219606 Forward-Port-Of: odoo/odoo#214036
This fixes unstable automated tests for the mail feature by ensuring checks wait for the background response to finish. It helps keep validation results reliable, especially when test servers are under heavy load, without changing user-facing behavior.
Original PR description
These tests were failing due to `expect.verifySteps()` being empty rather than the RPC response. The rpc response is asynchronous and awaiting the click doesn't necessarily mean the RPC had time to effectively happen, especially when runbot CPU load is high. Fixes runbot-error-160954 Forward-Port-Of: odoo/odoo#222839
This update fixes an unstable automated test in Web Studio that could fail unpredictably during validation. It improves confidence in release checks without changing user-facing behavior.
Original PR description
There was an undeterminism in a test relying on the event beforeunload beign defaultPrevented. For some reason it failed sometimes, probably because of an override somewhere. This commit fixes the problem by asserting other things in the test, arguably even more relevant than before. runbot-error-229754
A subscription upsell test was adjusted so it works reliably regardless of the year in which it is run. This helps keep automated checks stable and avoids false failures that could slow down releases.
Original PR description
Before this commit, when test_uninvoiced_upsell_close_log was launched in a year different than 2025, it would fail with the following error: ``` File…
Before this commit, when test_uninvoiced_upsell_close_log was launched in a year different than 2025, it would fail with the following error:
```
File "/data/build/enterprise/sale_subscription/tests/test_sale_subscription.py", line 2085, in test_uninvoiced_upsell_close_log
action = subscription.prepare_upsell_order()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1042, in prepare_upsell_order
action = self._prepare_renew_upsell_order('7_upsell', upsell_msg_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1012, in _prepare_renew_upsell_order
order = self._create_renew_upsell_order(subscription_state, message_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/test_sale_subscription/models/sale_order.py", line 228, in _create_renew_upsell_order
order = super()._create_renew_upsell_order(subscription_state, message_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 998, in _create_renew_upsell_order
values = self._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/project_sale_subscription/models/sale_order.py", line 40, in _prepare_upsell_renew_order_values
res = super()._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/partner_commission/models/sale_order.py", line 72, in _prepare_upsell_renew_order_values
values = super()._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1182, in _prepare_upsell_renew_order_values
raise UserError(_('You cannot create an upsell for this subscription because it :\n'
odoo.exceptions.UserError: You cannot create an upsell for this subscription because it :
- Has not started yet.
- Has no invoiced period in the future.
```
runbot-task-230716
Forward-Port-Of: odoo/enterprise#92307This fix prevents tiny rounding differences in Mexican POS eWallet payments from being treated as an amount still owed. Customers can proceed to payment normally when the order is effectively fully paid.
Original PR description
Before this commit, paying an order with eWallet could result in a small negative residual amount (due to tax calculation), instead of zero. This prevented users from proceeding to the payment screen. With this commit, the "lt" function is used to compare amounts while taking rounding precision into account, ensuring the residual is treated as zero when appropriate. opw-4867365 Forward-Port-Of: odoo/enterprise#91756 Forward-Port-Of: odoo/enterprise#88275
The default 13th month salary rate for Swiss payroll contracts was adjusted from 8.33% to 8.3333%. This improves payroll calculation precision and helps ensure Swiss employee compensation is computed more accurately.
Original PR description
-changed the default contractual thirteen month rate for Switzerland from 8.33 to 8.3333 Forward-Port-Of: odoo/enterprise#92129 Forward-Port-Of: odoo/enterprise#92095
This fix prevents users from selecting internal bank reconciliation widget models in places like Knowledge properties. It avoids errors caused by choosing models that are not stored in the database and cannot support normal search operations.
Original PR description
To reproduce this issue, just try to perform a name_search/search_count/etc.. on `BankRecWidget` for example: - Example of Steps in Knowledge: - Open knowledge - Create an article - Create another article in the first one (child) - Add a properties - Select `Bank reconciliation widget` in Model - Traceback `BankRecWidget` and `BankRecWidgetLine` use ```py _auto = False _table_query = "0” ``` to avoid being stored in db. This kind of model doesn't work with several methods of the model api, such as `search_count`, `name_search` etc... This commit will add a models blacklist via ir_model._is_valid_for_model_selector opw-4763713 Forward-Port-Of: odoo/enterprise#90060 Forward-Port-Of: odoo/enterprise#88352
The Cash Flow report now handles grouping by account codes consistently, preventing an error that could block report generation in certain configurations. This helps finance users reliably view cash flow details when custom account code fields are present.
Original PR description
The term used by GROUP BY should be the same term in the SELECT, avoiding the posible error like: ERROR: column "account_move_line__account_id.code_store" must appear in the GROUP BY clause or be used in an aggregate function That appears when a column named account_code is created for the model account_move_line. opw-4963180 Forward-Port-Of: odoo/enterprise#91915
18 changes
Resolved issues and error corrections
This fix makes automated checks for live chat session opening more reliable by skipping an unstable navigation step. It helps prevent false test failures while ensuring live chat sessions still open the correct conversation view.
Original PR description
The `test_session_history_open`, in later versions renamed `test_form_view_embed_thread`, ensures that clicking on a live chat session in the list view opens the thread, not the default form view. To do so, we first access the `/web` url, then open the command palette, and finally find the correct live chat view. However, such tests are known to be non-deterministic as the command palette is not always available at the start of the tour. Several live chat tours have been updated to directly access the view, providing the correct URL to `start_tour`: command palette part of the tour is meaningless. fixes runbot-161482 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 fixes an error that occurred when users duplicated several Point of Sale configurations from the list view at the same time. Businesses can now copy multiple POS setups without interruption, making store setup and administration smoother.
Original PR description
### Steps to reproduce the issue: 1) In the Point of Sale app, when trying to duplicate more than two records from the list view, it gives a singleton error. The implementation was added to the master branch from commit [1]. [1]: https://github.com/odoo/odoo/pull/92664/files#diff-4c6e412c7d8f4df2a05831547e7df93d0b91f510d03b7b3ed0d689a18f5dae44R360-R361 opw-4969713 ### Description of the issue/feature this PR addresses: #### Issue Previously, when duplicating more than one pos.config record, it would give a singleton error. #### Solution Added a for loop to iterate over the config records individually. ### Current behavior before PR: https://github.com/user-attachments/assets/ba5a3969-7647-4943-a0b1-12b1961f26cd ### Desired behavior after PR is merged: https://github.com/user-attachments/assets/b952b711-7782-4e9d-b05a-e4019ab79d87 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220452
This fixes unstable automated checks for website live chat ratings by waiting until the chat message is fully saved before verifying it. It helps prevent false test failures and supports more reliable delivery of live chat functionality.
Original PR description
The website live chat rating tours share common steps, among them, the `start` steps. Those steps check if the first message is not duplicated by: - Waiting for the `.o-mail-Thread` selector. -…
The website live chat rating tours share common steps, among them, the `start` steps. Those steps check if the first message is not duplicated by: - Waiting for the `.o-mail-Thread` selector. - Checking if there is only one message. - Adding a class to this message if that is the case. - Adding a step that looks for the added class. This approach is flawed because: - The thread will be persisted once the first message is sent. If the class is added to the transient message but the next assertion runs after persistence, the message with the class is no longer in the DOM. - The class can be overridden if the message re-renders before the next assertion. - There is no guarantee the message is in the DOM when executing `queryAll`. There is no reliable way to check the state before persistence because the thread may change between "trigger" and "run". This commit updates the assertions to ensure the message is sent correctly and no duplicates exist once the thread is fully persisted. fixes runbot-229822 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 fixes an intermittent automated test failure in Point of Sale where product variants could be selected too quickly before the screen refreshed. The change improves confidence in testing for barcode-based product selection without changing day-to-day user behavior.
Original PR description
This fixes a random runbot failure in the barcode search test involving product variants. The issue was caused by timing problems when selecting a second variant of a product with the same template…
This fixes a random runbot failure in the barcode
search test involving product variants.
The issue was caused by timing problems when selecting a second variant of a product with the same template name. Due to UI delays, the wrong variant could be selected.
The issue happened in this sequence:
- The test searched the first barcode (12341357), which correctly
displayed the product template "Product with Attributes" with the
variant (Value 1, 3, 5, 7) preselected.
- The product was added successfully.
- Then the second barcode (12342468) was searched. But before the UI
had time to update
and reflect the new variant (Value 2, 4, 6, 8), the test clicked
again on the same product template — which still had the *first*
variant preselected.
- As a result, the first variant was added twice, and the expected
second variant was missing.
To prevent this, a distinct product template ("Product without Attributes") was introduced between the two variant searches to give the UI enough time to refresh. The tour was also updated to properly wait for the correct product to appear and to avoid triggering the configurator on products without attributes.
runbot-230339
Forward-Port-Of: odoo/odoo#222631
Forward-Port-Of: odoo/odoo#222335This fixes a validation issue where certain legitimate nested view customizations were incorrectly shown as faulty in the interface. It helps prevent false error warnings for valid customizations, reducing confusion for administrators and developers working with Odoo views.
Original PR description
Have an arch that will move a subchild of a parent effectively replacing the parent ```xml <data> <xpath expr="/form/div/div" position="replace"> <xpath expr="/form/div/div/span" position="move" /> </xpath> </data> ``` Before this commit, the move xpath was marked as faulty in the IrUiView's form in the interface. After this commit, the xpath is not marked as invalid, because it is not. read `@def apply_inheritance_specs` to get a grasp on the supported semantics for xpaths arch. opw-4965869 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
Portal users can now open purchase orders even when an ordered product has no image. The purchase order page skips the missing image instead of showing an error, improving reliability for customers and suppliers using the portal.
Original PR description
In the purchase order portal template (`purchase.purchase_order_portal_content`), `image_data_uri(line.product_id.image_128)` was called without checking if the product had an image, leading to a rendering error when `image_128` is False. Steps to reproduce the bug: - create a product without an image - create a purchase order with that product - partner: portal user (e.g joel) - connect as portal user - go to the purchase order - the portal view will raise an error because it tries to render an image Solution: Added a conditional check to only render the `<img>` tag if the product image exists, preventing template evaluation errors. opw-5013230 Forward-Port-Of: odoo/odoo#222769
The website theme switch loader now shows progress correctly every time a user changes themes. This prevents confusion during repeated theme changes by ensuring the loading indicator restarts properly instead of appearing frozen.
Original PR description
__Current behavior before commit:__ When switching a theme, the website loader is displayed with a progress bar. When the operation is finished, the loader is hidden and the progress bar interval is cleared. However, the variable holding the interval ID is not being reset. If the user switch theme a second time, the `initProgressBar` method doesn't start a new interval because its initial guard finds the old interval ID and exit prematurely. This resulted in the progress bar appearing to be stuck. __Description of the fix:__ This commit fixes the issue by removing the initial guard of the `initProgressBar` method. __Steps to reproduce:__ 1. Open the Website builder 2. Click on the "Theme" tab 3. Click on "Switch Theme" 4. Choose a Theme 5. The loader is progressing 6. Do every steps again 7. The loader is stuck at the beginning Forward-Port-Of: odoo/odoo#218356
This fix allows Odoo's template engine to handle longer expressions correctly when running on newer Python versions. It prevents certain pages or reports from failing due to internal expression-size limits, improving reliability without changing user workflows.
Original PR description
Not entirely clear why it was apparently excluded, but apparently in 3.13 some qweb expressions require the use of `EXTENDED_ARG`. Specifically [1] makes the expression long enough that it needs at least one "long jump" which then requires an `EXTENDED_ARGUMENT`, here's the sizes for the expression in question in various Python versions: - 3.10: 102 bytes - 3.11: 188 bytes - 3.12: 214 bytes - 3.13: 272 bytes Thus it makes sense at at some point the earliest jumps in the expression (and `and`/`or` *are* jumps, since they're short-circuiting) would become "long". These increases in size can be due to a multitude of factors e.g. changes in inline cache details (3.11 and above), jumps becoming strictly typed and requiring `TO_BOOL` instructions (3.13), ... [1]: https://github.com/odoo/odoo/commit/cc68a012649f9eb331265deba3197abaf1700d97#diff-92dda03d204cc6ea8b7aacd0c07939843c83b1841f4a3049903844777d83c07bL154-R223 Forward-Port-Of: odoo/odoo#222939
The employee work address section now displays the state, city, and zip fields in a consistent horizontal alignment. This small layout fix makes the form easier to scan and helps users enter address details more clearly.
Original PR description
Task ID: 5002920 Description of the issue/feature this PR addresses: Align state, city, and zip fields horizontally on employee form Current behavior before PR: Not alignment in tab Employee > Work address as per fields state, city, and zip Desired behavior after PR is merged: Fields aligned
This fix updates the Time Off test setup so it archives existing leave types instead of deleting them when demo data is present. This prevents automated nightly builds from failing due to existing linked leave records, improving confidence in test results without changing user-facing behavior.
Original PR description
### Root cause: - We were using .unlink() before, but it throws error if a hr.leave.type is linked with any hr.leave. ### Fix: - Instead of unlink we will archive the record task: 4925370 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an automated test for employee time-off accruals by ensuring all date-sensitive checks run against a fixed date. It helps prevent false test failures caused by the current calendar date, improving release reliability without changing user-facing behavior.
Original PR description
Given that accrual plans are related to dates, all the testcase logic has to be inside 'with freezetime' to avoid date related errors Runbot-error: https://runbot.odoo.com/odoo/runbot.build.error/230722 Forward-Port-Of: odoo/odoo#222854
This fix ensures simulated time settings used in testing are applied only to the selected database. It prevents unintended effects on related databases, such as logging databases, making test behavior more reliable and safer.
Original PR description
Filtering the postgres database was not enough, the log_db was also affected. Since only the order was impacted, this was creating strange side effect in databases like the log-db where it was only modified when the function exists. Checking the -d is more reliable and safer to avoid any side effect when testing with faketime. Forward-Port-Of: odoo/odoo#222805
This change adjusts an automated test for public discussion channels so it no longer depends on a page reload that caused inconsistent failures. It helps keep quality checks stable without changing the experience for end users.
Original PR description
This test suspiciously fails in various ways in all versions before the following PR: https://github.com/odoo/odoo/pull/214358 This seems to indicate an issue with the page reload. Properly wait for the page to reload before proceeding with the next steps in the tour, hoping it will resolve all the related issues. https://runbot.odoo.com/odoo/error/111051 https://runbot.odoo.com/odoo/error/223165 https://runbot.odoo.com/odoo/error/227755 https://runbot.odoo.com/odoo/error/227756 https://runbot.odoo.com/odoo/error/227757 https://runbot.odoo.com/odoo/error/227758 https://runbot.odoo.com/odoo/error/229657 https://runbot.odoo.com/odoo/error/229724 https://runbot.odoo.com/odoo/error/229745 https://runbot.odoo.com/odoo/error/229817 https://runbot.odoo.com/odoo/error/230901 Forward-Port-Of: odoo/odoo#222876 Forward-Port-Of: odoo/odoo#222825
This fix makes an internal automated test for bus notifications run consistently by ensuring the test setup is ready before notifications are triggered. It helps reduce false test failures in the development pipeline without changing user-facing behavior.
Original PR description
This commit fixes the `test_postcommit` that fails in a non deterministic fashion. This test ensures bus notifications created in the post commit hook result in only one batch. To do so, the test listens on the connection with a selector. However, the main thread doesn't wait for the selector to be register before triggering the postcommit hook. This commit ensures the test waits for the selector to register the database connection before going further. runbot-77470 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#222810
Updates internal mail tests so they wait properly for background responses before checking results. This reduces false failures in automated checks, helping keep releases moving without affecting end users.
Original PR description
These tests were failing due to `expect.verifySteps()` being empty rather than the RPC response. The rpc response is asynchronous and awaiting the click doesn't necessarily mean the RPC had time to effectively happen, especially when runbot CPU load is high. Fixes runbot-error-160954 Forward-Port-Of: odoo/odoo#222839
French tax reports now compare totals using proper rounding instead of exact decimal matching. This prevents reports from incorrectly flagging matching amounts as different because of hidden decimal precision differences.
Original PR description
Currently, the code was checking for a strict equality between two sums. However, it may happen that there are many decimals that aren't displayed on the UI, hence the strict equality check fails. For instance `30201.63 != 30201.629999999997`. Instead, we now use the `float_compare` which takes care of rounding issues. opw-5000147 Forward-Port-Of: odoo/enterprise#92356
This fix updates an internal subscription test so it no longer depends on the calendar year in which it runs. It helps keep automated quality checks reliable across time, reducing false failures without changing customer-facing behavior.
Original PR description
Before this commit, when test_uninvoiced_upsell_close_log was launched in a year different than 2025, it would fail with the following error: ``` File…
Before this commit, when test_uninvoiced_upsell_close_log was launched in a year different than 2025, it would fail with the following error:
```
File "/data/build/enterprise/sale_subscription/tests/test_sale_subscription.py", line 2085, in test_uninvoiced_upsell_close_log
action = subscription.prepare_upsell_order()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1042, in prepare_upsell_order
action = self._prepare_renew_upsell_order('7_upsell', upsell_msg_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1012, in _prepare_renew_upsell_order
order = self._create_renew_upsell_order(subscription_state, message_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/test_sale_subscription/models/sale_order.py", line 228, in _create_renew_upsell_order
order = super()._create_renew_upsell_order(subscription_state, message_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 998, in _create_renew_upsell_order
values = self._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/project_sale_subscription/models/sale_order.py", line 40, in _prepare_upsell_renew_order_values
res = super()._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/partner_commission/models/sale_order.py", line 72, in _prepare_upsell_renew_order_values
values = super()._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1182, in _prepare_upsell_renew_order_values
raise UserError(_('You cannot create an upsell for this subscription because it :\n'
odoo.exceptions.UserError: You cannot create an upsell for this subscription because it :
- Has not started yet.
- Has no invoiced period in the future.
```
runbot-task-230716
Forward-Port-Of: odoo/enterprise#92307This fix prevents users from selecting bank reconciliation widget models in places where they cannot work correctly, such as model selectors in Knowledge properties. It avoids errors and tracebacks when those non-stored internal models are used by features that expect regular database-backed records.
Original PR description
To reproduce this issue, just try to perform a name_search/search_count/etc.. on `BankRecWidget` for example: - Example of Steps in Knowledge: - Open knowledge - Create an article - Create another article in the first one (child) - Add a properties - Select `Bank reconciliation widget` in Model - Traceback `BankRecWidget` and `BankRecWidgetLine` use ```py _auto = False _table_query = "0” ``` to avoid being stored in db. This kind of model doesn't work with several methods of the model api, such as `search_count`, `name_search` etc... This commit will add a models blacklist via ir_model._is_valid_for_model_selector opw-4763713 Forward-Port-Of: odoo/enterprise#90060 Forward-Port-Of: odoo/enterprise#88352
10 changes
Resolved issues and error corrections
Fixed an issue where opening My Requests in the Approvals app could fail when the same person appeared twice as an approver on one request. The system now safely uses one matching approver record, preventing the error and allowing users to view their approval requests normally.
Original PR description
#### Reproduce Approvals app -> My Approvals -> My Requests (Traceback Error) #### Issue The demo data contains a duplicate record for an approver (the user is set as default approver for the approval category and added again as record in xml data), so the request had 2 approvers with the same user. #### Fix Get the first record of filtered approvers for current user if there are many. task-4984137 Forward-Port-Of: odoo/enterprise#91806
A document sharing email template was corrected so it no longer references unavailable creator information. This prevents errors when document access records are created during upgrades, helping document sharing work reliably after migrations.
Original PR description
As `documents.access` records do not have `create_uid`, it isn't possible to reference it. This only comes up now as we've fixed the upgrade scripts to actually create this record (in odoo/upgrade#7959). Task-4480388 Forward-Port-Of: odoo/enterprise#92291
Portal templates in Field Service Sales were corrected after a recent subsection change caused display issues. This helps ensure customers and users see the intended layout without template errors.
Original PR description
\* industry_fsm_sale This commit fixes templates broken after the introduction of subsection in the section and note field ([1]). We wrote owl like "t-att-class" in python templates. task-5005432 [1]: https://github.com/odoo/enterprise/pull/91411
The default Swiss payroll rate for the contractual 13th month has been adjusted from 8.33% to 8.3333%. This improves payroll calculation precision for Swiss employees and helps avoid small rounding discrepancies.
Original PR description
-changed the default contractual thirteen month rate for Switzerland from 8.33 to 8.3333 Forward-Port-Of: odoo/enterprise#92231 Forward-Port-Of: odoo/enterprise#92095
This fix stops OCR processing from replacing an expense name that a user has already edited after upload. It helps ensure employee-entered expense descriptions are preserved and avoids confusion from unexpected name changes.
Original PR description
This commit https://github.com/odoo/odoo/commit/ca1f644a3c15f17482f56a2ece2a57f0f03098ff introduced the "untitled expense" title for expense when being uploaded. The user can then change manually the name. However, if the OCR is called after, it overrides the name previously set by the user. Therefore, if the name of an expense starts with "Untitled Expense", the OCR should not override the name. task-4653999
Fixes an issue where Mexican POS orders paid with eWallet could be stopped before the payment screen because a tiny tax rounding difference appeared as a negative remaining balance. The system now treats these near-zero amounts correctly, helping cashiers complete affected sales smoothly.
Original PR description
Before this commit, paying an order with eWallet could result in a small negative residual amount (due to tax calculation), instead of zero. This prevented users from proceeding to the payment screen. With this commit, the "lt" function is used to compare amounts while taking rounding precision into account, ensuring the residual is treated as zero when appropriate. opw-4867365 Forward-Port-Of: odoo/enterprise#91756 Forward-Port-Of: odoo/enterprise#88275
This fixes an internal subscription test that could fail when run outside the year 2025. It helps keep automated quality checks stable over time without changing customer-facing subscription behavior.
Original PR description
Before this commit, when test_uninvoiced_upsell_close_log was launched in a year different than 2025, it would fail with the following error: ``` File…
Before this commit, when test_uninvoiced_upsell_close_log was launched in a year different than 2025, it would fail with the following error:
```
File "/data/build/enterprise/sale_subscription/tests/test_sale_subscription.py", line 2085, in test_uninvoiced_upsell_close_log
action = subscription.prepare_upsell_order()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1042, in prepare_upsell_order
action = self._prepare_renew_upsell_order('7_upsell', upsell_msg_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1012, in _prepare_renew_upsell_order
order = self._create_renew_upsell_order(subscription_state, message_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/test_sale_subscription/models/sale_order.py", line 228, in _create_renew_upsell_order
order = super()._create_renew_upsell_order(subscription_state, message_body)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 998, in _create_renew_upsell_order
values = self._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/project_sale_subscription/models/sale_order.py", line 40, in _prepare_upsell_renew_order_values
res = super()._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/partner_commission/models/sale_order.py", line 72, in _prepare_upsell_renew_order_values
values = super()._prepare_upsell_renew_order_values(subscription_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/sale_subscription/models/sale_order.py", line 1182, in _prepare_upsell_renew_order_values
raise UserError(_('You cannot create an upsell for this subscription because it :\n'
odoo.exceptions.UserError: You cannot create an upsell for this subscription because it :
- Has not started yet.
- Has no invoiced period in the future.
```
runbot-task-230716
Forward-Port-Of: odoo/enterprise#92307This update corrects access permissions used by automated tests for Australian payroll accounting. It helps ensure payroll and accounting checks run reliably without failing because the test user lacks the right access groups.
Original PR description
[FIX] l10n_au_hr_payroll_account: missing groups The common test file is accessing models in account and hr modules but the user miss groups to have access to them. runbot-230912
Demo employee records in several country-specific payroll modules now use the correct payroll structure type. This helps demo environments show accurate payroll behavior and reduces confusion during evaluations, testing, or training.
Original PR description
Some employees on demo data don't have the correct structure type. This solves this issue. Task: 4890507 Forward-Port-Of: odoo/enterprise#88487
This update adjusts the appointment website test configuration so newly exposed snippet layouts are recognized correctly. It helps keep automated quality checks stable after a related website editor change, with no expected impact on daily users.
Original PR description
Starting from [1], the various dynamic snippet layouts are directly accessible from the snippet selection dialog instead of using the "Templates" option. The goal of this commit is to simply add the new snippets keys in the "sub-snippet templates" config to prevent the snippets drag and drop test from failing. [1]: https://github.com/odoo/odoo/commit/e3b062e5d3820ddfcee2eb669f21edc0c53c3330 runbot-230822 Community PR: https://github.com/odoo/odoo/pull/223010
17 changes
Resolved issues and error corrections
This fixes an automated live chat chatbot check that could fail because it moved on before changes were fully saved. The update waits for saving to finish, helping keep quality checks stable without changing customer-facing behavior.
Original PR description
This commit fixes the "change_chatbot_step_type" tour which fails because it doesn't wait for the form to be properly saved. This commit fixes the issue by waiting until the save button disappears. fixes runbot-229962 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 change removes an unnecessary warning caused by the use of an outdated internal method in inventory valuation logic. It helps keep system logs cleaner without changing day-to-day user workflows.
Original PR description
Before this commit a deprecated method is used and create a useless warning. 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 change updates HR tests so they run correctly in databases without demo data. It helps prevent false test failures and supports more reliable validation before releases.
Original PR description
Before this commit the test `test_webjson_employees` was failing in no demo builds as the json route only works in demo databases or when explicitly set. See https://github.com/odoo/odoo/pull/182196 This commit enables the system parameter, so that the test can be run as intended in no demo databases. Runbot Error: https://runbot.odoo.com/odoo/error/162907 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change adjusts an automated test for the HTML editor toolbar to reduce random failures. It helps keep development and release validation more stable without changing the product experience for users.
Original PR description
This is a deparate attempt to fix this test that keeps failing non-deterministically. Previous attempts were [1] and [2]. [1]: https://github.com/odoo/odoo/pull/222583 [2]: https://github.com/odoo/odoo/pull/222828
The accounting dashboard now excludes draft invoices from the checked items view, so users only see invoices that have been formally posted. This helps finance teams avoid confusing draft work with confirmed accounting records.
Original PR description
state = posted has been added in 18.0 but removed in https://github.com/odoo/odoo/commit/68fa35faa332615a2862935a82f778e38a2a3041#diff-6e3139ca3c848ecd9159cbee86a94aa51a3c7e0d2b62bbccfac1023c18a1edf5L586 initial opw-4349684
This fix allows Odoo's website and report templates to work correctly when running on newer Python versions that generate longer internal expressions. It prevents valid templates from failing due to a technical compatibility limit, helping maintain reliable system behavior during Python upgrades.
Original PR description
Not entirely clear why it was apparently excluded, but apparently in 3.13 some qweb expressions require the use of `EXTENDED_ARG`. Specifically [1] makes the expression long enough that it needs at least one "long jump" which then requires an `EXTENDED_ARGUMENT`, here's the sizes for the expression in question in various Python versions: - 3.10: 102 bytes - 3.11: 188 bytes - 3.12: 214 bytes - 3.13: 272 bytes Thus it makes sense at at some point the earliest jumps in the expression (and `and`/`or` *are* jumps, since they're short-circuiting) would become "long". These increases in size can be due to a multitude of factors e.g. changes in inline cache details (3.11 and above), jumps becoming strictly typed and requiring `TO_BOOL` instructions (3.13), ... [1]: https://github.com/odoo/odoo/commit/cc68a012649f9eb331265deba3197abaf1700d97#diff-92dda03d204cc6ea8b7aacd0c07939843c83b1841f4a3049903844777d83c07bL154-R223 Forward-Port-Of: odoo/odoo#222939
This fix ensures Italian EDI withholding tax descriptions are sent as plain text instead of including hidden formatting tags. It prevents incorrect text from appearing in generated XML documents and helps keep electronic tax reporting accurate.
Original PR description
The description field of the tax record was changed from char to html. This can break the dit functionality, as it now inserts the html tags into the description field. This PR aims to format the field as plaintext before rendering the XML to avoid such isses. opw-4985645
Portal users can now view purchase orders that include products without images. The page skips missing product images instead of failing, preventing an error that blocked access to the purchase order view.
Original PR description
In the purchase order portal template (`purchase.purchase_order_portal_content`), `image_data_uri(line.product_id.image_128)` was called without checking if the product had an image, leading to a rendering error when `image_128` is False. Steps to reproduce the bug: - create a product without an image - create a purchase order with that product - partner: portal user (e.g joel) - connect as portal user - go to the purchase order - the portal view will raise an error because it tries to render an image Solution: Added a conditional check to only render the `<img>` tag if the product image exists, preventing template evaluation errors. opw-5013230
This fix ensures a manufacturing test setup has the needed product variant permissions when demo data is not installed. It reduces the risk of false test failures and helps keep manufacturing-related updates reliable.
Original PR description
### Issue: The setUpClass of the `TestMultistepManufacturingWarehouse` test class fails without demo data since the `product_id` field is invisible in the bom view when the `product.group_product_variant` and is not automatic without demo data's: https://github.com/odoo/odoo/blob/7391082cfa42afdc62d17f1dac5cad97cf177e81/addons/product/data/product_demo.xml#L4-L7 https://github.com/odoo/odoo/blob/7391082cfa42afdc62d17f1dac5cad97cf177e81/addons/mrp/views/mrp_bom_views.xml#L63 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update makes an internal automated test for bus notifications more reliable by ensuring the test setup is fully ready before notifications are triggered. This helps prevent random test failures and supports smoother validation of future changes, with no expected impact on end users.
Original PR description
This commit fixes the `test_postcommit` that fails in a non deterministic fashion. This test ensures bus notifications created in the post commit hook result in only one batch. To do so, the test listens on the connection with a selector. However, the main thread doesn't wait for the selector to be register before triggering the postcommit hook. This commit ensures the test waits for the selector to register the database connection before going further. runbot-77470 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#222810
This fix ensures simulated time changes are only applied to the intended active database during testing. It prevents unrelated databases, such as logging databases, from being unintentionally affected and reduces the risk of confusing test side effects.
Original PR description
Filtering the postgres database was not enough, the log_db was also affected. Since only the order was impacted, this was creating strange side effect in databases like the log-db where it was only modified when the function exists. Checking the -d is more reliable and safer to avoid any side effect when testing with faketime. Forward-Port-Of: odoo/odoo#222805
Belgian and French reports now compare totals in a way that accounts for tiny rounding differences. This prevents reports from incorrectly flagging mismatches when the displayed amounts are effectively the same.
Original PR description
Currently, the code was checking for a strict equality between two sums. However, it may happen that there are many decimals that aren't displayed on the UI, hence the strict equality check fails. For instance `30201.63 != 30201.629999999997`. Instead, we now use the `float_compare` which takes care of rounding issues. opw-5000147
The Belgian payroll departure wizards now only show employees from the company the user is currently working in. This prevents confusion and accidental selection of employees from other companies in multi-company environments.
Original PR description
Added a domain to employees to limit the employee field in the departurre wizard to the logged in company **Steps to reproduce:** - Log into a Blgian Company - Access the Departure wizard through Payroll/Reporting or through the cog actions in an employee. **Issue:** Previously, when using the departure wizard, the employees shown were all the employees across different companies, when in reality it should be employees of the logged in company only **Fix:** Added employee domain so that it allows employees from the current logged in company only Task: 4965719 Forward-Port-Of: odoo/enterprise#90813
A payroll accounting test was missing a required dependency for Colorado tax calculations. Adding this dependency ensures the Colorado test case can run reliably and helps prevent false failures in payroll validation.
Original PR description
Issue: - Test case fails for the U.S. state of Colorado because the COINCOMETAX salary rule is defined in the l10n_us_hr_payroll_state_calculation module, but the test module test_l10n_us_hr_payroll_account does not depend on it. Fix: - Add a dependency on l10n_us_hr_payroll_state_calculation in the test_l10n_us_hr_payroll_account module. task-4949218
Upgrading the Colombian DIAN localization no longer removes the invoice and credit note email templates used for DIAN communications. This helps businesses keep their configured sending templates intact and avoids disruption after module updates.
Original PR description
**Steps to reproduce:** - Install l10n_co_dian => "Invoice (DIAN): Sending" and "Credit Note (DIAN): Sending" email templates are created - Upgrade l10n_co_dian **Issue:** "Invoice (DIAN): Sending" and "Credit Note (DIAN): Sending" are deleted. **Cause:** Email templates are reset during a module upgrade. These DIAN email templates are not defined in a XML, but created by a python function. This function is only called during installation. **Solution:** Set the "nopupdate" to True for these email templates to prevent them to be reset during the module upgrade. opw-4964347
Payslips now show the right weekly working hours when an employee uses a flexible-hours schedule. This prevents incorrect schedule information from appearing on payroll documents and improves clarity for employees and payroll teams.
Original PR description
> note: this PR should only be FW'd till `saas~18.4`, after that for `saas~18.5` (i.e., `master`), [this PR](https://github.com/odoo/enterprise/pull/85557) should be merged. ### Steps to reproduce: -…
> note: this PR should only be FW'd till `saas~18.4`, after that for `saas~18.5` (i.e., `master`), [this PR](https://github.com/odoo/enterprise/pull/85557) should be merged. ### Steps to reproduce: - Enable "Flexible Hours" in a working schedule. - Assign the schedule to an employee. - Generate a payslip for the employee. - Observe that the "Working Schedule" section always shows `hours_per_week` from the total hours calculated from the Work Schedule defined before turning on "Flexible Hours" ### Description: - the payslip incorrectly displayed the weekly working hours from the Work Schedule regardless of whether the employee's schedule used flexible hours. ### Cause: - the report template did not check for the `flexible_hours` flag and always rendered the value from `contract_id.hours_per_week`. ### Fix: - added a condition in the payslip template to check if `flexible_hours` is enabled. - if true, it displays `full_time_required_hours` from the working schedule instead of the contract's `hours_per_week`. task: 4719717
This fixes a conversion issue when portal users upload Excel files into shared document folders. Portal users are now kept at view-only access on converted spreadsheets, preventing errors and preserving the intended sharing restrictions.
Original PR description
Let's say a Document Folder is shared with a portal user with 'edit' access. The portal user shares a .xlsx file to the folder, and an internal user later try to convert the file to odoo spreadsheet. During the conversion, the portal user has 'edit' role on the folder, which is copied to the documents.access records of the converted sheet. Since Odoo prevents Spreadsheets from being shared in edit mode to portal users, _check_spreadsheet() raises a Validation Error. <img width="544" height="188" alt="image" src="https://github.com/user-attachments/assets/48426ff8-0cd9-4fb0-8e52-31099e586064" /> To resolve this issue, we force portal users to have `view` role on Spreadsheets during the XLSX to Spreadsheet conversion. opw-4753670