Wednesday, September 2, 2026
44 changes · saas-19.3
Resolved issues and error corrections
The Helpdesk team card layout was adjusted so the email alias lines up neatly with the team name. This small visual fix improves readability and gives the Helpdesk configuration screen a more polished appearance.
Original PR description
In this commit, we remove the margin before the mail alias, ensuring aligment within the helpdesk team card. task-6416578 Forward-Port-Of: odoo/enterprise#129865
This update re-enables important automated checks around inventory valuation across purchasing, manufacturing, point of sale, repairs, landed costs, dropshipping, and project-related stock accounting. It also fixes issues found while restoring those checks, helping ensure costs and accounting values remain accurate in complex stock and invoicing scenarios.
When a contact with multiple active user accounts is mentioned, every linked active user now receives the notification immediately. This prevents missed real-time alerts and ensures users no longer need to reload to see mentions intended for them.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This happens because the notification is sent on the single user that _notify_get_recipients picks for a partner, and since "[REF] bus, mail: use user rather than partner as bus target" a user is its own bus channel, so the other users of that partner are no longer reached. The notification record is stored per partner, which is why a reload shows it. This commit fixes the issue by sending to every active user of the notified partner. https://github.com/odoo/enterprise/pull/129969
Users who type a date or time directly into a field and press Enter will now have that value saved correctly. This prevents lost edits in forms when using keyboard-based data entry instead of opening the calendar picker.
Original PR description
Example of steps: - open any form view with a date field - navigate to this date field with tab - For example clicking on the previous field and pressing tab - type another date press enter (without…
Example of steps: - open any form view with a date field - navigate to this date field with tab - For example clicking on the previous field and pressing tab - type another date press enter (without opening the picker) - save => The change has not been saved. `onInputKeydown` closes the picker on Escape and on Enter the same way: by calling `saveAndClose()` directly, without first calling `updateValueFromInputs()` to parse the raw text typed in the input into the reactive `pickerProps.value`. This doesn't work when the calendar popover was never opened (i.e. the value was typed by hand instead of picked visually), `saveAndClose()` calls `apply()` directly, which only pushes `pickerProps.value` to `onApply`. Since that value was never refreshed from the input's text, `apply()` sees no change and silently returns without calling `onApply`, so the typed value is lost. Every other confirmation path (`onInputChange`, the popover's `onClose`, and `Ctrl+Enter`) already calls `updateValueFromInputs()` before proceeding, so plain Enter was the only path missing it. To fix this we call `updateValueFromInputs()` before `saveAndClose()` in the Enter/Escape case, like every other confirmation path already does. opw-6511435
This fix prevents saved copies of incoming emails from being selected as the main document for vendor bills. Bills created from emailed XML files with embedded PDFs now show the actual invoice document instead of a broken email-file preview.
Original PR description
When an incoming mail server has the "Keep Original" option enabled, a copy of every incoming mail is stored as original_email.eml. Because it is not a document of the invoice, the system unattaches…
When an incoming mail server has the "Keep Original" option enabled, a copy of every incoming mail is stored as original_email.eml. Because it is not a document of the invoice, the system unattaches it, however it may still be used as main attachment in case no other PDF or image was attached to the message. Steps to reproduce: - Configure an incoming mail server with "Keep Original" enabled, using an alias pointing to a vendor bill journal. - Send a mail to that alias containing an xml embedding a PDF. - Open that bill Issue: The invoice's main attachment points to the .eml file. This occurs because it is set before the PDF is extracted from the xml. Then, when import extracts the PDF, it is added as attachment on the invoice, but we already have a main attachment that won't be overwritten. However, once a pdf or image is added as attachment, the system will show the (broken) preview. opw-6431726 Forward-Port-Of: odoo/odoo#285409 Forward-Port-Of: odoo/odoo#280318
Invoices created from POS sales linked to a sales order now keep the customer's original reference. This helps businesses match invoices to customer purchase orders while still keeping POS traceability for combined batches.
Original PR description
The pos_sale override of _prepare_invoice_vals left ref and invoice_origin untouched, so the SO's client_order_ref was lost on the invoice. The fix is to mirror sale.order._prepare_invoice and set both fields from the linked SO, while preserving pos_reference traceability for mixed consolidated batches. task-id: 6295629 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278035
When a contact linked to multiple active users is mentioned, all of those users now receive the notification immediately instead of only seeing it after reloading. Related performance test expectations were updated to reflect the extra notification lookup work.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This commit raises the query counts of the activity tests: the fix in odoo resolves each notified partner to its active users, which costs one query per post with an inbox recipient. https://github.com/odoo/odoo/pull/283836
Fixes an issue in Project Forecast where automatic planning could behave incorrectly when several roles were involved. This helps teams generate more accurate schedules and staffing plans without manual corrections.
Original PR description
task-6484707 Forward-Port-Of: odoo/enterprise#129246 Forward-Port-Of: odoo/enterprise#128541
Long delivery method names now wrap correctly during eCommerce checkout instead of pushing the page layout out of alignment. This keeps the checkout experience readable and usable for customers when shipping options include long location or zone lists.
Original PR description
Issue ----------- Long delivery method names containing lists of locations/zones do not wrap properly on the eCommerce checkout page, causing the layout to overflow. Cause of the issue -----------…
Issue ----------- Long delivery method names containing lists of locations/zones do not wrap properly on the eCommerce checkout page, causing the layout to overflow. Cause of the issue ----------- The first column of `[.o_delivery_method_row](https://github.com/odoo/odoo/blob/saas-19.3/addons/website_sale/static/src/scss/website_sale_delivery.scss#L2)` uses `minmax(max-content, 1fr)`. `max-content` prevents the column from shrinking when the delivery method name is too long. Steps to reproduce ----------- 1. Create a Delivery Method with a long list of locations/zones in its name. 2. Go to the eCommerce checkout at the address page. 3. Observe that the delivery method name does not wrap and breaks the layout. Before Fix ----------- The `max-content` minimum prevents the delivery method name from wrapping, causing the layout to overflow. <img width="1781" height="852" alt="image" src="https://github.com/user-attachments/assets/1150a8ef-e2d8-49ab-9553-fe9728258060" /> After Fix ----------- Change `max-content` to `min-content` so the column can shrink and the delivery method name wraps. <img width="1882" height="890" alt="image" src="https://github.com/user-attachments/assets/84cfd5a4-796d-4b9f-bfdb-c18434f8b67f" /> [OPW- 6486780 ](https://www.odoo.com/odoo/project/70/tasks/6486780) [UPG- 4609267 ](https://upgrade.odoo.com/odoo/upgrade.request/4609267) Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix adjusts an automated website tour so it no longer fails unpredictably during testing. It helps keep release validation stable and reduces noise from false test failures, without changing the customer-facing website experience.
Original PR description
This is just a backport of the step from 19.3 where the tour is never failing randomly. https://github.com/odoo/odoo/commit/c5d7a6a90be4730e18070826a9394ab10dfc6be8#diff-c7720501ec33f5f92c907d8bb41de50edd832a4564317073e801a6915796a6bdR260-R261 runbot-237566 Forward-Port-Of: odoo/odoo#284689
This update fixes typos and inconsistent wording in the Point of Sale LNA checklist. It makes the checklist clearer for teams using or reviewing the document, without changing product behavior.
Original PR description
Fixed some typos and inconsistencies on the LNA checklist document Task-[6330795](https://www.odoo.com/odoo/project/1737/tasks/6330795) 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#281950
Swiss payroll employee records will no longer show repeated system-generated updates for LPP mutation changes. This reduces noise in the activity history, making important employee updates easier to find, especially when automated payroll jobs run frequently.
Original PR description
Calling `_create_or_update_snapshot` after writing on an employee recomputes `lpp_mutations`, deleting and recreating the linked records. Because `lpp_mutations` was tracked, every `write` on an employee generated unhelpful chatter entries, cluttering important history. This was especially noisy during frequent writes in hourly crons. Disable field tracking on `lpp_mutations` to improve chatter clarity and overall user experience. opw-6285407 --- Forward-Port-Of: odoo/enterprise#129628 Forward-Port-Of: odoo/enterprise#128033
This update stops users from creating self-order boxes from the printer setup screen. It helps ensure each self-order box is linked to a real physical device, reducing setup mistakes and unreliable point-of-sale configurations.
Original PR description
We prevent users from creating oboxes from pos.printer model, as oboxes should be paired with an actual device. Forward-Port-Of: odoo/enterprise#129960
This fix makes the creation order of accounting lines consistent when subcontracting inventory movements are completed. It helps avoid intermittent test failures and unpredictable accounting line ordering without changing business workflows.
Original PR description
The search order on account move line depends on date, move name and id. This search result order can be non deterministic because, when creating account move line from stock valuation, it depends on…
The search order on account move line depends on date, move name and id. This search result order can be non deterministic because, when creating account move line from stock valuation, it depends on the order from a set, but sets are unordered. **Step to reproduce** Run [test_subcontracting_purchase_bill](https://github.com/odoo/odoo/blob/13b2781978b0edad0df0800404276919b767e32b/addons/mrp_subcontracting_purchase/tests/test_mrp_subcontracting_purchase.py#L268) in: Single app, community, with demo data. **Observation** * The search: When doing the search since we didn't specify any order, the search from account.move.line will ordered by: https://github.com/odoo/odoo/blob/3dd41395e2e4205fa477eb474d4a4dba0a976154/addons/account/models/account_move_line.py#L23 https://github.com/odoo/odoo/blob/3dd41395e2e4205fa477eb474d4a4dba0a976154/addons/account/models/account_move_line.py#L1664 Since, for the components the date and move name are the same it will only depend on the aml ids: * `Account.move.line` creation: When it validate the receipt (`button_validate`) https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/mrp_subcontracting_purchase/tests/test_mrp_subcontracting_purchase.py#L296 It will mark as done the picking (`_action_done`) and the productions (`button_mark_done`) linked to this picking. https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/stock/models/stock_picking.py#L1429 https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/mrp_subcontracting/models/stock_picking.py#L49 Modify the inventory accordingly (`_post_inventory`) https://github.com/odoo/odoo/blob/869c750f978b1b00a4a04bd61226f0e20d2e7729/addons/mrp/models/mrp_production.py#L2231 while inside of `_post_inventory`, it will process all the production moves, for this it will divided them in set to process them by batch: https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/addons/mrp/models/mrp_production.py#L1904-L1911 From this set, it will create the `account.move.line`: It retrieve the actual stock move with the browse, and call `_action_done`, from where the stock valuation layer will create the `account.move.line`. https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/addons/mrp/models/mrp_production.py#L1913 https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/addons/stock_account/models/stock_move.py#L187 The issue arise because a set read order is non deterministic. runbot-939794 Forward-Port-Of: odoo/odoo#279396
Custom website snippets with very large responsive text now display at the right size in the snippets dialog. This prevents misleading previews for editors while keeping the actual page content unchanged.
Original PR description
Steps to reproduce: - Go to the website editor. - Add a snippet with editable text to the page. - Select the text and set its font size to 144. - Save the edited block as a custom snippet. - Open the…
Steps to reproduce: - Go to the website editor. - Add a snippet with editable text to the page. - Select the text and set its font size to 144. - Save the edited block as a custom snippet. - Open the snippets dialog. - Go to the Custom category. => The custom snippet preview shows the text too large. Before this commit, responsive font sizes using `clamp()` with a `vw` term were rendered too large in the block dialog. The `vw` value was based on the full preview iframe width, while snippets were displayed inside columns. After this commit, the block dialog adjusts `vw` values on cloned `.o_rfs` preview content only, so the preview matches its column width without changing the snippet dropped on the page. task-6303725 | BEFORE (font size -> 144) | AFTER (font size -> 144) | | ------------- | ------------- | | <img width="416" height="409" alt="image" src="https://github.com/user-attachments/assets/e0eb0a4e-eb7b-4ee6-b080-536ea2a75c68" /> | <img width="421" height="272" alt="image" src="https://github.com/user-attachments/assets/6468a234-0966-45c9-9435-e97d9752b794" /> |
This fixes an issue where certain changed manufacturing orders could incorrectly double the produced quantity or fail during completion. Businesses can now complete affected make-to-order production flows reliably, with correct quantities and inventory valuation.
Original PR description
When the quantity of a make-to-order manufacturing order is changed, its finished move is copied to propagate the extra quantity downstream. In some cases (after splitting then merging back…
When the quantity of a make-to-order manufacturing order is changed, its finished move is copied to propagate the extra quantity downstream. In some cases (after splitting then merging back productions) that copy is not merged back, so the order ends up with two finished moves for the same product. On validation, two things then go wrong: - _post_inventory writes the produced quantity on each finished move, so both get the full quantity and the production is doubled - mrp_account._cal_price prices the finished move and calls ensure_one(), which raises "Expected singleton" for an average/fifo product, so "Produce All" fails Split the produced quantity across the finished moves with unit_factor (like _set_qty_producing already does), and price them as a whole instead of expecting a single finished move. Steps to reproduce: - Create a BoM for product A with the MTO route, and a component B - Create a Sale Order for 30 units of A, confirm it - Split the MO into 3 productions of 10, merge two of them - On the third, Update Quantity 10 -> 15, then Produce All - The product should be produced once (15, not 30), with A valued in average/fifo it instead of an error. opw-6242504 opw-6310972 opw-6307025 opw-6354739 Forward-Port-Of: odoo/odoo#282733 Forward-Port-Of: odoo/odoo#269254
The editor no longer shows a non-working title replacement icon when users open the link popup for an image. This removes a confusing control and makes image link editing clearer.
Original PR description
**Current behavior before PR:** Steps to reproduce the issue: - Add an image - Add a link to the image - Put cursor just right after the image link so that link popover is opened - Notice that there is a wand icon in link popover to replace title, clicking on it does nothing **Desired behavior after PR:** There should be no replace title icon in popover for image-link. task-6420902 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279076
Odoo VoIP now correctly updates call records when an incoming call is answered or rejected in another softphone such as Linphone. This prevents calls from being incorrectly marked as missed or left in progress, giving users a clearer call history when using multiple VoIP tools.
Original PR description
Steps to reproduce: - Have an external VoIP software configured (e.g. Linphone) - Have your Odoo configured and opened too - Call your VoIP number, using your smartphone => Both the softphone and…
Steps to reproduce: - Have an external VoIP software configured (e.g. Linphone) - Have your Odoo configured and opened too - Call your VoIP number, using your smartphone => Both the softphone and Linphone ring - Answer or reject using Linphone => The VoIP call record in Odoo immediately switches from "Trying to call" to "Missed". While there was no guarantee for our VoIP integration to work alongside Linphone in 19.0, we decided this should be an easy safe enough fix. Starting 19.2 (with [1]), the fix will be simplified and hopefully prettier thanks to the ameliorations that were made. After this fix, provided Odoo is open while Linphone is used, the call records will now switch to the right terminated / rejected status, still immediately once Linphone answers / rejects. In future versions and especially 20.0+, the system will be different and will allow way more features like this one to work better (e.g. here the call record only even exists if Odoo is opened while using Linphone and we won't have any information about the call duration). [1]: https://github.com/odoo/enterprise/commit/942f32316ab02d8c739fe7fdd5ec2bdde472a68e task-6449259 Forward-Port-Of: odoo/enterprise#128644 Forward-Port-Of: odoo/enterprise#127077
This fixes an access error that prevented accountants from generating BOE files for Spanish Modelo 115 tax reports unless they also had company access-rights permissions. Accountants can now create the required BOE export without needing unnecessary administrative privileges.
Original PR description
Users who only have accounting rights (not the Settings > Users Companies > Access Rights group) get an access error on the Companies model when generating the BOE file for the Modelo 115 tax…
Users who only have accounting rights (not the Settings > Users Companies > Access Rights group) get an access error on the Companies model when generating the BOE file for the Modelo 115 tax reports, even though exporting a BOE file has nothing to do with editing company configuration and should be available to any accountant. Steps to reproduce: ------------------- * Log in as a user with accounting rights only (not part of the Companies > Access Rights group) * Go to Accounting > Reporting > Tax Return, open the Mod 115 report * Click the gear icon > BOE > Generate BOE > Observation: An AccessError is raised: "You are not allowed to modify 'Companies' (res.company) ... This operation is allowed for the following groups: Access Rights", even though the user is not trying to edit the company. Why the fix: ------------ The BOE wizard shared by Mod 111/115/303 declares a `company_partner_id` field, related to `company_id.partner_id`, with `readonly=False`. That field is invisible in every view and only exists to compute the domain of `partner_bank_id`; it was never meant to be edited by the user. Because it is declared writable, the ORM attaches an inverse to the related field, so saving the wizard (which happens when generating the BOE, since the field, though invisible, is still part of the view and thus of the saved values) writes `company.partner_id` back onto `res.company`, even though the value never actually changes. That implicit write requires write access on res.company, which is only granted to the Access Rights group, causing the error for regular accountants. Dropping `readonly=False` keeps the field as a plain readonly related field, still usable for the bank account domain, without ever triggering that spurious write. opw-6388869 Forward-Port-Of: odoo/enterprise#129924 Forward-Port-Of: odoo/enterprise#126661
Users can now discard changes after reordering long order-line lists that span multiple pages without hitting an error. This prevents an interruption in sales document editing when large quotations or similar records have many lines.
Original PR description
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to…
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to reorder them - Discard all changes (X shaped button) You will have an evaluation error **Behavior:** When loading a list of records exceeding the limit, only parts of the records are saved in `_cache`. When triggering a reordering of said list, all records need to be loaded including the ones on other pages: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/static_list.js#L1139-L1149 `_getResIdsToLoad()` gets all Ids missing from the cache, these are then passed through `._createRecordDatapoint` and will then be stored in `_cache`. The issue is that the Datapoints are getting created with only `activeFields` as data, which in our case are `id` and `sequence` When discarding the changes `._checkValidity()`is called on each Datapoint: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/record.js#L423-L429 And then `._isInvisible()` is called. This is where the issue happens, since only `sequence` and `id` are stored, when we try evaluate `combo_item_id`, which is the condition to see if sequence is invisible, `combo_item_id` is not found and we get an Evaluation Error. This commit prevents going into `._checkValidity()` by adding `this.isInEdition` to the check leading to it, requiring that the record is in 'edit' mode which is not the case for records created with `_createRecordDatapoint()` opw-6399024 Forward-Port-Of: odoo/odoo#281018
Swiss payroll payment report generation no longer fails when checking Revolut bank accounts after a bank data model change. This helps ensure ISO20022 payment files for Swiss payslips can be produced reliably.
Original PR description
res.bank and res.partner.bank.bank_id were removed in saas-19.2: the bank's identity now lives directly on the bank account as bank_bic and bank_name. The Revolut detection added in fba51a6a77a still read bank_account.bank_id, raising an AttributeError when generating the ISO20022 payment report for Swiss payslips. Forward-Port-Of: odoo/enterprise#129156
Checkout now stops carts that become priced at zero due to country-based pricing when zero-priced product sales are not allowed. Customers are sent back to the cart with a clear warning instead of experiencing a stalled payment step or timeout.
Original PR description
When 'Prevent Sale of Zero Priced Product' is enabled and a country-group pricelist prices a product at 0 once the customer's country becomes known during checkout, the cart total becomes 0. The 'free order' branch then validated the order at the payment step, which could hang and time out for a cart that is not actually sellable. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285739 Forward-Port-Of: odoo/odoo#284959
This fixes an issue where pickup location options could fail to load when a customer's delivery address included a country. Customers should now see the correct pickup choices during checkout, reducing blocked or confusing purchase flows.
Original PR description
`country_id` is a number so the fix in #281720 - which avoids a traceback when no country is present - now leads to nothing being loaded when the delivery address has a country. Because `country_id?.id` now gives `undefined`. The fix makes sense only if the field is marked as a many2One as done in 319bb52 (which was only merged in 19.4+). This is consistent with fix edf65dc done in 19.4+ as well.
French e-invoicing responses without a tracking ID are now ignored instead of being saved in a pending state. This prevents scheduled status updates from crashing and helps invoice and vendor bill processing continue normally.
Original PR description
Steps to reproduce: - Install `l10n_fr_pdp` and `l10n_be` module - Activate `French e-invoicing` (you need to put your DB in test mode) (i.e: `account_peppol.edi.mode = 'test'` in system parameter)…
Steps to reproduce:
- Install `l10n_fr_pdp` and `l10n_be` module
- Activate `French e-invoicing` (you need to put your DB in test mode)
(i.e: `account_peppol.edi.mode = 'test'` in system parameter) Refer this Documentation https://www.odoo.com/documentation/19.0/applications/finance/fiscal_localizations/france.html?highlight=e%20invoicing#localizations-france-e-invoicing-fac-elec-config
- Create a Invoice and Sent with `E-invoicing`
- Run `PEPPOL: retrieve new documents` Cron
- In Invoice Other Info > `E-Invoicing Status` should be in `Done` state
- Now Vendor Bill is created for that invoice > Cancel that bill with reason > Check `E-Invoicing Status` response for bill(one response will be without UUID)
- Go to schedule actions > `PEPPOL: update message status`
- Run it and get the traceback: `KeyError: 'false'`
Issue:
When sending a lifecycle response to the French PDP, `_pdp_send_response` calls the `/api/pdp/1/send_response` endpoint and expects IAP to return a `message_uuid` for each response.
However, IAP return a response without a message UUID, for example: ` {'messages': [{'message_uuid': False}]}` `_pdp_send_response` currently assumes that every returned message has a valid UUID and creates an `account.peppol.response` with:
```
'peppol_message_uuid': False
'peppol_state': 'processing'
```
This leaves an `account.peppol.response` in `processing` state without a UUID that can be used to track it.
During the next execution of `_cron_peppol_get_message_status`, `_peppol_get_message_status` retrieves this response through `_peppol_get_documents_for_status` and builds `uuid_to_record` using `peppol_message_uuid` as the key. The resulting mapping contains the Python value `False` as a key.
The cron then calls the PDP `1/get_document` endpoint with this invalid UUID. IAP returns it as the string `'false'`, which is passed to `_peppol_process_messages_status`. The French PDP implementation tries to retrieve the corresponding record with: `uuid_to_record[uid]`
Since the mapping contains `False` while `uid` is `'false'`, this raises: `KeyError: 'false'`
This failure prevents the status cron from completing the processing of the messages.
Solution:
Avoid creating the `account.peppol.response` when IAP does not return a `message_uuid`. A response without a UUID cannot be tracked through the PDP status flow, so creating it in `processing` state only leaves an
invalid record that will later cause the status processing to fail.
opw-6453133
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281691This fix prevents multiple server workers from blocking each other when a database starts while modules need updating. It improves reliability by allowing the update process to proceed without deadlock errors during startup.
Original PR description
When a database with a module 'to_update' starts in a multiple worker setup, we may get to the state where multiple workers took the soft lock on 'registry_loading' and none can get the hard lock and actually update the module, also throwing a deadlock traceback This PR will first release the soft lock, since we will try to get the hard lock anyways, before actually trying. This should avoid the deadlock opw-6519819 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
When users replace a selected link by pasting a new web address, the visible text now updates to match the new address. This prevents confusing mismatches where a link looks like one URL but actually points to another.
Original PR description
**Current behavior before PR:** Steps to reproduce the issue: - Create a link via typing a valid URL + space. - Copy/Paste a different URL from the browser. - Select the entire link you just created. - Paste the copied URL on top of it. Notice that the label is still the old URL even though the URL actually changed. This happens because after commit [1] When pasting a URL over an active text selection, selected content is converted into a link pointing to the pasted URL. This should not be the case if selected content is a link with same label and URL. **Desired behavior after PR is merged:** If a link is entirely selected and its label is the same as URL then it should replace the existing link label with new URL. [1]: https://github.com/odoo/odoo/commit/d356043a67e1d7291bd1302b1e90a2d9a07718da task-6456004 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281700
Fixes an issue where partial receipts involving subcontracted products could mark the wrong items as processed, creating inaccurate backorders. This helps ensure purchase receipts from subcontractors reflect the actual quantities received and prevents follow-up delivery errors.
Original PR description
### Steps to reproduce: - Create a subcontracted product P1 - Create a storable product P2 - Buy 5 units of both products from your subcontractor - On the receipt set both moves quantity to 2 Units -…
### Steps to reproduce: - Create a subcontracted product P1 - Create a storable product P2 - Buy 5 units of both products from your subcontractor - On the receipt set both moves quantity to 2 Units - Validate the receipt and create a backorder #### > Only the subcontracted move has been kept on the receipt and a backorder was created for 3 units of P1 and 5 of P2. ### Cause of the issue: Setting the quantity of the subcontracted move will automatically record the quantities on the subcontracted MO: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/stock_move.py#L83 https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/stock_move.py#L123 https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/mrp_production.py#L91 However, the `_update_finished_move` method adds and update the related subcontracted move lines marking them as *picked* to adapt the related reservation: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/mrp_subcontracting/models/mrp_production.py#L118-L164 This is problematic since picking a move line will also pick the move: https://github.com/odoo/odoo/blob/9440ff9064c77af0159a427de8f5e5721aec0de5/addons/stock/models/stock_move.py#L261-L267 And only picked moves are considered to be processed at picking validation. ### Note: The exact same issue had already been fixed in 17.0: db8b33ebb9fe23507bcba30b12741e4d688ae549 However, the fix had an issue concerning the barcode behavior as it removed the picked computation for subcontracted moves which made hybrid pickings such as the above one (with one subcontracted and one non-subcontracted move) impossible to process in the barcode app. As such, the fix and test where reverted in cf2d18c92bee55ef79db1a338e9baf12f258ee5b The present commit provides an alternative fix of the original issue keeping subcontracted moves unpicked by quantity changes without affecting the picked computation of subcontracted moves (e.g. adding a picked move line on a subcontracted move will still pick that move). Enterprise: https://github.com/odoo/enterprise/pull/123884 opw-6330584 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285614 Forward-Port-Of: odoo/odoo#275304
This fix registers the Greek electronic invoicing module with the translation system. It ensures the module can be translated through the standard process, improving localization support for Greek users.
Original PR description
Commit https://github.com/odoo/odoo/commit/45bd522dde7a67194e14a40d66944a2e34d1f79d introudced a new module without it's related `weblate.json` entry. This commit fixes this omission. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285570
The Point of Sale quotation list now hides quotations that have already been settled. This prevents staff from accidentally selecting and settling the same quotation twice, reducing duplicate payment or order handling mistakes.
Original PR description
Once a quotation is settled, opening the quotation list should not allow selecting it again. This commits updates the domain to prevent it. task-6479356 Forward-Port-Of: odoo/odoo#284768
This fix prevents users from deleting an image inside a website card cover while leaving behind an empty wrapper that the editor still treats as a valid cover. It avoids confusing editor behavior and prevents an error that could occur when using the Cover Image options.
Original PR description
It was possible to remove the image inside a card cover while keeping the figure wrapper. The card option would then still consider that there was a cover image even though the image was gone, which could also lead to a traceback. Steps to reproduce: - Insert the `s_three_columns` snippet - Click on the image of one card - Either press "Enter", "Delete", "Backspace" - Hover the "Cover Image" options => The image is removed but the `<figure>` is still there, so the option is still considered active (leading to a traceback) task-6081728 Forward-Port-Of: odoo/odoo#283106 Forward-Port-Of: odoo/odoo#280086
Users can now open WhatsApp Business account settings after switching Odoo to another language, such as French. The fix prevents a translation-related error that blocked access to the account configuration page.
Original PR description
Currently, an error occurs when a user tries to view the WhatsApp Business account. **Steps to Reproduce:** - Install the `whatsapp_oauth` module. - Go to `Settings` > `Languages` and add `French…
Currently, an error occurs when a user tries to view the WhatsApp Business account. **Steps to Reproduce:** - Install the `whatsapp_oauth` module. - Go to `Settings` > `Languages` and add `French (BE)`, then `switch to it`. - Go to `WhatsApp` > `Configuration` > `WhatsApp Business Accounts (Comptes Whatsapp Business)`. `ValueError: L'élément '<xpath expr="//div[contains(normalize-space(.), 'Receiving Messages')]">' ne peut être localisé dans la vue parente` When the user changes the language, the text in the view is translated [1]. Since the WhatsApp account view tries to locate the div using the plain text Receiving Messages [2]. Since the text has been translated in the parent view, the XPath can no longer locate the element and raise the error. This commit ensures that the XPath uses the name attribute to identify the element, which is language-independent. We cannot use the class attribute because the same class is used by other div elements. [1]- https://github.com/odoo/enterprise/blob/a3db72899cb97612505aebbd5450aeb65205db73/whatsapp/views/whatsapp_account_views.xml#L81-L84 [2]- https://github.com/odoo/enterprise/blob/a3db72899cb97612505aebbd5450aeb65205db73/whatsapp_oauth/views/whatsapp_account_views.xml#L61-L63 7534862409 Forward-Port-Of: odoo/enterprise#130003
This fix prevents an error when users navigate from an email alias to its related Helpdesk Team and then open the Tickets list. The system now uses the correct Helpdesk Team information, so the ticket view loads normally instead of showing a missing record error.
Original PR description
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe…
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe error ### Description of the issue/feature this PR addresses: **Issue:** When navigating from an email alias to its parent document (e.g., a Helpdesk Team), the web client incorrectly retains the `active_id` and `active_model` of the alias in the context. **Solution:** We updated the `action_view_ticket` method in `helpdesk.team` to explicitly inject the correct `active_model` and `active_id` into the context before calling `_for_xml_id`. This overwrites the polluted Alias data before the window action is evaluated. ### Current behavior before PR: Clicking the "Tickets" smart button passes the old alias context into the action. This bad data flows into the ticket view, which attempts to look up a Helpdesk Team using the Alias's ID to generate the empty list help message, resulting in a `MissingError`. ### Desired behavior after PR: The Python action sanitizes the context at the source, ensuring that the XML action and subsequent view evaluations receive the correct Helpdesk Team ID. Ultimately, the view will load normally without crashing. opw-6395638 Forward-Port-Of: odoo/enterprise#129939 Forward-Port-Of: odoo/enterprise#125232
Completed field service shifts linked to sales orders now keep their planned hours instead of being reset to zero. This prevents already finished work from incorrectly appearing as still needing to be planned, improving planning accuracy for sales order tracking.
Original PR description
## before: When marking a shift linked to SO as complete. The `allocated_hours` of this shift is reset to 0. So when the `Planned` button tries to compute the `planning_hours_planned` it adds zero to the planned hours, making all the hours go to the `To Plan`, which is incorrect ## after: prevents the `allocated_hours` from being recomputed when making the shift as complete to avoid this issue. This will leave the hours to be calculated in the `Planned` stat button instead --- task-6425357 Forward-Port-Of: odoo/enterprise#126396
The web tour system now handles cases where a saved tour can no longer be found, instead of crashing when users try to resume it. This improves stability for guided experiences, including free trial onboarding.
Original PR description
get_tour_json_by_name returned an empty array instead of False when no tour matched. TourService.getTour then skipped its `!tour` guard and crashed reading `tour.steps.length` on that string. Issue spotted on free trials Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an automated Point of Sale test that could fail on slower or heavily loaded machines. The change makes receipt feedback checks more reliable, helping ensure future updates are validated consistently without affecting day-to-day users.
Original PR description
The tour relies on the receipt rendering completing very quickly, as it removes the feedback screen after 500ms. On a slow/loaded machine (e.g. set `cpu_throttling=3` in the tour), the tour consistently fails as it waits for the feedback screen which has already disappeared. The fix is to check the feedback screen first, then confirm the receipt printing dialog. This lets the tour pass both normally and under load. runbot-946294 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285900
This update adjusts a manufacturing test so it checks the expected quantities without depending on the order in which lines appear. It helps prevent intermittent test failures, supporting more stable quality checks without changing user-facing behavior.
Original PR description
Issue: Test product_produce_6 fail from time to time due to lines being misordered. The test aim to check the amount within the line, not their order. runbot-946209 Forward-Port-Of: odoo/odoo#284406
Fixes an issue where expanding a newly created Calendar event from the quick create dialog opened a blank form instead of the event just saved. This prevents users from accidentally creating duplicate meetings for the same time slot.
Original PR description
Problem: In Calendar, dragging a slot opens the quick create dialog. Typing a subject and clicking the expand button in the dialog header creates the event, but the form that opens is empty, and…
Problem: In Calendar, dragging a slot opens the quick create dialog. Typing a subject and clicking the expand button in the dialog header creates the event, but the form that opens is empty, and saving it creates a second event for the same slot. Cause: `FormViewDialog` stores the id of the record it saved in `currentResId`, which `onExpand` passes as `res_id`. `saveRecord` sets it only in the branch that runs when no `onRecordSave` prop is given. `AttendeeCalendarController` passes one since 30478fe855cd (odoo/odoo#239435), so `currentResId` stays false and the action opens a new record. Solution: Set `currentResId` in the shared branch of `saveRecord`. It is private to `FormViewDialog`, so a consumer passing `onRecordSave` cannot set it. Steps to reproduce: - Open Calendar. - Drag a slot in the week view to open the quick create dialog. - Type a meeting subject. - Click the expand button in the dialog header. - Observe that the form opens on a new record while the event is created. Ticket [link](https://www.odoo.com/odoo/project/49/tasks/6476930) opw-6476930 Forward-Port-Of: odoo/odoo#285899
This fixes an issue in the HTML editor where changing text color could also affect nearby bold or inline text that was only partly selected. Users can now apply colors more accurately, reducing unexpected formatting in edited content.
Original PR description
Problem: When applying color on a selection that spans across partially selected inline elements (e.g. `<p><b>a[b</b>c]d</p>`), container elements whose contents are not fully selected (such as…
Problem: When applying color on a selection that spans across partially selected inline elements (e.g. `<p><b>a[b</b>c]d</p>`), container elements whose contents are not fully selected (such as `<b>`) were included in `targetedNodes`. This caused improper color formatting/nesting on partially selected elements. Cause: In `ColorPlugin._applyColor()`, `targetedNodes` were filtered by checking `isNodeEditable(node)` and `nodeName !== "T"`, but did not check whether the contents of `node` were fully selected (`areNodeContentsFullySelected(node)`). As a result, partially selected ancestor elements were included in `targetedNodes`. Solution: Filter `targetedNodes` in `_applyColor()` using `this.dependencies.selection.areNodeContentsFullySelected(node)` to ensure only fully selected nodes are targeted when applying colors. Steps to reproduce: 1. Open html_editor. 2. Insert content: `<p><b>ab</b>cd</p>`. 3. Select `b` inside `<b>` and `c` inside `<p>` (`<p><b>a[b</b>c]d</p>`). 4. Apply text color (e.g. red). 5. Observe "ab" and "c" was colored instead of just "b" and "c". task-6456443 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285658 Forward-Port-Of: odoo/odoo#281462
This update makes an automated test for reference field autocomplete behave consistently, even when small network delays occur. It helps reduce false failures in the validation pipeline without changing product behavior for users.
Original PR description
The test is non-deterministic and fails with the runbot error:
found 0 elements instead of 1:
0 matching ".ui-autocomplete .ui-menu-item:nth-child(2)"
if there is even a 100ms network delay. clear() dispatches input events, but without flushing the timers, the dropdown state at the time of click(".o_field_reference input") can be out of sync causing no menu items to render and failing the test.
This change makes the sequence deterministic without changing the assertions:
1. runAllTimers() clears the timers and allows the clear of the input to fully go through.
2. click(".o_form_view") unfocus the input so the next click of the input refocuses and triggers the menu opening.
3. checking contains on the dropdown children ensures the menu items can render before click.
runbot error: 940222
Forward-Port-Of: odoo/odoo#286055Instagram interaction calculations now handle missing responses from Meta safely. This prevents reporting errors when the external API fails and lets the interaction count default to zero instead of interrupting the process.
Original PR description
Currently, an error occurs while calculating Instagram interactions when
processing the Meta API response.
Error: `TypeError: int() argument must be a string, a bytes-like object
or a real number, not 'NoneType'
This happens because the `response` can be `None` when the Meta API
request get an error. Attempting to access the `response` as a dictionary
then results in an error.
This commit fixes the issue by using `response or {} as` a fallback. When the
`response` is `None`, an empty dictionary is used instead, causing the
interaction count to safely default to `0`.
sentry-7522266892This update ensures the Indian stock localization loads the accounting-related stock component it relies on. It prevents broken forms and failed single-app tests, helping keep stock and e-waybill workflows stable for Indian localization users.
Original PR description
The view 'l10n_in_ewaybill_stock.view_picking_form_inherit_ewaybill' is broken in single-app tests because it depends on stock.picking:country_code. That field is provided by module 'stock_account' through auto_install relationship. 'stock_account' auto_installs with 'stock' and 'account' installed. This condition exists on stable so it's safe to add this dependency. The dependency is added to l10n_in_stock because it seemed like the logical place where 'account' and 'stock' functionality comes together. [l10n_in_ewaybill_stock] ──[depends]──> [l10n_in_stock] [l10n_in_stock] ──[depends]──> [stock] [l10n_in_stock] ──[depends]──> [l10n_in] ──[depends]──> [account_tax_python] ──[depends]──> [account] REF Runbot: https://runbot.odoo.com/odoo/error/945482 Forward-Port-Of: odoo/odoo#284990
This fix prevents users from accidentally creating or seeing duplicate timesheet entries when they click Add or Create multiple times during a slow connection. It makes the timesheet workflow more reliable by ensuring rapid repeated actions are handled only once while the save is in progress.
Original PR description
Steps to reproduce: 1. Open the ActivityWatch timesheets view. 2. Throttle the network speed to simulate a slow connection. 3. Rapidly click "Add" on an ActivityWatch suggestion. 4. Click 'New', fill in the details, and rapidly click "Create" (or mash Ctrl+Enter). Issue: - Suggestion List: Multiple duplicate timesheets are created in the database. - Creation Form: The newly created timesheet appears multiple times in the UI list on the left side, even though only one might be created in the database. Cause: Both the `onTake` (ActivityWatch list) and `onSave` (Timesheet form) methods are asynchronous. Without a concurrency lock, rapid user interactions trigger these methods multiple times before the initial network request finishes, causing parallel ORM calls and duplicate UI array pushes. task-6462515 Forward-Port-Of: odoo/enterprise#129135 Forward-Port-Of: odoo/enterprise#127806
This fix prevents an error when users load sample data in the Shop Floor after a specific work center schedule has been deleted. The system now automatically uses the standard working schedule as a fallback, keeping setup and demos running smoothly.
Original PR description
Currently, an error occurs when loading the sample data in the Shop Floor. **Steps to Reproduce:** - Install the `mrp_workorder` module. - Go to `Employees` > `Configuration` > `Working Schedules`. -…
Currently, an error occurs when loading the sample data in the Shop Floor. **Steps to Reproduce:** - Install the `mrp_workorder` module. - Go to `Employees` > `Configuration` > `Working Schedules`. - Delete the `Work Center 40 hours/week` record. - Go to `Settings` > `Users & Companies` > `Groups`. - Open the `Manage Work Order Operation` group and add the `Administrator` to the `users` list. - Open the `Shop Floor`. If the `Activate your Work Center` dialog appears, click it and then click `Configure Later`. - Click `Load Samples`. `ValueError: External ID not found in the system: mrp.mrp_workcenter_calendar` After the [recent commit], the sample work center uses the `Work Center 40 hours/week` working schedule instead of `Standard 40 hours/week`. As a result, if the `Work Center 40 hours/week` record is deleted, loading the sample data raises the error [1]. This commit ensures that when the Work Center 40 hours/week calendar is not available, it falls back to `Standard 40 hours/week`, restoring the previous behavior [2]. This fallback is required because `resource_calendar_id` is mandatory from the view perspective, even though it is not required at the model level. If it is left empty, the form displays a missing required field. The `Standard 40 hours/week` calendar is always available because it is linked to the main company [3] and its `resource_calendar_id` field uses `ondelete='restrict'` [4], preventing it from being deleted. [recent commit]: https://github.com/odoo/enterprise/commit/336d721f7b353473fe5e07c29ce14ed77a88fb98 [1]- https://github.com/odoo/enterprise/blob/c0045ec3cf94650d66192a4ca3e0dc3c17daa5bd/mrp_workorder/models/mrp_production.py#L213-L216 [2]- https://github.com/odoo/enterprise/blob/51c1e74e90e510d59aad78820e2c29e821ba2854/mrp_workorder/models/mrp_production.py#L214-L217 [3]: https://github.com/odoo/odoo/blob/4c4219a7d9d51f703b15e83ab755faf1f2c8a71d/addons/resource/data/resource_data.xml#L10-L12 [4]: https://github.com/odoo/odoo/blob/4c4219a7d9d51f703b15e83ab755faf1f2c8a71d/addons/resource/models/res_company.py#L12-L13 sentry-7651161729 Forward-Port-Of: odoo/enterprise#126859
This fix ensures Twitter mentions returned by user search are sent in the format the social widget expects. Users can now see and select mentions correctly when preparing Twitter social content, avoiding a broken or confusing posting experience.
Original PR description
This commit fixes an issue with the introduction of the new user search endpoint in [1]. The new endpoint returned a list of mentions that were wrongly wrapped inside of another list. This meant that the widget couldn't properly handle them when it received the mentions. Now the mentions are properly handled by the widget as they follow the correct format. task-6026857 [1]: https://github.com/odoo/enterprise/commit/cdc2bd4bff93e5081858c4f7e2e08061131f6e2d
Original PR description
*: stock_landed_costs, purchase_{stock,mrp}, stock_dropshipping, sale_mrp, pos_mrp, repair, mrp_landed_costs, mrp_subcontracting_{dropshipping,landed_costs}, point_of_sale, {project_,}stock_account…
*: stock_landed_costs, purchase_{stock,mrp}, stock_dropshipping, sale_mrp, pos_mrp, repair, mrp_landed_costs, mrp_subcontracting_{dropshipping,landed_costs}, point_of_sale, {project_,}stock_account
Adapts the test skipped to fast merge the valuation refactoring made in https://github.com/odoo/odoo/commit/08b62a4bbcc6f9a391b2cc00a621ef4c76100229.
<img width="482" height="297" alt="table" src="https://github.com/user-attachments/assets/ba57f350-2a9e-4a51-990d-fabe14f5a56a" />
(*) Includes the one sale_project_stock_account test re-enabled through the TestAnalytics subclass.
It is organised as one commit per module. Two of the re-enabled tests surfaced genuine bugs in the new valuation model; those commits also carry the related fixes: purchase_mrp, project_stock_account Every other commit changes tests-only.
Only one skipped test remains: point_of_sale TestUi.test_05_ticket_screen, a browser tour with no stock-valuation content that was swept into the mass skip by mistake and fails for an unrelated reason (it is left to a separate point-of-sale tour investigation).
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278698
Forward-Port-Of: odoo/odoo#275246