Thursday, August 14, 2025
28 changes · saas-18.4
Enhancements to existing features
Draft invoices no longer show outstanding credit or debit messages when the related payment widget is already hidden. This keeps the invoice screen consistent and reduces confusion for users reviewing invoices that are not yet posted.
Original PR description
Before this commit: --- Draft invoices can be reconciled with payments via the Bank Reconciliation screen, but the Outstanding Payments widget is hidden to avoid confusion. However, outstanding credits/debits messages were still displayed on draft invoices, leading to inconsistency. In this commit: --- Updated the form to hide outstanding credits/debits messages when the invoice is in draft, making the behavior consistent. Before: --- <img width="1258" height="298" alt="image" src="https://github.com/user-attachments/assets/376b3799-e721-4bd6-bf9c-cb56ca02bb5f" /> After: --- <img width="1258" height="257" alt="image" src="https://github.com/user-attachments/assets/374e33d5-c406-44c1-9309-40c124b45451" /> task-4987833 Forward-Port-Of: odoo/odoo#221680
Employee profile images now keep the same size while creating and after saving an employee record. This avoids a visual jump between the placeholder avatar and the default saved image, making the HR form feel more polished and consistent.
Original PR description
Problem: the employee image avatar placeholder when creating a new employee is larger than the default image when saving the record. This commit adds a max width for the employee avatar image so that the default image is the same size as the placeholder before saving the record. task-4879346 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
The eInvoicing format dropdown now uses clearer, country-aware labels when configuring customer invoicing settings. This makes it easier for users to choose the right format without needing to understand technical names, reducing confusion across several localizations.
Original PR description
Renamed the selection labels for invoice_edi_format field to make them easier to understand based on the user's country context when choosing format inside customer's account tab. This improves the usability of the dropdown when selecting an eInvoicing format, especially for users in localizations where the technical name was unclear or confusing. 4889699 shzi Forward-Port-Of: odoo/odoo#220397
This update makes duplicating Italian electronic invoicing document types more user-friendly. Instead of immediately triggering an error because the copied record has the same code, the form view now helps users adjust the duplicate properly.
Original PR description
In https://github.com/odoo/odoo/commit/3e557745f16c33ab3c1b5984d6297913a8849024, we added a contraint to avoid same code. The "issue" with that is that the Duplicate option instantly raises the constraint. It's not really user-friendly. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222611 Forward-Port-Of: odoo/odoo#218933
This update adds standardized helper methods for finding employee contract versions and selecting the right contract for a date range. It helps HR-related features use contract data more consistently, reducing duplicate logic and the risk of inconsistent results.
Original PR description
Problem ---------- Normalize the way to retrieve contracts of employees Objective ---------- Create 2 helper functions : `_get_contract_versions` To retrieve for each employee, a list of versions recordset, one for each contract, ordered by date_version. Make the function flexible by adding date_range to filter the search. And additional domain option. `_get_contracts` It uses the previous function. To retrieve for each employee a single version recordset as contracts Add the option to retrive the first before date_start or latest version within the daterange task-4984245
Creating a payroll pay run is now quicker because users choose only the start date with a simple date picker instead of a date range popup. The end date is still calculated automatically and remains editable when manual adjustments are needed.
Original PR description
To ensure a smoother UX, the `daterange` widget has been replaced, as `date_end` is already calculated based on the selected `date_start`. Previous behavior: When creating a pay run and selecting `date_start`, a date range popup was displayed. This required two clicks, even though `date_end` was already auto-filled. New behavior: A simple date picker is used for `date_start`. The `date_end` remains editable so it can still be updated manually if needed. Task: 5005903
Network IoT devices will now have records even when another IoT Box has already detected them. This makes it easier to troubleshoot device ownership and understand which IoT Box is linked to each device.
Original PR description
We used not to create records for network IoT devices if they were already detected by another IoT Box on the database. This is making the debugging more complex, and doesn't make sense anymore as we show the IoT Box owning the device in many2x fields.
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
Code cleanup and technical improvements
The accounting tax calculation code was reorganized so the tax total rounding step is isolated in its own component. This makes it easier for localization or custom accounting modules to adjust rounding behavior without copying larger parts of the process, reducing maintenance effort and upgrade risk.
Original PR description
Move the code block responsible for rounding `total_per_tax` aggregates inside `_round_base_lines_tax_details` into a dedicated helper method `_round_total_per_tax`. This refactor allows custom modules to override only the rounding logic without reimplementing the entire `_round_base_lines_tax_details` method, improving maintainability. Related: https://github.com/OCA/l10n-japan/pull/70 @qrtl QT5088 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222951 Forward-Port-Of: odoo/odoo#222759
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