Thursday, September 3, 2026
44 changes · saas-19.1
Enhancements to existing features
Rental stock calculations now reuse an existing shared rule for identifying products currently rented. This makes it easier for future extensions or custom modules to adjust rental quantity behavior consistently without duplicating logic.
Original PR description
There is already an existing hook on product.product ([sale_renting.models.product_product.ProductProduct._get_qty_in_rent_domain](https://github.com/acsone/enterprise/blob/2cd105c93bb7199a5ecea67a919a7ab5d9251cbf/sale_renting/models/product_product.py#L24)), use it to get the domain, so it can be inherited by other modules.
While the upstream method uses `('product_id', 'in', self.ids)` instead of this one's `('product_id', '=', self.id)`, this isn't an issue since there's a `self.ensure_one()` just above.
Forward-Port-Of: odoo/enterprise#129191Resolved issues and error corrections
Automated checks for financial reports now wait for each report section to load before moving to the next step. This prevents occasional false failures in testing and helps keep report quality checks stable after recent performance-related rendering changes.
Original PR description
After https://github.com/odoo/enterprise/pull/127516 report lines that are folded or filtered are no longer kept in the DOM with d-none. They are now removed entirely to reduce the number of rendered…
After https://github.com/odoo/enterprise/pull/127516 report lines that are folded or filtered are no longer kept in the DOM with d-none. They are now removed entirely to reduce the number of rendered components on large reports. This made several tours non-deterministic. The tours unfolded multiple lines in succession using positional nth-child selectors. Since unfolding now creates new rows, the next positional selector could match an existing row before the previous DOM update was completed, causing the tour to click the wrong line. The tour would then wait indefinitely for a child of the intended line to appear. We should wait for the expected child line after each unfold before continuing with the next action. Also make some positional triggers more specific by checking the expected line name. This ensures that each DOM update is completed before the following nth-child selector is evaluated. [error-946088](https://runbot.odoo.com/odoo/error/946088) Forward-Port-Of: odoo/enterprise#128127
Code cleanup and technical improvements
This change removes extra processing around final PDF uploads for Greek electronic invoicing. It relies on the normal Send & Print flow and safely retries uploads when needed, reducing unnecessary transaction handling without changing the user workflow.
Original PR description
The final PDF endpoint is idempotent and is safe to call repeatedly with the same invoice identifiers. Remove the unnecessary PDF-specific lock and explicit commit, let the upload status follow the normal Send & Print transaction and retry the idempotent upload when needed. Related: https://github.com/odoo/odoo/pull/281739 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285889
Corrected a small typo introduced during a previous update in the Website module. This helps ensure the related website functionality uses the intended behavior and avoids minor issues from the forward-port change.
Original PR description
During forward port, typo: should be get instead of set. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Portal users can now update their Electronic Format after adding a company name to their address. This prevents the field from appearing empty again and ensures invoice-related preferences are saved on the correct company record.
Original PR description
Steps: - Install accounting app. - Login with portal user and set `Company name` on `my/address`. - Try to edit `Electronic Format` field on my details. Issue: - `Electronic Format` field stays empty. Cause: - Since [PR](https://github.com/odoo/odoo/pull/211043) when user set `Company name` on the portal it'll create parent company and since `Electronic Format` is computed from `commercial_partner_id`, so when I update `Electronic format` field on `my/address` it'll set that value on `invoice_edi_format_store` on current address and now when I re-open `my/address` it'll compute `invoice_edi_format` from `commercial_partner_id`'s `invoice_edi_format_store` which is 'none' and it'll set `invoice_edi_format` to False and there is no way portal user can update that company's record Fix: - Update inverse of `Electronic Format` field to properly store invoice_edi_format_store value on commercial partner.
Refund lines without a product now suggest the correct type of account based on whether the document is a sale or purchase. This prevents customer credit notes from using expense accounts and vendor credit notes from using income accounts, improving accounting accuracy for contacts used as both customers and vendors.
Original PR description
Before this commit, when adding a line without a product to an invoice or credit note, `_get_most_frequent_account_for_partner` picked the partner's most-used account, filtered to an income or…
Before this commit, when adding a line without a product to an invoice or credit note, `_get_most_frequent_account_for_partner` picked the partner's most-used account, filtered to an income or expense account depending on `get_inbound_types` and `get_outbound_types`. Those helpers classify move types by cash-flow direction which is correct for choosing a receivable and payable account but wrong for choosing an income ro expense account: they group `in_refund` with `out_invoice` as "inbound", and `out_refund` with `in_invoice` as "outbound". As a result, a Vendor Credit Note line with no product would be filtered to income accounts instead of expense accounts, and a Customer Credit Note line to expense accounts instead of income accounts. This only surfaced for contacts who are both customer and vendor, since the query needs matching history to return a result; otherwise it silently falls back to the journal's default account, masking the bug for ordinary contacts. This commit uses `get_sale_types` and `get_purchase_types` instead, which classify by document side, sale vs. purchase rather than cash-flow direction, matching the classification already used for product-based lines `is_sale_document` and `is_purchase_document` opw-6373124 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277951 Forward-Port-Of: odoo/odoo#276846
Credit notes created from existing Turkish customer invoices now use the sales return account configured on the sales journal. This keeps sales and returns separated correctly in accounting reports, while cancellation reversals still mirror the original invoice as required.
Original PR description
The Turkish chart of accounts keeps sales and sales returns on separate accounts, and the sales journal carries the account to use for returns. A credit note typed in by hand already lands on it, but one created from an existing customer invoice did not. Reversing an invoice copies `account_id` over from the invoice line, and since that field is a stored compute without depends, nothing ever recomputes it, so the return kept the sales account. Set the journal account on the copied product lines instead. Reversals made to cancel an entry are left alone, as those have to mirror the original move exactly for the two to net out, and a plain duplicate is untouched. Task-6438412 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284357 Forward-Port-Of: odoo/odoo#282858
This fixes a checkout issue where POS orders using online payments could fail validation after staff added products and returned from the floor plan. The order total is now updated before payment checks run, reducing failed validations and helping payments complete reliably.
Original PR description
When products were added after selecting an online payment method and going back to the floor plan, the subsequent validation failed with "Invalid online payments" because the server's amount_unpaid was based on the old order total. Fix: sync the order to the server before querying amount_unpaid (both when online payment lines remain and when checking synced orders after deletion), so the server always has the latest total when checkRemainingOnlinePaymentLines is called. Also guard cancelPayment against calling the payment terminal interface on online payment methods that do not use one. task-id: 6330704 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277749
Analytic plan rules with a company filter no longer override the default setting in screens that are not tied to a specific business area, such as Work Centers or Employees. This prevents analytic fields from being incorrectly marked as mandatory where they should remain unavailable, reducing confusion and data-entry blockers.
Original PR description
### Issue: When an analytic plan has applicability lines with a company filter, the applicability is incorrectly applied on views that do not define a `business_domain`, such as Work Centers or…
### Issue: When an analytic plan has applicability lines with a company filter, the applicability is incorrectly applied on views that do not define a `business_domain`, such as Work Centers or Employee views For example, if a plan has: - Default Applicability: Unavailable - A line with Domain: Invoice, Company: My Company, Applicability: Mandatory Opening the analytic distribution on a Work Center shows `Mandatory` instead of the default `Unavailable` ### Cause: In commit https://github.com/odoo/odoo/commit/ffcf2ee1a3185ef73db93bfd95625844506692c5 `_get_score` was updated to return `0.5` when the applicability line's company matches the caller's company, even when no `business_domain` is provided In `_get_applicability`, the loop selects the first rule whose score exceeds the current minimum, which starts at `0`: https://github.com/odoo/odoo/blob/710e056e5171af2ab72d7d7793da3518f12faf5e/addons/analytic/models/analytic_plan.py#L255-L264 A score of `0.5` is enough to win over the default applicability, so a company-only match on a domain-specific rule incorrectly overrides the default when no `business_domain` is passed ### Steps to reproduce: - Install `mrp` and `accountant` with demo data - Enable Analytic Accounting in Settings - Open the Internal analytic plan and edit its applicability line: -- Remove the account prefix -- Default Applicability: Unavailable -- Domain: Invoice, Company: My Company (SF), Applicability: Mandatory - Go to Manufacturing > Configuration > Work Centers - Open any work center and click on Analytic Distribution Before the fix, Internal is shown as Mandatory instead of Unavailable Removing the company from the applicability line confirms the issue opw-6404884 Forward-Port-Of: odoo/odoo#280312
The IoT printer test now waits briefly before checking printer communication, preventing occasional false failures caused by timing delays. This improves confidence in automated testing without changing customer-facing printer behavior.
Original PR description
When a new bus channel is subscribed to, the frontend waits for a 300ms debounce before sending the subscription to the server. If we try to send a message back before then, it won't be sent to the frontend. This behaviour caused the IoT printer test tour to occasionally fail. To fix the tour, we simply add a sleep for 500ms, which should guarantee enough time has passed to avoid the issue. Unfortunately there seems to be no cleaner way to wait for the channel list to be updated. This error only affects versions 19.1 and 19.2. In 19.3 the delay when adding a new channel was removed. runbot-241937
The website builder now handles the header width setting correctly for several header designs where live preview could show an inaccurate result. This helps users avoid confusion when configuring website headers and ensures the saved setting is applied as expected.
Original PR description
The header width option is not previewed properly on the following header templates: - `template_header_boxed` - `template_header_sales_one` - `template_header_sales_two` - `template_header_sales_three` - `template_header_sales_four` - `template_header_search` This happens because these templates are not compatible with the action `previewableWebsiteConfig` (their width can't be previewed by adding a single class). This commit fixes the problem by using the action `websiteConfig` instead of `previewableWebsiteConfig` when one of these templates is set. task-6420611 Forward-Port-Of: odoo/odoo#286292 Forward-Port-Of: odoo/odoo#282311
Product pages now keep multi-checkbox options unselected unless the shopper explicitly chooses them. This prevents accidental product option selections and unexpected URL changes after refreshing the page, improving checkout accuracy for eCommerce customers.
Original PR description
**Steps to reproduce:** 1. Create a product. 2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio). 3. Publish the product and open its page on eCommerce. 4. Verify that no…
**Steps to reproduce:**
1. Create a product.
2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio).
3. Publish the product and open its page on eCommerce.
4. Verify that no multi-checkbox option is selected by default.
5. Refresh the page twice.
**Issue:**
On the second page refresh, the first option of the multi-checkbox attribute is automatically selected, and the URL is updated with its parameter.
**Cause:**
- `_prepare_product_values` construct attribute combinations by mapping requested `attribute_values` query parameters line by line.
- When URL query parameters were present (e.g., set after the first refresh), the fallback logic `or ptal.product_template_value_ids.filtered('ptav_active')[:1]` treated unselected `multi_checkbox` attribute lines as missing required selections rather than empty selections, forcing them to default to their first active option.
**Fix:**
If no selection is provided for `multi_checkbox` line, return an empty recordset instead of falling back to the first active option.
opw-6494697
Forward-Port-Of: odoo/odoo#284798This fix ensures Point of Sale orders are still synchronized when sending order changes even if printing fails because no preparation printer is configured. This helps restaurants and shops avoid missing or unsaved order updates after a printer setup issue.
Original PR description
pos*: point_of_sale, pos_restaurant Before this commit, the syncing of the order was not done when we clicked on the send button to send order changes and the printing failed (no preparation printer linked). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281676
The return creation wizard now checks for duplicate returns within the selected company only. This prevents users working across multiple companies from being incorrectly blocked by returns that belong to another company.
Original PR description
To reproduce the issue: 1) Create two companies in Belgium: A and B 2) Manually create a return for A before its opening date 3) Switch to company B, and keep A active as well 4) Try creating a return of the same type and at the same date as in 2) ===> The wizard blocks you and displays a warning saying there's already a return at this date. There is, but for another company. We fix that by properly filtering the company when searching for existing returns. Moving the _read_group inside the loop on self is okay here: we'll never compute that field for multiple wizards at once. Forward-Port-Of: odoo/enterprise#130303
Freezing a spreadsheet now records a data loss prevention log entry. This helps businesses keep a clearer audit trail when document spreadsheet content is locked or preserved.
Original PR description
Task: 6389096 Forward-Port-Of: odoo/enterprise#129607 Forward-Port-Of: odoo/enterprise#126461
The Helpdesk SLA Status Analysis report now counts a ticket's open time from creation until closure, matching the Ticket Analysis report. This gives managers accurate visibility into how long tickets remain open instead of confusing it with assignment time.
Original PR description
1. Open Helpdesk > Tickets and create a ticket on the team "Customer Care", assigned to yourself 2. More than an hour later, move it to the "Solved" stage to close it 3. Open Helpdesk > Reporting > Ticket Analysis, switch to the pivot view and pick the "Hours Open" measure -> the ticket holds the hour it stayed open 4. Open Helpdesk > Reporting > SLA Status Analysis and pick the "Hours Open" measure as well -> the ticket holds nothing, as it was assigned as soon as it was created odoo/enterprise#47454 added the "Hours Open" measure of the ticket analysis to the SLA status analysis, but computes it up to the assignment date instead of the closing date. The measure therefore holds the hours until the ticket was assigned, which the report already offers as "Working Hours to Assign". With this commit, both reports count the hours from the creation of the ticket to its closing. Forward-Port-Of: odoo/enterprise#130170
This update fixes an inconsistent automated test for Canadian payment processing by ensuring expected results are checked in a consistent order. It helps keep quality checks reliable and prevents false failures during release validation.
Original PR description
Sorts the expected items in `test_cpa005` to ensure consistent ordering. runbot error: https://runbot.odoo.com/odoo/error/941567 Forward-Port-Of: odoo/enterprise#127703
Point of Sale orders are now saved and synced when staff send order changes, even if preparation printing fails because no printer is configured. This helps avoid missing or unsynced restaurant orders and keeps operations more reliable.
Original PR description
Before this commit, the syncing of the order was not done when we clicked on the send button to send order changes and the printing failed (no preparation printer linked). Forward-Port-Of: odoo/enterprise#127506
This fixes an inconsistent employee ordering issue that could cause automated checks around employee time-off return dates to fail unpredictably. Employee records with the same name are now ordered consistently, improving reliability without changing business workflows.
Original PR description
Before this commit, TestPartner.test_res_partner_to_store fails on the all-modules and per-country builds: AssertionError: '2024-06-06' != '2024-06-07' : Return date is the return date of the main…
Before this commit, TestPartner.test_res_partner_to_store fails on the all-modules and per-country builds: AssertionError: '2024-06-06' != '2024-06-07' : Return date is the return date of the main user of the partner This happens because the test reads the first entry of the hr.employee list, which holds one employee per user of the partner: back on the 7th for the main user, on the 6th for the other. This comes from "[FIX] hr*: load out-of-office dates from all user employees", which added the employees of the partner to the payload, where it held those of the main user only. The problem is that the list keeps the order of employee_ids, which is 'name' with no tiebreaker, and both employees are named test1, as an employee takes the name of its user and creating the second user renames the partner. Postgres is then free to return either one first, and the failing builds get the second one. This commit fixes the issue by ordering the employees on 'name, id', so that employees sharing a name keep a stable order instead of the one the database picks. The test asserts the whole hr.employee list, one entry per user of the partner, rather than its first entry alone, and that assertion pins the order. https://runbot.odoo.com/odoo/error/945994 Forward-Port-Of: odoo/odoo#286236
When users reduce or remove column layouts, the editor now drops columns that contain no real content instead of leaving behind extra blank paragraphs. This keeps edited pages cleaner while still preserving meaningful content and keeping empty layouts editable.
Original PR description
#### Description of the issue this PR addresses: - When reducing the number of columns or removing a column layout, empty columns were previously unwrapped like any other column. - As a result, columns containing only placeholder paragraphs contributed empty paragraphs to the resulting content, even though they did not contain any meaningful user content. #### Desired behavior after PR is merged: - Fully empty columns are discarded when they are removed. - Non-empty columns continue to be merged as-is, preserving their content. - A single empty paragraph is still kept when all columns are empty to ensure the editor remains editable. - Rename `Remove columns` to `Remove column layout` and update its description to `Convert columns to regular content` to better reflect the operation. task-6296536 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284687 Forward-Port-Of: odoo/odoo#270220
Colombian child contacts linked to a company are now kept as contacts instead of being treated as separate companies. This restores the expected company-and-contact display name and lets users find related child contacts when searching by the parent company name.
Original PR description
Issue: Colombian child contacts linked to a NIT company are displayed with their standalone name instead of "Company, Contact". Searching Contacts by the company name consequently returns the company…
Issue: Colombian child contacts linked to a NIT company are displayed with their standalone name instead of "Company, Contact". Searching Contacts by the company name consequently returns the company but not its child contacts. Steps to reproduce: - Create a Colombian company with NIT - Add a child contact or address to that company - Filter Contacts by the company name - Observe that the child is displayed separately and is not returned Cause: The Colombian `is_company` computation classifies every partner with a Colombian NIT and qualifying obligations as a company: https://github.com/odoo/enterprise/blob/911686a31d5d3c1539d0dff7d16edf1ce9b101ca/l10n_co_edi/models/res_partner.py#L43-L53 Those fiscal values are commercial fields and are propagated to child contacts. Without checking that the partner is its own commercial entity, children are therefore classified as companies, preventing the standard display name logic from prefixing their parent name. Solution: We need to restrict the Colombian company classification to partners that are their own commercial partner. This preserves the NIT and obligation rules for actual companies while keeping their inherited child records as contacts, restoring both the combined display name and parent name search behavior. opw-6470958
Manually created quantity-based quality checks can now handle partial failures without blocking the warehouse transfer. This prevents validation errors when only some units fail inspection, helping teams continue processing pickings accurately.
Original PR description
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `quality_control` module - Create a picking order with a product - From the gear menu, create an on-demand Quality Check -…
Version:
--------
- 19.0+
Steps to reproduce:
-------------------
- Install `quality_control` module
- Create a picking order with a product
- From the gear menu, create an on-demand Quality Check
- Set the check to *Control per Quantity* and back to the picking
- Set the done quantity to 10
- Open the Quality Check wizard
- Try to fail 3 units
Issue:
------
Validating the partial failure raises a `ValidationError`:
- Missing required value for the field 'Team' (team_id)
The quality check split is not performed and the picking cannot be processed.
Cause:
--------
Quality checks created on-demand from the picking (via the gear menu) have
no associated `quality.point` or `stock.move.line` — only
`picking_id` is set at creation time.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L457
In `_move_to_failure_location()`, the `move_line` branch assumes
`check.move_line_id` is populated. Since it is empty for on-demand
checks, the split logic operates on an empty recordset.
The new quality check for the split is then created via:
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L493
At this point both `failed_move_line` (a copy of the empty move line) and
`check.point_id` are empty. `_get_check_values(False)` cannot derive
fields normally sourced from the quality point (`team_id`, `company_id`,
`measure_on`, `test_type_id`, etc.), causing the `ValidationError` on record creation.
Fix:
----
- If the quality check is not linked to a move line, find the matching move line
from the picking before splitting the failed quantity.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/stock_move_line.py#L94-L97
- `_get_check_values()` normally takes values from a Quality Point.
Since on-demand quality checks do not have one, fill the missing
values (`team_id`, `measure_on`) from the original quality check instead.
This allows manually created quantity-based quality checks to be
split correctly after a partial failure.
---
opw-6428749
Forward-Port-Of: odoo/enterprise#126505The automated Click All test was repeatedly reopening the Shop menu and never finishing, causing Website app build checks to fail. This change skips that menu during the automated test walk so validation can complete reliably without affecting normal users.
Original PR description
Before this commit, every Click All build failed on the Website app:
FAIL: Subtest TestMenusAdmin.test_01_click_everywhere_as_admin
AssertionError: Script timeout exceeded
This happens because the Shop menu is an `ir.actions.act_url` on the current tab, so clicking it loads the website preview as a new page. Clickall resumes from the state it keeps in the local storage, but restarts the menu walk of the app at its first menu, so it reaches Shop again and the same menus are tested over and over, until the 1200 seconds script timeout.
This commit adds the menu to the Clickall blacklist. Master and saas-19.4 carry that entry from "[FIX] web: blacklist shop menu from Clickall to prevent infinite reload loop".
https://runbot.odoo.com/odoo/error/944407This fix ensures order changes made on one point-of-sale device are still saved after another device synchronizes the same table. It prevents restaurant staff from losing newly added order lines when moving between the table view and floor plan.
Original PR description
Steps to reproduce: - Device A opens table 10 and adds a product - Device B opens table 10, then goes back to the floor plan - Device A goes back to the floor plan => The lines added on A are lost, they are never synced to the database, nor to the other device When B triggers a synchronisation, A reads the open orders from the server. The local lines of A are kept, but `setup`, which is also called when a record is updated, resets the dirty flag of the order. Going back to the floor plan calls `syncAllOrders`, which filters the order out because it is not dirty anymore, so the lines are never sent. The dirty flag is now kept when the record is updated with server data, since that data does not contain the changes made locally and must be synced in the next synchronization call task-id: 6486258 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284701
When a booking slot reaches its capacity, it now stays visible in the point of sale selection window instead of disappearing. Cashiers can clearly see it marked in red and still choose it when an exception is needed, helping avoid confusion and support real-world service needs.
Original PR description
Before this commit: = - When a slot reached its maximum capacity for a given time frame, it was hidden from the POS slot selection dialog. After this commit: = - The slot remains visible with a red background, allowing the cashier to force-select it. task-6340956
Adyen payment processing now reads the correct values from incoming payment data. This helps prevent payment status or transaction details from being interpreted incorrectly, improving reliability for businesses using Adyen.
Original PR description
opw-6512723 Forward-Port-Of: odoo/odoo#284773
This fix prevents the Polish bank verification module from trying to recalculate verification data for all existing payments during installation. It helps large databases install or upgrade the module without crashing, improving reliability for companies with high payment volumes.
Original PR description
account.payment model computes every record l10n_pl_verification_id at module installation (l10n_pl_bank_verification), causing crash in case of db with a large number of records wrong method name correction: _auto_init instead of init and call super after creating the db column see odoo/odoo#282504 Forward-Port-Of: odoo/odoo#285968
The website translations endpoint is no longer handled as a full website page because it already receives the requested language directly. This prevents unexpected language redirects and cookie conflicts, making translation loading more reliable for users.
Original PR description
/website/translations does not require request.website or language redirection logic as `lang` is passed explicitly. Drop `website=True` to prevent unexpected language redirects and cookie conflicts. Backport of 4faddd8b44 (odoo/odoo#269325). runbot-231758 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281738
UPS shipments could be rejected when a customer's invoicing address had no name. This fix uses a fallback name for the billing contact so affected deliveries can be confirmed successfully.
Original PR description
Issue ----- By default, invoicing addresses of existing partners are created without a name. This leads to the deliveries being rejected by UPS. Steps to reproduce ----- - Set Up UPS - Create a Customer - Create an invoicing address with no name - Create a SO for the partner & confirm - UPS delivery - Open the picking and confirm it > UPS rejects the shipment /!\ I could not reproduce in testing environment, so this is based off user steps in their production DB. /!\ Cause ----- The partner being used in `_set_invoice` was changed in #119747 but this use case was missed due to the error not occuring in test mode. ----- Ticket: opw-6485164 Forward-Port-Of: odoo/enterprise#128933
The website editor no longer shows a theme background option for tab blocks because that option did not work correctly. This keeps the available choices aligned with what users can reliably apply when designing website tabs.
Original PR description
The theme background options (`o_cc` classes) on the `s_tabs` snippet's tabs doesn't work since 18.4 (html_builder refactor). It was not supported either in previous versions. We decided to fix it so it would be useable in master (20.0) but leave stable versions as is, by restraining the available tabs and removing the theme one. task-5951656 Forward-Port-Of: odoo/odoo#277528
The Romanian tax return formerly shown with the generic label "Tax" is now named "D300". This makes it easier for users to identify the correct declaration when selecting or generating Romanian tax returns.
Original PR description
Before this commit: When generating a Romanian tax return, one of the return types in the list was labeled "Tax", which was too generic to know which specific tax declaration it referred to. After this commit: The tax return is now renamed to "D300", making it easy to identify this return in the list instead of seeing a generic "Tax" label. task - 6388087 Forward-Port-Of: odoo/enterprise#124583
The website editor search field now shows a pointer cursor when users hover over the clear icon in browsers that display it. This small usability fix makes it clearer that users can quickly clear their snippet search.
Original PR description
Steps to reproduce: - Open the website editor. - Open the "Insert a block" dialog. - Enter text in the search bar. - Hover over the clear icon. => The cursor does not indicate that the icon is clickable. Before this commit, the search clear icon kept the default cursor. After this commit, the clear icon uses a pointer cursor to indicate that it is clickable. Note that Firefox does not natively add this clear icon to search inputs, unlike Chrome. This fix only affects browsers that render it. task-6259086 Forward-Port-Of: odoo/odoo#283435
This fix makes an automated rental pricing test use a fixed date so it no longer fails during certain late-night UTC hours. It helps keep quality checks reliable without changing how customers use the website rental flow.
Original PR description
Scenario:
- be (or switch your computer) at time between 21:01 and 23:59 UTC
- run test test_product_attribute_value_config_get_combination_info
Result:
This error is happening:
Traceback (most recent call last):
File "…/tests/test_website_sale_product_attribute_value_config.py",
line 106, in test_product_attribute_value_config_get_combination_info
self.assertEqual(combination_info['price'], price_3_hours)
AssertionError: 6.42 != 15.0
Cause: since the time range is on multiple day, we favor a weekly price
that is more interesting and the result is not the 3 hours price.
Fix: set the date for the test.
runbot-227695
Forward-Port-Of: odoo/enterprise#130062This fixes an issue where pages using Odoo live chat could block browser keyboard shortcuts like Alt+D even when no shortcut hints were available. Browser shortcuts now remain available unless Odoo actually has shortcut overlays to show, preserving the existing behavior where overlays are present.
Original PR description
Description of the issue/feature this PR addresses: When `im_livechat` (or any page) boots the OWL web stack with no `[data-hotkey]` / `withOverlay` targets, pressing Alt still called…
Description of the issue/feature this PR addresses: When `im_livechat` (or any page) boots the OWL web stack with no `[data-hotkey]` / `withOverlay` targets, pressing Alt still called `preventDefault()` in `hotkey_service`. That blocked browser shortcuts such as Alt+D (focus address bar) on websites that embed the livechat scripts. See https://github.com/odoo/odoo/issues/267928 Current behavior before PR: - Pressing the overlay modifier (Alt, or Ctrl on macOS mapped to `"alt"`) always set `overlaysVisible = true` and called `preventDefault()`, even when there were no hotkeys to overlay. - A follow-up key (e.g. D while Alt is held) then also hit `preventDefault()` because overlays were considered visible. - Loading `/im_livechat/loader/...` + `assets_embed.js` on an external site therefore broke browser Alt shortcuts. Desired behavior after PR is merged: - `addHotkeyOverlays` returns whether overlays were actually displayed. - `preventDefault` on the overlay modifier runs only when there is at least one overlay target. - Pages with no hotkeys (typical livechat embed) leave browser shortcuts alone. - When hotkeys exist, Alt still shows overlays and cancels the default, same as before. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284145
This fixes an issue where online payment lines in restaurant point of sale could be treated as adjustable for tips or payment changes. Online payments are now correctly locked from these adjustments, helping prevent incorrect payment handling at checkout.
Original PR description
In commit ea56e09c1adb, the `canBeAdjusted` override on `PosPayment` was accidentally replaced with `cancelPayment`. However, `canBeAdjusted` is required when `pos_restaurant` is installed to prevent online payment lines from being treated as adjustable (for tips/adjustments). This commit restores `canBeAdjusted` returning `false` for online payments and removes the unused `cancelPayment` method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286259
When a timesheet date is changed from a linked task, the Timesheet Assistant now updates immediately instead of showing the old date until refresh. This helps users trust that the assistant reflects their latest saved changes and avoids confusion during time entry.
Original PR description
Steps to Reproduce: - Install timesheet_grid and activate Timesheet Assistant - Open a timesheet and click the task external link - Change the timesheet date from the task form and save Issue: When the timesheet date is changed from the task, the assistant still shows the old date until the page is refreshed Fix: Reload assistant timesheets after the linked task is saved and refresh or clear the selected timesheet based on the new date task-6454988
This fix makes the restaurant point-of-sale order tracking check wait until payment validation is fully completed and synchronized. It prevents false test failures where the system checked order details too early, improving confidence in automated quality checks without changing user-facing behavior.
Original PR description
The order tracking tour only waited for the feedback screen to be shown after validating the payment. Since order validation is performed asynchronously while the feedback screen is displayed, the tour could finish before the updated order was synced to the backend. This caused the Python test to still see the original quantity and `is_edited` set to false. To fix we wait for the feedback screen continue button to be enabled, which ensures order validation and synchronization have completed before the tour ends. [error-940386](https://runbot.odoo.com/odoo/error/940386) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Kit products now correctly respect the selected accrual date when calculating delivered quantities for invoicing. This prevents sales orders from appearing as invoiceable when the related delivery happened after the chosen accounting date.
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#274745
This fixes a timing issue in Mail where mention suggestions could reopen after being dismissed, preventing the Escape key from discarding a reply in some cases. The change makes the behavior more stable and avoids intermittent failures in automated testing, reducing the risk of unreliable reply handling.
Original PR description
Two independent causes made "reply: discard on pressing escape" red, one commit each. "[FIX] mail: wait for the mention suggestions before Escape" is the one that fixes the reported failure, and it holds on every branch: the test presses Escape while the mention fetch is in flight, and the suggestions arriving from the server re-open the list that Escape closed, so the re-opened list takes the second Escape and the reply is never discarded. The test now waits for the fetched suggestions before pressing Escape. "[FIX] mail: keep the suggestion list closed on a re-render" backports "[FIX] mail: keep composer suggestion list closed on unrelated re-render", which entered at 19.0 and never came down. Here NavigableList is re-opened on every patch, so opening the emoji picker after Escape brings the dismissed list back, and it then steals the Escape meant for the picker. https://runbot.odoo.com/odoo/error/946314 Forward-Port-Of: odoo/odoo#286041 Forward-Port-Of: odoo/odoo#284725
The Helpdesk team card layout has been adjusted so the email alias lines up properly with the team name. This creates a cleaner, more consistent display for users managing helpdesk teams without changing any business process.
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
The unread tickets filter now correctly treats tickets as needing attention when the latest update is an automatic system message, such as one from OdooBot. This helps support teams avoid missing customer-submitted tickets that were previously hidden from the unread view.
Original PR description
**Steps to reproduce:** - Install website_helpdesk. - Create a team and enable website form. - Create a ticket through the website. - Apply the Unread filter. **Issue:** system generated message, such as message authored by OdooBot, were not considered when determining whether a ticket was unanswered. **Cause:** the search method only considered the last message when its author matched the ticket's partner. **Fix:** Consider a ticket unanswered when the last message's author matches the ticket's partner, or when the last message is an automatic system generated message. task-5138678
This fixes an issue where selected website themes were not fully applied during website setup, leaving elements like headers and footers unchanged. The update ensures theme-specific changes are applied at installation time and the correct website is identified reliably during setup.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286085 Forward-Port-Of: odoo/odoo#283174
Fixes an issue where manually increasing the quantity on a timesheet invoice could prevent later timesheet entries from being invoiced. Businesses can now bill future work periods correctly while keeping refund-related behavior intact.
Original PR description
## Issue When a use rmanually increases the invoiced quantity on a timesheet invoice, subsequent timesheets logged in future periods can no longer be invoiced. The system assumes that the most recent…
## Issue
When a use rmanually increases the invoiced quantity on a timesheet invoice, subsequent timesheets logged in future periods can no longer be invoiced. The system assumes that the most recent logged hours are already covered by the previously over-invoiced amount, blocking the billing of the most recent timesheet entries.
## Steps to reproduce
1. Install *Sales Timesheet* (`sale_timesheet`)
2. Create a Product P
- Product Type: Service
- Invoicing Policy: Based on Timesheets
- Create on Order: (Project &) Task
3. Create an SO:
- Customer: Any
- Product: P (any quantity)
- Confirm
4. Record hours on the task created:
- 06/01/2026 (June 1st): 1 hour
- 07/01/2026 (July 1st): 1 hour
5. Create the invoice for the June timesheet entry (by setting a timesheets period when creating the invoice), then **change the quantity to any value strictly greater than 2** and confirm.
6. Create the invoice for July
7. **An "Invalid Operation" error appears, stating that there's nothing to invoice, even though the timesheet entry from July was never invoiced.**
## Cause
Since https://github.com/odoo/odoo/commit/3b86ac3d180993239b63fd305ee0ba1f17f7eb20, the computation of the quantity to invoice changed to include the difference between the quantity delivered and the quantity already invoiced. In the flow described by the steps to reproduce above, the quantity to invoice is larger than the quantity delivered, making the `qty_to_invoice` equal to `0.0`.
https://github.com/odoo/odoo/blob/626d31fa0191bfe7ca8e1fcf177357eeeb60f2c7/addons/sale_timesheet/models/sale_order.py#L331-L334
The reason for the fix above being the partial refunding of timesheet-related invoices, we can keep that solution when working with refunded invoices, and keep the previous behavior for other cases.
This solution solves the issue in the steps to reproduce above, but was also manually tested on the issues from https://github.com/odoo/odoo/commit/3b86ac3d180993239b63fd305ee0ba1f17f7eb20 and https://github.com/odoo/odoo/commit/64cf4afabd0c5ef040cf87fc6f3125fe0bb81bbb.
opw-6485674
Forward-Port-Of: odoo/odoo#286116
Forward-Port-Of: odoo/odoo#284470Users adding a certificate key file without a password will no longer see an immediate misleading error banner. The warning now appears only when a password was entered and is actually incorrect, making the certificate setup experience clearer.
Original PR description
When adding a key file without entering a password, an error banner is immediately displayed, incorrectly suggesting that the password may be invalid. Only show the error banner when a password was provided and is incorrect. Also refactored the compute function to avoid repeated try-except blocks. task-6299175 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285744 Forward-Port-Of: odoo/odoo#283589