Daily updates from Odoo
Monday, July 14, 2025
28 changes · 18.0
Enhancements to existing features
This update lets Odoo automatically add the right labels to certain automated tests when they use website tours or database query checks. It helps the testing system run and report these tests more accurately, reducing missed labels and warning developers when special tests are not marked correctly.
Original PR description
This commit add the possibility to automatically add test-tag on a test method at runtime. A generic method `get_method_additional_tags` is added on `BaseCase` test class. That method can be overridden to return a list of test-tags that will be added on the test methods. With this mechanism, the `HttpCase` class override this method to add a `is_tour` test-tag when the `start_tour` method is used in the test method. Also, the `start_tour` method will now emit a warning when the method is called without being tagged `is_tour`. That way, all the tours can now be started with the `is_tour` test-tag. Forward-Port-Of: odoo/odoo#217102 Forward-Port-Of: odoo/odoo#212315
Resolved issues and error corrections
Portal users can now upload Excel, Word, and similar office documents without Odoo mistakenly treating them as ZIP files. This preserves the expected file names and formats in shared Documents workspaces, reducing confusion and failed document handling.
Original PR description
Issue: .xlsx files shared by portal users being converted into .zip files. https://drive.google.com/file/d/1MgHOrCW4QOVWmlYES-qWUQwEBH2M5gjk/view https://www.odoo.com/odoo/action-4043/4607156…
Issue: .xlsx files shared by portal users being converted into .zip files.
https://drive.google.com/file/d/1MgHOrCW4QOVWmlYES-qWUQwEBH2M5gjk/view
https://www.odoo.com/odoo/action-4043/4607156
https://www.odoo.com/odoo/my-support-tasks/4753670
How to reproduce:
1. Share a Documents workspace with a portal user.
2. Ensure the portal user has "edit" rights on the workspace. (so that he/she can share documents.)
3. Log in to the portal as the portal user.
4. Navigate to the shared workspace.
5. Upload an Excel (.xlsx) or Word (.docx) file.
6. Issue: The files are now .zip files.
Background:
In commit [9a1dec8](https://github.com/odoo/odoo/commit/9a1dec8eea5eae3a3e801dd2210fefa8a05ae485), the _from_request_file() method was introduced to guess a file's mimetype by analyzing only its first 1024 bytes.
https://github.com/odoo/odoo/blob/2d7bb960b00bfeae3e6ab8c0367237f3b08271cb/odoo/addons/base/models/ir_attachment.py#L769-L771
The guessing process ultimately calls zipfile.ZipFile(), which requires the entire file content to correctly parse OOXML formats.
https://github.com/odoo/odoo/blob/2d7bb960b00bfeae3e6ab8c0367237f3b08271cb/odoo/tools/mimetypes.py#L28-L42
Because we only provided the initial chunk, zipfile could not detect the file as `.zip` file, raising Error.
```
2025-06-10 14:49:54,049 61227 WARNING odoo_18_empty2 odoo.tools.mimetypes.guess_mimetype: Sub-checker '_check_open_container_format' of type 'application/zip' failed
Traceback (most recent call last):
File "/Users/sujuodoo/odoo18/odoo/odoo/tools/mimetypes.py", line 159, in _odoo_guess_mimetype
guess = discriminant(bin_data)
^^^^^^^^^^^^^^^^^^^^^^
File "/Users/sujuodoo/odoo18/odoo/odoo/tools/mimetypes.py", line 59, in _check_open_container_format
with io.BytesIO(data) as f, zipfile.ZipFile(f) as z:
^^^^^^^^^^^^^^^^^^
File "/Users/sujuodoo/.pyenv/versions/3.11.6/lib/python3.11/zipfile.py", line 1302, in __init__
self._RealGetContents()
File "/Users/sujuodoo/.pyenv/versions/3.11.6/lib/python3.11/zipfile.py", line 1369, in _RealGetContents
raise BadZipFile("File is not a zip file")
zipfile.BadZipFile: File is not a zip file
```
(Handled by Line 158 -167 below, where `discriminant()` = `_check_ooxml()`)
Consequently, it fell back to the generic application/zip mimetype. ( Line 168-170 below)
https://github.com/odoo/odoo/blob/2d7bb960b00bfeae3e6ab8c0367237f3b08271cb/odoo/tools/mimetypes.py#L154-L170
https://github.com/odoo/odoo/blob/2d7bb960b00bfeae3e6ab8c0367237f3b08271cb/odoo/tools/mimetypes.py#L122-L144
We already load the entire file in memory to `self.create()`, so I'm assuming it is fine to do so earlier in the code and pass it to the `guess_mimetype` -> `_odoo_guess_mimetype`, but at the same time I guess this might me a technical limitation.
https://github.com/odoo/odoo/blob/2d7bb960b00bfeae3e6ab8c0367237f3b08271cb/odoo/addons/base/models/ir_attachment.py#L778-L784
I'm curious how you guys think about this.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix ensures express checkout customer details are updated correctly when the website is used in languages where order references appear in a different position in generated partner names. It helps prevent checkout and delivery information from staying outdated for translated storefronts such as Spanish.
Original PR description
[FIX] website_sale: handle translated express checkout partners Versions -------- - 17.0+ Steps ----- 1. Change website language to Spanish 2. add a deliverable order to cart; 3. go via express checkout. Issue ----- The express checkout partner doesn't get updated as expected. Cause ----- Before this commit, it checks whether the express checkout partner's name ends with the order reference, as is the case in English. In Spanish however, the order reference gets used in the middle of the name. As a consequence, the `_create_or_edit_partner` method does not get called. Solution -------- Check whether the order reference is part of the partner name. opw-4894059 Forward-Port-Of: odoo/odoo#217528
This fixes an import error that could block Italian electronic invoices containing a zero-priced line with no discount or surcharge. Businesses can now process these invoices normally without a division-by-zero failure.
Original PR description
Error "division by zero" raised when importing a XML invoice with `price_unit == 0` and `ScontoMaggiorazione == 0` introduced by #206238
Factur-X electronic invoices now use deferred start and end dates when they are available, instead of defaulting to the invoice and due dates. This helps businesses send more accurate compliant invoice data for services delivered over a specific period.
Original PR description
### Issue: The FacturX XML has a field `BillingSpecifiedPeriod`, it should depend on `deferred_start/end_date` if they are there. Currently, it only outputs the invoice date as start date and the due…
### Issue: The FacturX XML has a field `BillingSpecifiedPeriod`, it should depend on `deferred_start/end_date` if they are there. Currently, it only outputs the invoice date as start date and the due date as end date. ### Steps to reproduce: - Install "l10n_de" and switch to a German company - Go to a contact, in the page Accounting > Electronic Invoicing change the format to "Factur-X (CII)" - Create an invoice for this contact - Add a start date and end date on the line of this invoice (`deferred_start/end_date`) - Confirm and send to Factur-X - In the generated XML the dates used are the invoice date and the due date ### Cause: As the `deferred_start/end_date` fields are defined in enterprise and the XML generation is in community, this [commit](https://github.com/odoo/odoo/commit/f0c5d5b46444a289bf55ad5846623d48ac3a3b71) set dates defined in community instead of the deferred ones. ### Solution: Mimicking [the way it's done for UBL20](https://github.com/odoo/odoo/blob/638268a81ed5a292a02d7fc353c4954159de54e1/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py#L846) we check if `deferred_start/end_date` are defined (i.e. account_accountant is installed). If it's the case, we use the min/max of the `deferred_start/end_date` as start/end date of the `BillingSpecifiedPeriod` in the XML. To include as much info as we can this commit also adds the `deferred_start_date` and `deferred_end_date` on lines. opw-4874370 Forward-Port-Of: odoo/odoo#215595
Fixes and usability improvements for Greece myDATA e-invoicing make invoice submission more reliable and reduce manual rework. The update corrects VAT formatting, error handling, PDF generation, invoice type defaults, settings placement, and default classification values to help users create and send compliant invoices more smoothly.
Original PR description
First major fixes and improvements for Greece EDI. task-4781479
This update adjusts translated messages so they no longer use a format that can break translation extraction on some Ubuntu build environments. It helps keep automated builds and deployments reliable without changing business workflows or user-facing features.
Original PR description
On Jammy, babel does *not* cope well with f-strings as values inside `_()` calls: it uses `eval` to try and figure them out, which attempts to execute the f-string, which fails because the evaluation context is empty. This is likely fixed from Babel 2.11 onwards (python-babel/babel#915) but Jammy uses babel 2.8[^1]. https://runbot.odoo.com/odoo/runbot.build.error/97849 [^1]: This doesn't seem to trigger on Noble even though it uses 2.10, but locally it does trigger on 2.10.3 (installed via pip), so ubuntu might have backported the fix or something.
This update prevents users from creating duplicate Italian electronic invoicing document type codes. It avoids invoice confirmation failures caused by duplicated document type records, making the invoicing process more reliable.
Original PR description
**Issue** : The computation of `l10n_it_document_type` fails when multiple `l10n_it.document.type` records share the same code. This can happen if a user duplicates an existing Document Type or…
**Issue** : The computation of `l10n_it_document_type` fails when multiple `l10n_it.document.type` records share the same code. This can happen if a user duplicates an existing Document Type or creates a new one with the same code, causing `get()` on the grouped recordset to return multiple results.
**Traceback :**
```python
File "/home/odoo/odoo/codebase/odoo/17.0/odoo/fields.py", line 3252, in convert_to_cache
raise ValueError("Wrong value for %s: %r" % (self, value))
ValueError: Wrong value for account.move.l10n_it_document_type: l10n_it.document.type(1, 23)
```
**Steps to Reproduce:**
1. Install the `l10n_it_edi_ndd` module.
2. Go to Customer Invoices and create a new invoice.
3. Set a Document Type, then confirm the invoice.
4. Open that Document Type and duplicate it.
5. Create another invoice without setting a Document Type, then confirm it.
observation: you will receive a traceback for wrong value error
**Solution :** This fix adds a check to ensure that the `code` field remains unique across all `l10n_it.document.type` records.
opw - 4902513
related upgrade pr : https://github.com/odoo/upgrade/pull/8032
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#217155Fixed a problem that could cause warnings when survey answer statistics were translated. This makes survey reporting more reliable for users working in different languages.
Original PR description
Issue: Prior to this commit, a translation issue occurred due to the use of a list comprehension. The _get_translation_source function attempts to scan the local variables, but in the context of a list comprehension, only variables defined within the comprehension are accessible. As a result, variables like uuid and cursor were not available to the _get_lang function, ultimately leading to an error. Fix: Replaced the list comprehension with a standard for loop to ensure proper access to local variables. runbot-135198
This update fixes editor issues that could create malformed lists when pasted content included list items without a surrounding list, and could prevent users from removing bold or italic formatting across multi-paragraph selections. This helps keep website and HTML editor content structured correctly and makes formatting controls behave reliably.
Original PR description
**Current behavior before PR:** **Issue 1:** - Paste a content with multiple `<li>` elements without `ol/ul` tag, each `<li>` having a paragraph element inside. - Try to create a list from these…
**Current behavior before PR:** **Issue 1:** - Paste a content with multiple `<li>` elements without `ol/ul` tag, each `<li>` having a paragraph element inside. - Try to create a list from these elements. - List is created with wrong element structure. The problem occurs because when pasting multiple `<li>` elements without an `<ol>/<ul>` tag, `sanitizeNode` replaces existing `<li>` elements with new `<p>` elements. Since each `<li>` already contains a `<p>`, this results in paragraphs being nested inside other paragraphs. As a result, creating the list from these paragraphs leads to an incorrect structure. **Issue 2:** If there are multiple paragraph selected along with newline character nodes `(\n)`, it is not possible to remove bold or italic format from selected content using toolbar. The issue happens because `isSelectionFormat` method fails to give correct value if traversed nodes contains one or more newline `(\n)` characters. **Desired behavior after PR is merged:** **Issue 1:** Now, if an `<li>` contains a `<p>`, the `<li>` is unwrapped instead of creating a new paragraph, resulting in a correct element structure when creating a list. **Issue 2:** Now, `\n` nodes are filtered from traversed nodes so that format can be removed from selected content. task-4752385 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#208127
Internal users without Accounting permissions can now add sub-contacts to contacts that use Spanish FACe Center roles without hitting an access error. This removes an unnecessary restriction so regular contact management works as expected while keeping the change limited to read access for role data.
Original PR description
**Steps to reproduce:** - Install l10n_es_edi_facturae - With an admin user, create a contact - From the contact, add a "FACe Center" sub-contact with a Role - Save the contact - With a user that doesn't have any Accounting rights, try to add a sub-contact to the previously created contact **Issue:** An access error is raised because some Accounting rights are needed to access "l10n_es_edi_facturae.ac_role_type" records. **Cause:** "l10n_es_edi_facturae.ac_role_type" is only readable for "account.group_account_invoice" group and "account.group_account_readonly" group. **Solution:** There's is no point to restrict the read access to an Accounting group. The model is made readable for all internal users. opw-4788636 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Receipts created with an invoice date now keep that intended date instead of being set to the current day. This helps ensure accounting records reflect the correct transaction timing and avoids date-related reporting errors.
Original PR description
* When invoice_date is set with create method for receipts, the date is not set correctly to invoice_date, but it's wrongly set to today. * Missing dependency 'move_type' to compute method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents users from changing another company's currency when that company already has journal items. It ensures existing accounting activity is detected correctly across companies, helping protect financial data consistency.
Original PR description
To_reproduce: ============== 1- switch company. 2- update any other company currency that has journal items. 3- company currency changed. Problem: ========= - When switching companies, users could update the other company's currency even when journal items existed for that company. Solution: Solution: ========= - Added .sudo() to the account.move.line search to bypass access rights and properly detect existing journal items in that company. opw-4920206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217988 Forward-Port-Of: odoo/odoo#217929
The shop page now avoids showing the same product category list twice when filters are opened on larger screens. This removes a confusing duplicate menu and makes the shopping experience cleaner for customers.
Original PR description
Steps to reproduce: 1. Go to the shop page. 2. Open the editor and configure Categories to display on the left, and Attributes at the top. 3. Save the changes and click the offcanvas toggle button next to the layout buttons. Issue: - The category list appears twice: once on the left side and again in the offcanvas dropdown. This is redundant and affects the user experience. Cause: - The category list in the offcanvas menu isn’t restricted to mobile view, so it also displays on larger screens where it’s already visible in the sidebar. Fix: - Add the 'd-lg-none' class to hide the category list in the offcanvas menu on large devices. opw-4830180 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#218330
A small typo was fixed in the portal sharing flow, with a minor code cleanup to make the logic clearer. This helps keep portal sharing messages or behavior polished without changing the overall user experience.
Original PR description
fix a small typo and and refactor for clarity opw-4938011 Forward-Port-Of: odoo/odoo#218570
This fixes planning calculations for flexible employees so their work intervals cover the intended flexible period instead of behaving like standard employee schedules. This helps ensure planning availability and related scheduling decisions reflect flexible work arrangements accurately.
Original PR description
Bug: - flexible employee work intervals are similar to work intervals for normal employees. Source: - condition to return an Interval covering all the period is _is_fully_flexible Fix: - condition changed to _is_flexible
Self-service and kiosk order numbers now include an S or K prefix, making it easier for staff and customers to identify where each order came from. The order number is shown consistently across tickets, receipts, preparation screens, and preparation receipts, with receipt header display limited to restaurant setups where it applies.
Original PR description
- Add a prefix `S` or `K` (respectively for Self and Kiosk orders) to the `tracking_number` for the Self/kiosk orders. - Display the `tracking_number` in the receipt header only if `pos_restaurant` is installed. - This prefix will be displayed on the ticket screen, on the receipt, on the preparation display and on the preparation receipt for coherence and to facilitate tracking of orders. task-id: 4922308 enterprise PR: https://github.com/odoo/enterprise/pull/90042 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures Nilvera documents use the Turkish UBL format instead of Peppol-specific handling. This matters because Nilvera is not a Peppol format and should not rely on Peppol fields, reducing the risk of incorrect electronic invoicing data.
Original PR description
It's not a format that is on peppol and does not use the fields from peppol. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#218220
This change reverts a recent analytic accounting update that caused errors when validating transactions using mandatory project analytics on expense accounts. It restores the previous behavior so affected accounting workflows can be completed reliably.
Original PR description
This reverts commit 8194c6e2bfedc9437964090b1a498c3e8cff225c. Steps to reproduce: - Modify analytic plan "project": default applicability: optional domain: miscellaneous financial account prefix: 6 applicability: mandatory - create a transaction - on the transaction > manual operation change account to expense put an analytic for "Projet" - validate opw-4936028 opw-4933629 opw-4935236 opw-4933456 opw-4933652 opw-4935789 opw-4938570 opw-4938388 opw-4935709 opw-4940233 opw-4938849
This fixes an error that could occur when changing reordering quantities for manufactured products during replenishment updates. Users can now adjust those rules without the process failing, improving reliability for inventory and manufacturing planning.
Original PR description
**Steps to reproduce:** - Install MRP module - Create a new product tracked by quantity and set its route to manufacture - Create a new BoM and set the Manuf. Lead Time to 2 days - Create a new…
**Steps to reproduce:**
- Install MRP module
- Create a new product tracked by quantity and set its route to manufacture
- Create a new BoM and set the Manuf. Lead Time to 2 days
- Create a new reordering rule, set the minimum quantity to 2 and click on order
- Navigate to the newly created manufacturing order and set the scheduled date to the next day
- Try increasing the minimum quantity on the reordering rule
- `KeyError` is triggered
**Issue:**
When computing `unwanted_replenish` field, the `_quantity_in_progress` function builds a dictionary (`res`) created using the IDs of current 'stock.warehouse.orderpoint' records as keys.
During `onchange()` process the keys can be set as temporary IDs (`NewID` class). But, when evaluating domains, `orderpoint.id` is returned as the real ID (`orderpoint._origin.id`), which make the index lookup fails when checking value of existing model:
```
self.id => NewId origin=6
res => {<NewId origin=6> : 0.0}
orderpoint.id => 6
res[orderpoint.id] => KeyError
```
This mismatch occurs due to the implicit conversion when using `NewId` inside domain filters with `.ids`. In which case they return the elements which matched the `_origin` id (for previous existing records). Domains will return the matching records with real IDs, but the dictionary still expects `NewId` as key.
**Fix:**
Ensure safe lookup by explicitly checking whether the dictionary has either the real ID or the `NewId` wrapper.
opw-4729116
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prWhen purchased goods fail a quality check and are moved to a failure location, Odoo now updates the linked stock flow so the related sales delivery can continue correctly. This prevents sales orders from staying stuck waiting for availability after a failed inspection.
Original PR description
Steps to reproduce the bug:
- Unarchive the MTO route
- Create a product P1:
- Type: Storable
- Route: MTO + Buy
- Supplier: Vendor A
- Create a quality point:
- Product: P1
- Control per: Quantity
- Failure location: WH/input/order Processing
- Create a sales order for 1 unit of P1
- Confirm the SO → A purchase order is created for Vendor A with 1 unit of P1
- Confirm the PO
- Go to the related PO picking
- Fail the quality check
Problem:
picking related to the SO remains in the "Waiting Availability" state and the stock move is not switched to the Make to stock procure method
opw-4874199
Forward-Port-Of: odoo/odoo#216337This fixes an issue where bank reconciliation could conflict with automatic analytic accounting updates. The change helps prevent processing loops and keeps journal entry analytics consistent during reconciliation.
Original PR description
Since a recent fix[^1], the analytic distribution on journal entries is updated with any update made on analytic items. In order to avoid loops and do things in the right order, a context key was added. However, the reconciliation widget was also manipulating analytic items, so it needed to use the context key as well. opw-4936028 opw-4933629 opw-4935236 opw-4933456 opw-4933652 opw-4935789 opw-4938570 opw-4938388 opw-4935709 opw-4940233 opw-4938849 [^1]: https://github.com/odoo/odoo/commit/8194c6e2bfedc9437964090b1a498c3e8cff225c
When a purchased item fails a quality check and is moved to a failure location, the related customer delivery no longer stays stuck waiting for the original item. The system now switches the affected stock move to use available stock, helping orders continue correctly after failed inspections.
Original PR description
Steps to reproduce the bug:
- Unarchive the MTO route
- Create a product P1:
- Type: Storable
- Route: MTO + Buy
- Supplier: Vendor A
- Create a quality point:
- Product: P1
- Control per: Quantity
- Failure location: WH/input/order Processing
- Create a sales order for 1 unit of P1
- Confirm the SO → A purchase order is created for Vendor A with 1 unit of P1
- Confirm the PO
- Go to the related PO picking
- Fail the quality check
Problem:
picking related to the SO remains in the "Waiting Availability" state and the stock move is not switched to the Make to stock procure method
opw-4874199
Forward-Port-Of: odoo/enterprise#88791Preparation displays now show an S or K prefix on order tracking numbers to distinguish Self and Kiosk orders. This makes it easier for staff to match the same order across the POS ticket screen, preparation receipt, and kitchen preparation display.
Original PR description
Add a prefix `S` or `K` (respectively for Self and Kiosk orders) to the `tracking_number` in the preparation display, so we can follow orders with the same `tracking_number` in the POS (ticket screen), on the preparation receipt and in the preparation display. task-id: 4922308 community PR : https://github.com/odoo/odoo/pull/218543
This fixes rare cases where Hong Kong payroll payment amounts shown on payslips did not match the HSBC Autopay file. The change helps ensure employees and payroll teams see consistent payment amounts across payroll records and bank payment files.
Original PR description
Explanation: In some rare cases, the autopay amount in payslip and the amount in hsbc autopay file doesn't match. This is due to hsbc autopay files are trimming all the decimal places, and the amount in payslip are rounded.
Odoo now includes depreciation amounts imported during a migration when showing cumulative depreciation and depreciation schedules. This prevents migrated assets from appearing under-depreciated and gives finance teams more accurate reports without creating duplicate journal entries.
Original PR description
Working:- - When migrating from any other accounting software to Odoo,in `Depreciated Amount(already_depreciated_amount_import)` field we put asset's depreciated amount till then(before migration).…
Working:- - When migrating from any other accounting software to Odoo,in `Depreciated Amount(already_depreciated_amount_import)` field we put asset's depreciated amount till then(before migration). This depreciation is recorded in each account when starting in Odoo(the original balances) and in Odoo creating Journal Entries are skipped for this imported depreciated amount. Example:- - Consider Asset with Original Value: \$10,000.00, Acquisition Date: 01/01/2020, Method: Straight Line, Duration: 10 Years, Computation: No Prorata. - Now according to our computation this asset will depreciate \$1000.00 for the years 2020 to 2029 each, and Journal Entries would be created on 31st December each year. - Now someone migrating from other software to Odoo in the year 2025 will put Depreciated Amount: \$5,000.00 . - Now Odoo will create Journal Entries for only years 2025 to 2029 and skip creating Journal Entries for the years 2020 to 2024 as these entries are created in previous accounting package and are recorded in original balances while migrating. Before this commit:- - In Depreciation Board, Cumulative Depreciation starts from \$1,000.00 for the year 2025 and goes till \$5,000.00 for the year 2029, ignoring imported depreciated amount. - Depreciation Schedule report displays constant \$5,000.00 as depreciated value for the years 2020 to 2024. After this commit:- - In Depreciation Board, imported depreciated amount is added in Cumulative Depreciation, so it starts from \$6,000.00 for the year 2025 and goes till \$10,000.00 for the year 2029. - In Depreciation Schedule Report, `_simulate_imported_depreciation` method will modify report values to simulated imported depreciation amount and skipped Journal Entries. task-4864528 Forward-Port-Of: odoo/enterprise#90012 Forward-Port-Of: odoo/enterprise#88127
Appointment bookings now reuse an existing contact when the same email address is used again, instead of creating a duplicate. This keeps customer records cleaner and reduces manual cleanup for teams managing appointments.
Original PR description
**Description** Booking an appointment on the website creates a new contact. If the same user books again, a duplicate contact is created instead of reusing the existing one. This is a regression from v17 where fallback logic prevented duplication. --- **Steps to Reproduce** 1. Book an appointment with a name, email, and phone. 2. Book a second appointment using the same data. 3. A new duplicate contact is created. --- **Before** * Existing contacts are not reused, causing duplicates. **After** * Existing contacts are reused if a matching email is found. --- This fix restores the fallback email search logic from v17 to avoid creating duplicates. **opw-4614897**
This update adds missing labels to Helpdesk automated tests so they are correctly recognized by the test system. It helps keep internal quality checks reliable and prevents test runs from being misclassified.
Original PR description
With the new test-tags features that allows to add additional test tags at runtime, the tests that starts a tour or that are using a query_count and that are not detected as such must be tagged respectively `is_tour` or `is_query_count`. Forward-Port-Of: odoo/enterprise#89934