Monday, September 14, 2026
24 changes · master
Resolved issues and error corrections
Website builder content inserted through editing options now uses the website's language instead of the editor user's language. This improves consistency for multilingual sites and also fixes a form editor issue where descriptions for Cc and recipient email fields could not be removed.
Original PR description
This PR moves to `*.edit.xml` the templates that are rendered by options and whose content is inserted in the page. And uses `websiteBridge` to render those. With this, the text content of those templates is in the language of the website instead of the language of the user (to be consistent, this is also done for templates that have no text to translate) A few of those templates where files in `website/static/src/xml`. Other files in that directory are templates for interactions, to be consistent with other interactions, those are moved to the directory of the interactions. The template `website.prompt` was not use at all so it is removed. To avoid issues caused by `markup` from the iframe that is different from the `markup` out of the iframe (thus consider each other as text to escape), the options of forms are refactored to avoid using them (and a bug was found and fixed in there)
Product listings now show the correct variant image instead of the generic product template image in product snippets and wishlists. This helps shoppers see the exact product variant they are considering, reducing confusion and improving the browsing experience.
Original PR description
We wrongly displayed template images instead of variant images in product snippets (with "split variant" toggled on) and on the wishlist page.
Belgian customers who changed their Peppol registration identifier can now be re-checked automatically when invoices are sent. This helps prevent valid partners from being marked unreachable and reduces failed electronic invoice delivery.
Original PR description
Some partners were registered on Peppol with EAS 9925 (Belgian VAT) but have since moved to 0208. They became unreachable via Peppol because we never check if they exist on the network with EAS 0208, which makes their status `not_valid`. This fix forces the re-checking of the status with EAS 0208 for partners having EAS 9925 and a `not_valid` status. task-6296017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287297 Forward-Port-Of: odoo/odoo#270742
Starting the first work order on a planned manufacturing order no longer removes its planned status. This prevents confusion for production teams and keeps the planning action from reappearing unnecessarily after work has already started.
Original PR description
This commit fixes the issue of unplanning a planned MO when a workorder is started (among other workorders as one workorer doesn't reproduce the bug). To reproduce the bug: 1- Confirm an MO with multiple workorders. 2- Plan it 3- Start the first workorder = The MO becomes unplaned and the button `Plan` reappear. The bug was happening becasue the write method of the mrp_production was unplanning the MO when the `date_start` changes unless the state is in progress by this commit: https://github.com/odoo-dev/odoo/blob/39db3c9c19ccd5c9c20e2ec61e921d3c3acdfbea/addons/mrp/models/mrp_production.py#L1117. However, in our case the state is not yet written, so we used the context guard in this case. Task-6566626
This change corrects how Belgian payroll data is initialized for DMFA reporting when time credit proration is involved. It helps ensure payroll declarations use the right calculation logic and reduces the risk of reporting errors.
Original PR description
. Fix _l10n_be_get_time_credit_proration() call parameters on DMFA Occuptaion init . Update l10n_be_get_time_credit_proration() name to _l10n_be_get_time_credit_proration() task-6565810
This fixes the employee deactivation flow so that cancelling or closing the departure dialog no longer archives the linked user by mistake. HR users now get clearer choices to deactivate only, deactivate and end collaboration, or discard the action, reducing accidental employee access changes.
Original PR description
Bug reproduction: 1 - Install hr module 2 - Create some user in the settings, create an employee for it. 3 - Give contract to the employee make it 1 January 2020. 4 - Press to invited button in the…
Bug reproduction:
1 - Install hr module
2 - Create some user in the settings, create an employee for it.
3 - Give contract to the employee make it 1 January 2020.
4 - Press to invited button in the top -> Deactivate
5 - Press to discard or X button in the opened pop-up.
6 - The button in the top converts to archived and user is archived.
Bug cause:
1 - In function: action_toggle_user_active, the active field of the user is toggled first
2 - If employee has a contract, we open the departure pop-up.
- 2.1 - But in pop-up, we can select discard or press to X to cancel it.
Bug solution:
1 - If the user is active and employee has a contract, I open the pop-up.
2 - Otherwise, I'm toggling the active field of the user. By that way, if discard or X is pressed, the active does not toggled.
task-6535464
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-prIndonesian payroll now calculates Employer Cost from the Gross Total instead of Net Salary. This gives companies a more accurate view of their full payroll expense, including allowances, benefits, taxes, and company contributions.
Original PR description
The Employer Cost of a payslip sums the rules flagged as contributing to it, and only the Net Salary rule was flagged. The amount therefore showed the employee's take-home pay instead of what the company actually spends. Flag the Gross Total rule instead, which sums every employer-paid component: basic salary and fixed allowance, allowances, benefits in kind, tax allowance and company contributions. task-6371974
Belgian payroll now calculates the structural deduction using the actual payroll amounts being computed, rather than the employee's standard contract wage. This helps avoid incorrect deductions when pay differs due to part-time work, variable pay, or other payroll adjustments.
Original PR description
The structural deduction 3000 (`_get_l10n_be_structural_deduction_3000`) needs the total remunerated wage (ww) for the quarter, built from the sum of payslip lines tagged with remuneration codes 1, 2, 4, 5 and 12. For the payslip currently being processed (state == draft), those lines don't exist yet, so the previous implementation approximated ww by simply adding the contract's wage. This is inaccurate whenever the actual computed amount differs from the wage, e.g. partial occupations, variable pay elements, or any other rule that lowers/raises the base pay for the period. Instead of falling back to the contract wage, look up the rules on the payslip's structure that map to the missing remuneration codes and read their real computed amounts directly from the rule engine's in-progress results (result_rules) for the current computation pass, since `line_ids` is not yet populated on the slip being computed. Task: 6516341
Mexican electronic payment complements now report tax amounts using the decimal precision required for the payment currency. This prevents valid payments from being rejected by PAC providers such as Quadrum and improves compliance with SAT validation rules.
Original PR description
The 'ImpuestosP' node of the payment complement (Pagos 2.0) is reported with 6 decimals while the SAT expects the amounts to be expressed with the number of decimals supported by the currency of the…
The 'ImpuestosP' node of the payment complement (Pagos 2.0) is reported with 6 decimals while the SAT expects the amounts to be expressed with the number of decimals supported by the currency of the payment ('MonedaP'), as published in the 'c_Moneda' catalog, for example 2 decimals for MXN.
Steps to reproduce:
- Have an MX Company setup with Quadrum as PAC.
- Create and sign a customer invoice in MXN with a 16% IVA tax.
- Register a full payment and send the payment complement to the PAC.
Issue:
Payment will be rejected
```
Code : CRPER654
Message : El importe del campo BaseP que corresponde a Traslado, no tiene la cantidad de decimales que soporta la moneda (MonedaP)
```
Analysis:
Quadrum recently aligned its validation on that rule and now rejects the document having fields with too much decimals and, currently, fields like BaseP, ImporteP are pinned to 6 decimals in the template.
Reporting them with the decimals of the payment currency is not enough when the payment settles a document expressed in another currency: those amounts are also compared with the ones of the related documents converted with 'EquivalenciaDR', and the PAC expects the values truncated or rounded
```
Code : CRP20274
Extra Info : Traslados: La sumatoria de ImporteDR es mayor al ImporteP 1.30.
Valores minimos permitidos: Truncado: 1.29 o redondeado: 1.3
```
opw-6561617
Forward-Port-Of: odoo/enterprise#131343
Forward-Port-Of: odoo/enterprise#131267This fixes an issue where some monetary totals appeared blank in pivot reports, such as the Invoices Analysis report. Users can now see key financial amounts consistently in pivot views, matching what already appeared in graph views.
Original PR description
Steps to reproduce: - Install Accounting - Go to the "Invoices Analysis" report -> The default "Untaxed Amount" doesn't display any value. Same for fields like "Total," for example. However, currency fields don't have the issue. Any Monetary measure whose own aggregator is `sum_currency` (e.g., price_total in the account.invoice.report model) renders completely empty in the pivot view, while the graph view for the same model/measure displays correctly. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an error that could stop the marketing automation screen from loading when adding a record to a campaign. Users should now be able to open that campaign action without encountering a crash caused by incorrect component setup.
Original PR description
A props validation error happens when the component is rendered due to the wrong props definition. ``` > UncaughtPromiseError > TypeError > > Uncaught Promise > type is not a function > > Occurred on…
A props validation error happens when the component is rendered due to the wrong props definition. ``` > UncaughtPromiseError > TypeError > > Uncaught Promise > type is not a function > > Occurred on 125085990-master-all.runbot132.odoo.com on 14/Sep/2026 05:43:28 > > TypeError: type is not a function > validate@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:647:291 > validateObject@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:691:34 > validateLooseObject@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:695:108 > validateType@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:648:67 > assertType@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:645:109 > makeProps@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:1192:48 > __exports.AddRecordToCampaign<@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:39471:954 > AddRecordToCampaign@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:39471:812 > ComponentNode@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:1035:999 > createComponent/owl@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:1123:6 > slot1@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js line 1511 > Function:13:12 > callSlot@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:1089:25 > __template__14@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js line 1511 > Function:30:10 > render@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:1026:199 > initiateRender@https://125085990-master-all.runbot132.odoo.com/web/assets/31cc50d/web.assets_web.min.js:1041:56 ```
This update fixes subscription dashboard information so non-admin users see the correct subscription status. It also hides sensitive database management options from non-admin users and adds a clearer Odoo Account section for safer, easier account navigation.
Original PR description
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
Validated future leave requests are now counted against an employee's available leave balance when the days are granted upfront. This prevents employees and HR teams from seeing an overstated remaining balance after future time off has already been approved.
Original PR description
**Steps to reproduce:** - Create and validate an allocation of 10 days. - Take and validate a leave of 5 days in the future. - Issue: the allocation's `virtual_remaining_leaves` still shows 10 instead of 5. **Issue:** `hr.leave.allocation._compute_leaves()` calls `_get_consumed_leaves()` with `ignore_future=True`, which filters the leaves domain to `date_from <= today`. A validated future leave is excluded from the query before it can be deducted, even though the allocation grants its days upfront and isn't gated by any accrual plan. This flag was intentionally dropped from this call by (https://github.com/odoo/odoo/pull/193685), then came back by accident via a forward-port of (https://github.com/odoo/odoo/pull/249441). **Solution:** Drop `ignore_future=True` from `_compute_leaves()` Task-6534125
Kit sales now correctly exclude deliveries completed after the selected accrual date when calculating delivered quantities. This prevents orders from appearing as ready to invoice when their delivery happened outside the reporting period.
Original PR description
When selling a kit, the qty_delivered_at_date was not ignoring moves that were done after the accrual_entry_date. Steps to reproduce: ------------------- * Create a kit with any component and make it's invoice policy "Delivered quantities" * Create a sale order for this kit and confirm it, change the order date to any date in the past * Validate the picking * Go check the "Invoiced to be issued" * Change the accrual_entry_date to a date before the picking was validated > Observation: The order still appears opw-6290222 Forward-Port-Of: odoo/odoo#286406 Forward-Port-Of: odoo/odoo#274745
The Frontdesk Members kiosk now loads correctly after fixing where its barcode input component is sourced from. This prevents the kiosk from crashing when staff open it, helping member check-ins continue smoothly.
Original PR description
Steps to reproduce: -Open the Frontdesk application. -Open the Frontdesk Members station. -Open the Kiosk. Problem: -The Members Kiosk crashes because BarcodeInput is imported from manual_barcode, which does not export it, preventing frontdesk_members from being registered. Solution: - Import BarcodeInput from `@barcodes/components/barcode_input` so the Members Kiosk component loads and registers correctly. Issue introduced by https://github.com/odoo/odoo/commit/90f6801a3ab96f01197f61259ff31a501877ab88 TaskId-6562097
General Ledger exports now include the same accounts shown on screen when users apply a search filter. This prevents missing lines in exported reports and makes downloaded results more reliable for reconciliation and review.
Original PR description
When applying a search filter in the General Ledger, the lines displayed in the UI differ from the ones exported. The discrepancy comes from the fact that the UI search bar filters lines using a simple "contains" logic on the displayed line name, while the backend export relies on the account model’s `_name_search` behavior, just as in the chart of accounts. For example, searching for "40" displays the accounts 400000, 400010, and 124000 but the last one (124000) is not is in the export results. task: 5917435 Forward-Port-Of: odoo/enterprise#131011 Forward-Port-Of: odoo/enterprise#107928
French accounting localization can now be used without requiring the Partner Autocomplete feature. This lets businesses disable partner autocomplete without unintentionally removing French localization, and avoids forcing extra services in Community Edition setups.
Original PR description
*: base,partner_autocomplete Description of the issue/feature this PR addresses: Pull Request #283584 added a dependency between l10n_fr_account and partner_autocomplete. Some comments on that PR…
*: base,partner_autocomplete Description of the issue/feature this PR addresses: Pull Request #283584 added a dependency between l10n_fr_account and partner_autocomplete. Some comments on that PR proposed to not add dependency (cf https://github.com/odoo/odoo/pull/283584#discussion_r3822664753). Adding this dependency does not allow anymore to deactivate partner_autocomplete on an Odoo instance. Tested on runbot on both Community and Enterprise Edition, if you install French localization and then you want to untick "Partner autocomplete" option in General Settings, it would try to remove French localization. In addition, on most Community Edition integration, this module partner_autocomplete is not installed (nor is IAP) and this change would force installation and usage of partner_autocomplete. <img width="1164" height="596" alt="image" src="https://github.com/user-attachments/assets/d4378241-ffea-4236-8d2f-d75adedae1df" /> Current behavior before PR: With French localization installed you cannot deactivate Partner autocomplete option. Desired behavior after PR is merged: French localization does not depend on partner_autocomplete and the function to retrieve identifiers to enrich is moved to base module (since the other default field retrieved, vat is part of base module). The method may need to be renamed though, but I did not want to change too much the existing signatures. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixed Taiwan ECPay B2B e-invoices so tax amounts are sent based on the invoice's booked tax instead of recalculating them differently. This prevents rejected invoices involving down payments and helps ensure the e-invoice tax matches accounting records.
Original PR description
Current behavior: -- Sending a B2B invoice that deducts a down payment is rejected by ECPay with "(item tax discrepancy exceeds 1 NT$)", so the invoice cannot be issued at all. When it is accepted,…
Current behavior: -- Sending a B2B invoice that deducts a down payment is rejected by ECPay with "(item tax discrepancy exceeds 1 NT$)", so the invoice cannot be issued at all. When it is accepted, the tax on the e-invoice can still differ from the tax the invoice books. Expected behavior: -- The invoice is accepted, and the tax reported on the e-invoice is the one the invoice booked. Steps to reproduce: -- - Set a company up in Taiwan (TWD) with the ECPay credentials filled in - Create a sale order of 190,630 for a customer with a VAT number - Invoice a 50% down payment through the down payment wizard, then a 30% one, and post both - Invoice the remainder and post it - Send the final invoice to ECPay Cause of the issue: -- _l10n_tw_edi_prepare_item_list rebuilt the tax from the raw amount of every line and rounded that total once. Both steps also disagree with the invoice. Negative lines resulting from downpayments seem to be more strictly checked on ECPay and taxes cannot be re-derived easily by ECPay's system. There is a also a relevant but slightly different issue where the invoice amount is calculated differently but the ECPay page will show a different value. e.g. the invoice rounds each computation key on its own: 50.00 - 16.50 = 33.50 rounds to 34 where the invoice books 50 - 17 = 33. No issue was detected for purely positive lines (a transaction with different products but no downpayment) Fix: -- Use the tax amount the line carries when it has one, and fall back to the raw amount otherwise, so the payload reports what the invoice booked. Send the tax of each line in the ItemTax field. Let ECPay derive its own per-item tax and checks it against the declared total for purely positive lines, and recalculate them for negative so the rounding difference between them is spread one unit at a time across the lines, the way ECPay distributes it. opw-6424237 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281928
This update fixes several issues introduced by the blog redesign so existing blog pages keep their intended look after upgrades. It restores important cover sizing and color choices, improves scheduled post labels and dates, and makes sidebars, tags, and table of contents behavior clearer for editors and visitors.
Original PR description
Related to task-3083656
Copying and pasting list items that contain nested lists now preserves the intended content more accurately. This prevents users from accidentally copying extra nested items or losing the outer list structure when editing rich text.
Original PR description
Problem: Copying content from a list item containing a nested list can either include the unselected nested list or lose part of the copied content. Solution: - Detect whether the whole `<li>` was selected before copying the full list item with its nested lists. - When only part of the list item is selected, copy only the selected content and rebuild the required `<li>` wrapper. - Apply this logic only to list items with multiple top-level children. Steps to reproduce: - Add bullet list with nested list. - CTRL+A - Press Enter twice to create new paragraph. - Paste. - Observe the outer list is lost. task-6438347 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281205
This fixes an issue where opening the Project Pivot view from a saved My Tasks favorite could crash. Saved task reporting views now handle personal stages correctly, improving reliability for users who track work through favorites and Pivot reports.
Original PR description
Since the introduction of `read_grouping_sets` for Pivot views, opening the Pivot view from a saved favorite filter can crash. ### **Steps to reproduce:** - Install Project. - Open My Tasks. - Save…
Since the introduction of `read_grouping_sets` for Pivot views, opening the Pivot view from a saved favorite filter can crash. ### **Steps to reproduce:** - Install Project. - Open My Tasks. - Save the current filter as a favorite. - Switch to the Pivot view. ### **Error:** ``` ValueError: Cannot convert project.task.personal_stage_id to SQL because it is not stored. ``` ### **Root Cause:** Since [commit](https://github.com/odoo/odoo/pull/194413/changes/166a546ec52784c413f5b5d7d29af89d618d6519), Pivot views use `_read_grouping_sets` instead of `_read_group`. `project.task` only remaps `personal_stage_type_id` to the stored `personal_stage_type_ids` in [_read_group](https://github.com/odoo/odoo/blob/5f6fb63d5d7585805642c702d096b2f882e73761/addons/project/models/project_task.py#L2169-L2179), so the remapping is bypassed for Pivot views. The ORM then attempts to group by the non-stored `personal_stage_type_id` relation, leading to the SQL conversion error. ### **Fix:** Mirror the remapping logic in `_read_grouping_sets` so Pivot views use `personal_stage_type_ids` before the ORM generates the SQL query. **opw-6306389** Forward-Port-Of: odoo/odoo#272985
This fixes an issue where manually changing an order's total weight did not refresh the delivery price for rule-based shipping methods. Businesses using weight-based delivery pricing will now see the correct shipping charge applied before adding the delivery line, preventing undercharged orders.
Original PR description
Steps to reproduce ------------------ - Install `website_sale_stock` and `sale_management` module. - Create a product. - Create a rule-based delivery method with: - In Pricing tab click add a line -…
Steps to reproduce ------------------ - Install `website_sale_stock` and `sale_management` module. - Create a product. - Create a rule-based delivery method with: - In Pricing tab click add a line - condition: `Quantity >= 0` - variable factor: `weight` - price per unit: 2 - Create a quotation containing the product. - Open the delivery method wizard by clicking into `Add Shipping` - Select the rule-based delivery method. - Change the total weight from 0 to 10. - Add the delivery method. Issue ----- - Changing the total weight does not recompute the delivery price. - The delivery line is added with a price of 0 instead of 20. Cause ----- The delivery wizard defines `_onchange_carrier_id` for both `carrier_id` and `total_weight` https://github.com/odoo/odoo/blob/9860ba5a593c5e7723494674b62890d16ae1a9a8/addons/delivery/wizard/choose_delivery_carrier.py#L41-L50 The call flow is expected to be: `total_weight` change -> `_onchange_carrier_id` -> `_get_delivery_rate` -> `rate_shipment` `_get_delivery_rate` passes the manually entered weight through the `order_weight` context key: https://github.com/odoo/odoo/blob/9860ba5a593c5e7723494674b62890d16ae1a9a8/addons/delivery/wizard/choose_delivery_carrier.py#L87-L90 The rule-based carrier gives this context value priority over the saved order weight and the weight computed from order lines: https://github.com/odoo/odoo/blob/9860ba5a593c5e7723494674b62890d16ae1a9a8/addons/delivery/models/delivery_carrier.py#L588-L594 For example, with `total_weight = 10` and a price factor of 2, the expected calculation is: `delivery_price = 0 + 2 * 10 = 20` However, the pickup-location implementation added an override in `website_sale_stock` that declared only `carrier_id` as an onchange trigger: https://github.com/odoo/odoo/blob/0da3259034ff3b2b79f417df53969fe017207195/addons/website_sale_stock/wizard/choose_delivery_carrier.py#L13-L16 Since the override uses the same method name, its decorator replaces the base onchange specification. Therefore, changing `total_weight` does not call the method and the initial `delivery_price = 0` is kept. This does not occur in saas-19.2. because `website_sale_stock` does not override the delivery wizard there. The base method remains registered for both `carrier_id` and `total_weight`: The conflicting override was introduced later in this [commit](https://github.com/odoo/odoo/commit/0da3259034ff3b2b79f417df53969fe017207195) from saas-19.3 Fix --- Add `total_weight` to the `website_sale_stock` onchange decorator so the inherited delivery-rate computation runs when the user edits the weight. --- opw-6516301 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285864
This fixes a mobile and tablet issue where opening a file picker inside an editable list could trigger an automatic save and close the row being edited. Users can now attach files in these embedded form lists without silently losing the changes they were making.
Original PR description
The form view autosaves on 'visibilitychange' (e.g. when the user switches tab/app) to avoid losing unsaved changes. On mobile, opening the native file picker for a binary field also fires 'visibilitychange', which triggered this autosave. When that binary field was part of an editable x2many list, the autosave forced the row out of edition before the file could be selected, silently discarding the edition in progress. Skip the autosave when a x2many field of the root record currently has a row in edition. Can be reproduced in eLearning > course > content > Additional Resources, on mobile devices (must force "desktop mode" in the browser), and on tablets. opw~6517735 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#287855 Forward-Port-Of: odoo/odoo#287581
Creating multiple helpdesk teams with website forms no longer adds repeated Help menu entries on the website. Existing Help menus are reused across teams, keeping website navigation clean and avoiding confusing duplicate links.
Original PR description
Currently on creating new helpdesk team everytime a new website menu is created. ### **Steps to Reproduce:** 1) Install website_helpdesk 2) Navigate to `Helpdesk>Configuration>Helpdesk Team`. 3)…
Currently on creating new helpdesk team everytime a new website menu is created. ### **Steps to Reproduce:** 1) Install website_helpdesk 2) Navigate to `Helpdesk>Configuration>Helpdesk Team`. 3) Create 2 helpdesk team with `Website Form` option enable. 4) Navigate to Website. ### **Observed Behavior:** Two Help menus are created. ### **Expected Behavior:** Multiple menus should not be created. ### **Root Cause:** The menu creation logic relies on the following [condition](https://github.com/odoo/enterprise/blob/b66097122ba3a758734ac6fb2b26579c35cb72c2/website_helpdesk/models/helpdesk.py#L111-L112) `team_count_by_website` is built from `_read_group(..., ['website_id'], ...)`, which keys its result by the `website_id` *recordset*, not its id. Looking it up with `team_count_by_website.get(website.id, 0)` therefore always misses and falls back to `0`, so `team_count <= 1` is always `True` regardless of how many teams already exist for that website. The only thing left guarding menu creation is `any(team.website_menu_id for team in teams)`, which only looks at the teams in the current create/write call, not every team on that website. So saving a second team in a separate call always creates another menu. ### Fix: Make the website menu a resource shared by every team with the website form enabled on a given website, instead of "owned" by whichever team created it: - Before creating a new menu, look up other teams (active or archived) that already point to a menu, matched through the `website_menu_id` relation between teams rather than a hardcoded `/helpdesk` URL, so a customized menu URL doesn't cause a duplicate to be created. Reuse that menu when found. - Only delete a menu once no team (active or archived) still references it, checked before removing a team's own reference. **opw-6303846** Forward-Port-Of: odoo/enterprise#130401 Forward-Port-Of: odoo/enterprise#121120