Friday, June 20, 2025
22 changes · 18.0
Enhancements to existing features
This update improves Hoot, Odoo’s internal unit testing system, with clearer diagnostics, safer error handling, and more consistent test runner behavior. The changes help developers maintain and troubleshoot Odoo tests more reliably while keeping the impact limited to the testing ecosystem.
Original PR description
## Pull Request HOOT (PRHOOT) 33 This pull requests brings various improvements and fixes to Hoot and the Odoo unit test ecosystem. See the different commit messages for more details. Note: these changes are made in stable to avoid having to support multiple versions of the HOOT API. As such, these changes are intended to be strictly limited to unit tests as to not put the rest of the code base at risk. Enterprise: https://github.com/odoo/enterprise/pull/87476 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When users use the automatic fix to prepare a POS scale for certification, the system now also enables Units of Measure. This makes it easier for businesses to assign the right product units, such as kilograms, immediately after the setup is corrected.
Original PR description
This commit automatically enables the 'Units of Measure' setting when the user auto-fixes their settings to make their POS scale certified. While this is not a strict requirement, it helps the users to then quickly set the correct units for their products (e.g. kg) task-4885681
Resolved issues and error corrections
This fix prevents Discuss call tests from keeping old browser window data in memory after each test ends. It lowers test memory usage and helps keep automated testing more stable without changing end-user functionality.
Original PR description
Before this commit, discuss call HOOT tests retained the window object after test ended. Retained memory was about 2.5Mb-4Mb per test. An earlier PR [1] fixed a similar issue from a `const` object…
Before this commit, discuss call HOOT tests retained the window object after test ended. Retained memory was about 2.5Mb-4Mb per test. An earlier PR [1] fixed a similar issue from a `const` object being used in field default value. This was a problem because JS models internal code is keeping a reference to this object, and since HOOT suite test reuses the same window object, the window of each test were retained. The PR [1] fixed the issue by not setting object as default value of the field. Note that the default value and its presence in internal code of JS models happened for all tests that use `@mail` static files. That means this PR `[1]` fixed a retained memory for all `@mail` and related tests. While this fixed many tests, we still observed this retained memory on all discuss call tests. This happens because while the default value no longer uses this shared object, the computed value still does. Therefore call tests were sharing the const and thus retaining the window object. Note that the computed method is implicitly lazy, so this is only invoked in code that actually uses this `iceServers` field, hence why only discuss call tests were still affected by the issue. This commit fixes the issue by replacing the DEFAULT_ICE_SERVERS object by GET_DEFAULT_ICE_SERVERS function. This ensures each test use a different object, thus preventing retaining the window object after test has ended. [1]: https://github.com/odoo/odoo/pull/204521
Miscellaneous changes
task-id: 4746445 IAP PR: https://github.com/odoo/iap-apps/pull/1088 Forward-Port-Of: odoo/odoo#213819
Original PR description
task-id: 4746445 IAP PR: https://github.com/odoo/iap-apps/pull/1088 Forward-Port-Of: odoo/odoo#213819
Point of Sale receipts for GCC companies now show the cashier line only once instead of repeating “Served by.” This makes receipts cleaner and avoids confusing duplicate wording for customers.
Original PR description
Steps to reproduce: 1. Install l10n_gcc_pos. 2. Set the company’s country to a GCC country. 3. Print a POS receipt. Issue: - The receipt displays the phrase 'Served by' multiple times first two hardcoded and third one from prefix due to the cashier prop already including the prefix 'Served by '. - https://github.com/odoo/odoo/blob/f2dc7b5aaaf60d23e42e92f1ca0c6eed4ea13bf2/addons/l10n_gcc_pos/static/src/overrides/app/screens/receipt_screen/receipt/order_receipt.xml#L22 - Standard header data https://github.com/odoo/odoo/blob/0f8546528566acbcd2dd2fc1a99ae148ea2a7895/addons/point_of_sale/static/src/app/store/pos_store.js#L2099-L2105 Solution: - Replace cashier prop with gcc_cashier to return only the cashier’s name, without the 'Served by ' prefix. This avoids duplication and allows the template to handle translations consistently. opw-4724578
Fixes an error that occurred when users edited a scheduled email and added another attachment from the chatter. This makes scheduled email editing more reliable and prevents users from being interrupted by a traceback.
Original PR description
Steps to reproduce - open a record from Contacts app - from chatter, click `send mail` , open full mail composer - add a attachment - schedule a message, by clicking '▼' on send message - Again from…
Steps to reproduce - open a record from Contacts app - from chatter, click `send mail` , open full mail composer - add a attachment - schedule a message, by clicking '▼' on send message - Again from chatter, click on edit the same message - try to add another attachment Observation: A traceback is received Issue: Currently, `onFileUploaded` function attempts to get `res_ids` from `data`, https://github.com/odoo/odoo/blob/69828835c926485ec80ed92e14dd11fbc6c1caaa/addons/mail/static/src/core/web/mail_composer_attachment_selector.js#L25-L30 but in case message is scheduled, which is stored in `mail.scheduled.message` ,when editing it we do not have `res_ids` https://github.com/odoo/odoo/blob/69828835c926485ec80ed92e14dd11fbc6c1caaa/addons/mail/wizard/mail_compose_message.py#L120 instead we have `res_id` field, https://github.com/odoo/odoo/blob/69828835c926485ec80ed92e14dd11fbc6c1caaa/addons/mail/models/mail_scheduled_message.py#L46 hence a traceback is received when trying to json parse a `undefined` value. Fix: Adapt the `onFileUploaded` function to consider both, `res_ids` and `res_id` opw-4839926 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
A website testing tour was corrected so it more accurately detects when popup animations have finished and when scrolled elements are hidden. This helps keep automated website checks reliable and reduces false failures during quality assurance.
Original PR description
In this commit, we fix the tour snippet_popup_and_animations. For trigger: "...olumns .row > :last-child:not(:has(.o_animating))", :not(:has) is always true because no child has class o_animating. When the goal is check that the element has not a class, just use :not Also, when the scroll is well done, the element become invisible. So we need to add :hidden.
The Point of Sale product card now shows the last weighed value with adjusted text sizing. This makes the weighing information easier to read for cashiers when handling products sold by weight.
Original PR description
This small PR changes the text size displaying last weighed value for a product **Before:**  **Now:** 
The date range picker now lets users click an already selected start date to continue choosing an end date. This removes an unnecessary workaround and makes date range entry smoother and more intuitive.
Original PR description
This commit fixes an issue in the datetime_picker where clicking on an already selected start date would not initiate the selection of an end date. As a result, users were forced to select a different date first before being able to reselect the same start date. With this fix, clicking the start date again now correctly triggers the end date selection phase, improving the overall usability of the daterange picker. task-4845373
Pasting plain text into code blocks now keeps indentation using regular spaces instead of hidden non-breaking spaces. This makes copied code easier to edit, read, and reuse without unexpected invisible characters.
Original PR description
### Rationale for omitting `nbsp` in code blocks: - Code blocks, usually rendered within `<pre>` tags, inherently preserve whitespace & indentation through browser’s white-space: pre CSS behavior. Thus, inserting `nbsp` to maintain space visibility is redundant & may introduce hidden characters. ### Description of the issue/feature this PR addresses: - Indentation pasted as plain text inside code blocks was replaced by `nbsp`. ### Desired behavior after PR is merged: - Pasting plain text inside code blocks preserves indentation using normal spaces, avoiding insertion of `nbsp`. task-4815939 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
German POS receipts using Fiskaly now show official, readable names for TSS security information instead of internal technical field names. This makes receipts clearer for customers and staff and helps businesses present required certification details in a more understandable way.
Original PR description
Currently when using Fiskaly, the receipt gets printed with the technical names of the tss values. Steps to reproduce: ------------------- * Set up the db to use fiskaly * Open restaurant * Place and pay an order > Observation: On the receipt screen the name of the tss values are shown as: transaction_number, signature_algorithm, client_serial_number, .... Why the fix: ------------ Beore this commit https://github.com/odoo/enterprise/commit/d1a94147060083da54f9423f8c379676fbb7db66#diff-960ffa6839618d084dd5de6e29458ef68766a31250fc7d296512ec5358f04056 we were using a dictionnary `name, value` when using tss information, cf `_initTssInformation()` in `l10n_de_pos_cert/static/src/overrides/models/models.js`. We re-introduce this behavior and revert the following commit https://github.com/odoo-dev/enterprise/commit/9f75e3fe092bd838fffb11a35a8d854afff71869 to use the official names instead of the technical ones. opw-4822342
This update improves and fixes Odoo's internal unit test coverage for Hoot-based testing across several Enterprise apps. It helps keep future changes safer by making automated tests clearer and more reliable, with no intended impact on end users.
Original PR description
## Pull Request HOOT (PRHOOT) 33 This pull requests brings various improvements and fixes to Hoot and the Odoo unit test ecosystem. See the different commit messages for more details. Note: these changes are made in stable to avoid having to support multiple versions of the HOOT API. As such, these changes are intended to be strictly limited to unit tests as to not put the rest of the code base at risk. Community: https://github.com/odoo/odoo/pull/213223
### Steps to reproduce: - On a contact, add the "Factur-X" E-Invoicing method under the "Accounting" tab - Create an invoice with this contact as the customer - Send the invoice, download the PDF - Verify the PDF. For example with https://demo.verapdf.org/ - `The aforementioned EOL marker shall be immediately followed by a % (25h) character followed by at least four bytes, each of whose encoded byte values shall have a decimal value greater than 127` - `The MIME type of an embedded file, o
Original PR description
### Steps to reproduce: - On a contact, add the "Factur-X" E-Invoicing method under the "Accounting" tab - Create an invoice with this contact as the customer - Send the invoice, download the PDF -…
### Steps to reproduce: - On a contact, add the "Factur-X" E-Invoicing method under the "Accounting" tab - Create an invoice with this contact as the customer - Send the invoice, download the PDF - Verify the PDF. For example with https://demo.verapdf.org/ - `The aforementioned EOL marker shall be immediately followed by a % (25h) character followed by at least four bytes, each of whose encoded byte values shall have a decimal value greater than 127` - `The MIME type of an embedded file, or a subset of a file, shall be specified using the Subtype key of the file specification dictionary. If the MIME type is not known, the "application/octet-stream" shall be used` ### Cause: - 1 Pypdf 2.2 is [adding the necessary binary](https://github.com/py-pdf/pypdf/commit/036789a4664e3f572292bc7dceec10f08b7dbf62) like Odoo [does](https://github.com/odoo/odoo/blob/c1679123c9c6f7184293befb399de1e79a6205a9/odoo/tools/pdf/__init__.py#L471) for Pypdf2.1 because it is mandatory for PDF/A. The issue comes from two line break following each others: Pypdf2.2 adds one at the beginning of the [file](https://github.com/py-pdf/pypdf/blob/036789a4664e3f572292bc7dceec10f08b7dbf62/PyPDF2/pdf.py#L487): `\n % E2 E3 CF D3` Then Odoo [adds the header `%PDF-1.7\n` before](https://github.com/odoo/odoo/blob/c1679123c9c6f7184293befb399de1e79a6205a9/odoo/tools/pdf/__init__.py#L469) resulting in : `b"%PDF-1.7" \n \n % E2 E3 CF D3` PDF/A expects to have `% E2 E3 CF D3` on the second line right after the header but there is nothing on this line. - 2 The Subtype is badly formatted: from `text/xml` to `/text#232Fxml` instead of `/text#2Fxml` This occurs as Odoo [replace `/` by `#2F`](https://github.com/odoo/odoo/blob/2e43bee546d5c14729d654386209b539d8aa71d7/odoo/tools/pdf/__init__.py#L369-L377). But then when [adding the subtype](https://github.com/odoo/odoo/blob/2e43bee546d5c14729d654386209b539d8aa71d7/odoo/tools/pdf/__init__.py#L595C17-L595C74) to the attachment, we call `NameObject` from PyPdf. This object will [format](https://github.com/py-pdf/pypdf/blob/1c4173a12cd21b91dff6d6596ed0bbf1999f2d10/PyPDF2/generic/_base.py#L548) the text again replacing the `#` by `#23`. ### Solution: - Don't add a `\n` after `%PDF-1.7` when using `_pypdf2_2`. - As PyPdf2.2 is doing the formatting itself, we don't format on our side if `submod == ._pypdf2_2`. We still need to add the `/`. opw-4748600 Forward-Port-Of: odoo/odoo#211006
Backport of https://github.com/odoo/enterprise/pull/86477 which improves what was done in commits - https://github.com/odoo/odoo/commit/ebd6b5f374303dcdfcc69fa64522c1b83bd7fe58 - https://github.com/odoo/enterprise/commit/37cc5e067ff8d1e45edbd9a167a2d801c658739c since it avoids reloading the demo data twice by hooking on `_install_demo`. Instead, we just call our own function to create the demo data once in the accountant module. This commit therefore only reverts ebd6b5f374303dcd
Original PR description
Backport of https://github.com/odoo/enterprise/pull/86477 which improves what was done in commits - https://github.com/odoo/odoo/commit/ebd6b5f374303dcdfcc69fa64522c1b83bd7fe58 - https://github.com/odoo/enterprise/commit/37cc5e067ff8d1e45edbd9a167a2d801c658739c since it avoids reloading the demo data twice by hooking on `_install_demo`. Instead, we just call our own function to create the demo data once in the accountant module. This commit therefore only reverts ebd6b5f374303dcdfcc69fa64522c1b83bd7fe58 Enterprise PR: https://github.com/odoo/enterprise/pull/87204 Forward-Port-Of: odoo/odoo#213379
**PROBLEM** In the user menu, the text of dropdown item sometimes overlap with the checkbox next to it when it's too long. **STEP TO REPRODUCE** (happened with the italian localization of the onboarding module, but it's no longer the case because the text was shortened) 1. In `enterprise/web_enterprise/i18n/it.po`, for the msgid "Dark Mode" set the translation to something long. 2. click on the user menu and notice the text for the dark mode dropdown item is overlapping with the checkbox
Original PR description
**PROBLEM** In the user menu, the text of dropdown item sometimes overlap with the checkbox next to it when it's too long. **STEP TO REPRODUCE** (happened with the italian localization of the onboarding module, but it's no longer the case because the text was shortened) 1. In `enterprise/web_enterprise/i18n/it.po`, for the msgid "Dark Mode" set the translation to something long. 2. click on the user menu and notice the text for the dark mode dropdown item is overlapping with the checkbox next to it. **CAUSE** The checkbox in the user_menu.xml template use d-flex and flex-row-reverse, which doesn't work well with the class form-switch. form-switch add a negative left-margin of -2.5em to the <input> inside the checkbox template. **FIX** Put the description text before the checkbox in a flex div, and remove the flex-row-reverse on the checkbox. opw-4654405 Forward-Port-Of: odoo/odoo#214127
**Description** - Correction of the entry to calculate Time as per the set duration. **Steps to Reproduce** 1. go to Payroll app -> work entries -> work entries 2. Create new work entry. 3. set the end date at least 24 hours away from the start date. 4. notice that there is a 24 hours extra added/ per everyday you add. --- **Before** the calculation of the work entries duration was incorrect if it exceeds one day. --- **After** the work entry duration is calculated correc
Original PR description
**Description** - Correction of the entry to calculate Time as per the set duration. **Steps to Reproduce** 1. go to Payroll app -> work entries -> work entries 2. Create new work entry. 3. set the end date at least 24 hours away from the start date. 4. notice that there is a 24 hours extra added/ per everyday you add. --- **Before** the calculation of the work entries duration was incorrect if it exceeds one day. --- **After** the work entry duration is calculated correctly and still well rounded. --- **Why the fix** - When the following commit was merged, it introduced duration rounding , but rouding the entire timedelta converted to seconds instead of the number of seconds within a day, while still adding the total days - - commit : https://github.com/odoo/odoo/commit/80ae5f47650077b75dfbe4e813a122c81538cab3 --- opw-4827487 Forward-Port-Of: odoo/odoo#213211
Whenever there is a fault in the ZATCA onboarding steps (like missing Certificate Signing Request (CSR) information etc.), a traceback is returned to the user instead of a clear error message. This behavior was introduced by the following PR: https://github.com/odoo/odoo/pull/205671 which changed the return format of the `_l10n_sa_call_api` function in case of failures. Steps to reproduce: - Configure a Saudi Arabia company - Switch ZATCA environment to Simulation (or Production) - At
Original PR description
Whenever there is a fault in the ZATCA onboarding steps (like missing Certificate Signing Request (CSR) information etc.), a traceback is returned to the user instead of a clear error message. This…
Whenever there is a fault in the ZATCA onboarding steps (like missing
Certificate Signing Request (CSR) information etc.), a traceback is
returned to the user instead of a clear error message.
This behavior was introduced by the following PR: https://github.com/odoo/odoo/pull/205671
which changed the return format of the `_l10n_sa_call_api` function in
case of failures.
Steps to reproduce:
- Configure a Saudi Arabia company
- Switch ZATCA environment to Simulation (or Production)
- Attempt to onboard a journal using an incorrect OTP code
- A traceback is triggered instead of a clear user-facing error
Traceback example:
```
File "/home/odoo/src/odoo/17.0/addons/l10n_sa_edi/models/account_journal.py", line 200, in _l10n_sa_compute_production_csid_validity
journal.l10n_sa_production_csid_validity = self._l10n_sa_get_pcsid_validity(
File "/home/odoo/src/odoo/17.0/addons/l10n_sa_edi/models/account_journal.py", line 516, in _l10n_sa_get_pcsid_validity
b64_decoded_pcsid = b64decode(PCSID_data['binarySecurityToken'])
File "/usr/lib/python3.10/base64.py", line 80, in b64decode
s = _bytes_from_decode_data(s)
File "/usr/lib/python3.10/base64.py", line 45, in _bytes_from_decode_data
raise TypeError("argument should be a bytes-like object or ASCII "
TypeError: argument should be a bytes-like object or ASCII string, not 'NoneType'
```
This is due to the check in `_l10n_sa_get_compliance_CSID` for an 'error'
key, not present in the response when an OTP is invalid because in these
case, the `_l10n_sa_call_api` return the response_data directly.
This fix improves the behavior by displaying a user-friendly alert
message with the error returned by ZATCA, instead of a traceback.
This ensures a better experience and compliance with CCSID onboarding flows.
opw-4838542
Forward-Port-Of: odoo/odoo#215067
Forward-Port-Of: odoo/odoo#214391- Adding new taxes required by DIOT - Adding relevant tags and accounts Enterprise PR: https://github.com/odoo/enterprise/pull/82864 task-4568859 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#213194 Forward-Port-Of: odoo/odoo#204742
Original PR description
- Adding new taxes required by DIOT - Adding relevant tags and accounts Enterprise PR: https://github.com/odoo/enterprise/pull/82864 task-4568859 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#213194 Forward-Port-Of: odoo/odoo#204742
With a Spanish company and `l10n_es_edi_facturae`: - Create an invoice with a Spanish contact and confirm it. - Create a credit note for this invoice. Send and print it. In the Facturae XML, the `InvoiceClass` uses `OO` instead of `OR` (as specified on page 24 of [the specifications](https://www.facturae.gob.es/formato/Versiones/Esquema_castellano_v3_2_x_06_06_2017_unificado.pdf)). This commit also removes the hard-coded `'FC'` for `InvoiceDocumentType`, writing `'FA'` instead in the c
Original PR description
With a Spanish company and `l10n_es_edi_facturae`: - Create an invoice with a Spanish contact and confirm it. - Create a credit note for this invoice. Send and print it. In the Facturae XML, the `InvoiceClass` uses `OO` instead of `OR` (as specified on page 24 of [the specifications](https://www.facturae.gob.es/formato/Versiones/Esquema_castellano_v3_2_x_06_06_2017_unificado.pdf)). This commit also removes the hard-coded `'FC'` for `InvoiceDocumentType`, writing `'FA'` instead in the case of a simplified invoice. opw-4806099 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#211649
Previously, when multiple form snippets were added to the same page, corresponding fields (e.g., the "Name" field) in each form were assigned the same ID. This happened because we retrieved the form fields from the `FormEditorRegistry`. For the first form snippet, field IDs are generated and assigned correctly. However, assigning IDs to the fields also updated the fields stored in the `FormEditorRegistry`. So when a second form snippet is added, the fields it receives from the registr
Original PR description
Previously, when multiple form snippets were added to the same page, corresponding fields (e.g., the "Name" field) in each form were assigned the same ID. This happened because we retrieved the form…
Previously, when multiple form snippets were added to the same page, corresponding fields (e.g., the "Name" field) in each form were assigned the same ID. This happened because we retrieved the form fields from the `FormEditorRegistry`. For the first form snippet, field IDs are generated and assigned correctly. However, assigning IDs to the fields also updated the fields stored in the `FormEditorRegistry`. So when a second form snippet is added, the fields it receives from the registry already have an ID. The ID generation logic skips fields that already have an ID, so the fields in subsequent forms never got new IDs. With this fix, we now create a shallow copy of each field before using it. This prevents the original field definitions in the `FormEditorRegistry` from being modified. As a result, fields in different forms now receive unique IDs without needing to explicitly delete the field ID to force a new one to be generated. [task-4251881](https://www.odoo.com/web#id=4251881&cids=1&menu_id=4720&action=333&active_id=1695&model=project.task&view_type=form) Forward-Port-Of: odoo/odoo#210537 Forward-Port-Of: odoo/odoo#183883
Backport of https://github.com/odoo/enterprise/pull/86477 which improves what was done in commits - https://github.com/odoo/odoo/commit/ebd6b5f374303dcdfcc69fa64522c1b83bd7fe58 - https://github.com/odoo/enterprise/commit/37cc5e067ff8d1e45edbd9a167a2d801c658739c since it avoids reloading the demo data twice by hooking on `_install_demo`. Instead, we just call our own function to create the demo data once in the accountant module Community PR: https://github.com/odoo/odoo/pull/2133
Original PR description
Backport of https://github.com/odoo/enterprise/pull/86477 which improves what was done in commits - https://github.com/odoo/odoo/commit/ebd6b5f374303dcdfcc69fa64522c1b83bd7fe58 - https://github.com/odoo/enterprise/commit/37cc5e067ff8d1e45edbd9a167a2d801c658739c since it avoids reloading the demo data twice by hooking on `_install_demo`. Instead, we just call our own function to create the demo data once in the accountant module Community PR: https://github.com/odoo/odoo/pull/213379 Forward-Port-Of: odoo/enterprise#87204
- Reworking the DIOT report to comply with 2025 standard - Adjusting operation_type values on res.partner to match - Adjusting DIOT tests and other tests affected by the rework Community PR: https://github.com/odoo/odoo/pull/204742 task-4568859 Forward-Port-Of: odoo/enterprise#87102 Forward-Port-Of: odoo/enterprise#82864
Original PR description
- Reworking the DIOT report to comply with 2025 standard - Adjusting operation_type values on res.partner to match - Adjusting DIOT tests and other tests affected by the rework Community PR: https://github.com/odoo/odoo/pull/204742 task-4568859 Forward-Port-Of: odoo/enterprise#87102 Forward-Port-Of: odoo/enterprise#82864