Wednesday, August 26, 2026
37 changes · master
Enhancements to existing features
Odoo now starts real-time notification subscriptions from a confirmed point instead of relying on a short replay window. This reduces the risk of missed updates after connection issues and avoids unnecessary message bursts after long inactivity.
Original PR description
*: im_livechat, mail, point_of_sale, pos_self_order, web, website_livechat. When the client subscribes to new channels, it passes its last known notification id as the starting point of the stream.…
*: im_livechat, mail, point_of_sale, pos_self_order, web, website_livechat. When the client subscribes to new channels, it passes its last known notification id as the starting point of the stream. For the very first connection, the last id defaults to 0. In this case, the server replays notifications from the last 50 seconds. This heuristic can lead to missed notifications (e.g. if the WebSocket fails to connect and retries exceed the window), or to a large useless dispatch when reconnecting after a long period of inactivity. This commit fixes both issues by having the client always start from an explicit, known-good id instead of 0. A topic fetches notifications starting from the lowest last id among its subscribers. If a single subscriber joins with 0 as its last_id, that 0 becomes the lower bound for the whole topic, and the 50s heuristic then applies to everyone sharing it, possibly excluding notifications the topic still needed. Providing a real id also fixes this issue. follow-up of task-5449503 enterprise: https://github.com/odoo/enterprise/pull/128917
This update makes Turkish e-Dispatch workflows easier by adding a single fetch action for XMLs and PDFs, improving upload placement, and naming files so they are easier to match. It also fixes commercial invoice status and banner behavior so users can correctly see whether a recipient response is pending, approved, auto-approved, or rejected.
Original PR description
## Description of the issue/feature this PR addresses: Fetch-button and matching UX improvements for e-Dispatch (receipts & deliveries), plus a fix to commercial (TICARIFATURA) invoice status…
## Description of the issue/feature this PR addresses: Fetch-button and matching UX improvements for e-Dispatch (receipts & deliveries), plus a fix to commercial (TICARIFATURA) invoice status handling and its response banner on account.move. ## Current behavior before PR: - "Upload e-Dispatch (XML)" is only available as a list-view toolbar button. - There is no single action to fetch e-Dispatch XMLs and then their PDFs. - "Update From GİB e-Dispatch (XML)" shows even when no XML is linked to the receipt. - Updating a receipt from its XML does not (re)fetch the matching Nilvera PDF. - Outgoing deliveries do not fetch the Nilvera PDF on status synchronization. - Fetched XML attachments are hard to match (no customer name in the name). - Commercial (TICARIFATURA) invoices that succeed without a recipient answer never reach the "succeed" status, and the commercial response banner (awaiting / approved / rejected) does not display correctly. ## Desired behavior after PR is merged: - "Upload e-Dispatch (XML)" is moved to the Actions menu on the list view. - A new "Fetch e-Dispatches" action fetches the XMLs and then the PDFs, in order (receipts and deliveries). - "Update From GİB e-Dispatch (XML)" is hidden until an e-Dispatch XML is linked. - Updating a receipt from its XML (re)fetches the matching Nilvera PDF. - Outgoing deliveries fetch the Nilvera PDF (via the Sale channel) on a successful status sync. - Fetched XML attachments carry the customer name for easier matching. - Commercial invoices persist "succeed" while awaiting the recipient's answer, and the awaiting / approved / auto-approved / rejected banners display correctly. task-6044179 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
HR will now automatically create company closure days for the next 12 months on a monthly schedule. The wording is also updated from public holidays to closure days, making it clearer that these days can cover any company-wide closure, not only official holidays.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Partner autocomplete now searches across additional company identifier fields, not just name or VAT. This makes it easier for users to find the right company using identifiers such as DUNS, improving data entry speed and accuracy.
Original PR description
We want to add the autocompletion feature on the multi-ids fields. Before, we could search by VAT number or by name. Now, we can search by name, VAT, or any field in the multi-ids (including DUNS) Related on IAP : https://github.com/odoo/iap-apps/pull/1755 Task-5367705
The icon picker in the website editor now searches Material Symbols on the server instead of sending the full searchable icon list to every browser. This reduces unnecessary page-load weight and makes icon searches feel more responsive, while also making icon font generation more consistent for future updates.
Original PR description
Enterprise PR: odoo/enterprise#127664 [REF] web: rename the webIcon "iconClass" key to "icon" --- __Before this commit__ - The `webIcon` object built from `ir.ui.menu.web_icon` exposed its first part…
Enterprise PR: odoo/enterprise#127664
[REF] web: rename the webIcon "iconClass" key to "icon"
---
__Before this commit__
- The `webIcon` object built from `ir.ui.menu.web_icon` exposed its first
part as `iconClass`, a leftover from the FontAwesome era.
- Since the Material Symbols migration that part is a `data-icon` name,
not a class: every reader passes it to `t-att-data-icon`.
__After this commit__
- The key (and the local variables around it) is named `icon`.
[IMP] html_editor: shorten icon search debounce
---
__Before this commit__
- `SearchMedia` hardcoded a 1000ms debounce, so the icon picker waited a
full second after each keystroke before searching.
__After this commit__
- `SearchMedia` accepts an optional `delay` prop (still 1000ms by
default, leaving the file/image selectors untouched).
- `IconSelector` passes `delay="250"` for a snappier pictogram search.
[IMP] html_editor, web: move ms icons list in backend
---
__Before this commit__
The Material Symbols list used by the media dialog's icon picker was a
generated JS module of ~152 KB for 446 icons, shipped in the assets
bundle to every browser on every page load. Most of that weight is the
`tags` search terms, only ever used to filter the list when the user
types in the picker.
__After this commit__
`generate_icons.py` writes a Python `MS_ICONS` dict in
`html_editor/controllers/ms_icons.py` instead of a JS module, and the new
`/html_editor/material_symbols_search` route searches it server-side
against a `name tags` index built once at import. It returns only
`{name, has_fill}`, so the tags never reach the browser.
The picker fetches the full list on start, then one filtered list per
search. Odoo UI icons (`oi_*`) are still read from the CSS rules and
searched client-side, since they are cheap to discover there.
`MediaDialog` rebuilds the pre-selected icon from the element's
`data-icon` attribute instead of looking it up in the full list.
[FIX] web, mail: make the icon font generation reproducible
---
__Problem__
Two runs of `addons/web/tooling/icons/generate_icons.py` on an unchanged
`icons_wishlist.txt` produce different font files, so a diff on those
binaries tells nothing about whether the icons actually changed.
__Reason__
- `detect_filled_variants` returns a `set`, whose iteration order varies
from one process to the next (string hash randomization). That order
is what gets handed to `fontext` as its ligature list, and `fontext`
numbers the glyphs it keeps in the order it is given them, so the
filled half of `glyf` is reshuffled on every run -- 242 of the 717
glyphs.
- `fontext` stamps `head.created` / `head.modified` with the current
time, and the `TTFont` reading its output recomputed `modified` once
more on save.
__Quick fix__
Sort the suffixed icon names before subsetting, and date the fonts only
when their content actually changed: `save_font` compares the newly built
font with the one already on disk, both with their `head` dates equalized,
and rewrites the same bytes when they match. `created` is kept for the
lifetime of the file, `modified` only follows a real change.
Rebuilding on an unchanged wishlist now leaves every generated font
untouched, so any diff on them means the icons really moved. The WOFF1
fallbacks and the `_pua_cmap` font are regenerated here, as they still
carried the old glyph order.Customer credit and debit notes in India can now be marked as either standard adjustments or price-only adjustments. This helps GST filings, e-invoicing, printed documents, and sales quantities correctly distinguish goods movement from value-only corrections.
Original PR description
Customer credit/debit notes are often issued to adjust prices without any movement of goods, for example, for a discount, rebate, or price revision without any change in quantity. This PR introduces…
Customer credit/debit notes are often issued to adjust prices without any movement of goods, for example, for a discount, rebate, or price revision without any change in quantity. This PR introduces an Adjustment Type field on customer credit/debit notes with two options: - **Standard:** Used when the adjustment involves a change in quantity, such as goods returned, cancelled service contracts, or additional goods supplied. - **Price Adjustment:** Used when the adjustment only changes the amount, with no change in quantity, such as a discount, rebate, or price revision. This distinction allows GST filing, EDI, and sales documents to correctly reflect whether an adjustment involves movement of goods or is purely a value correction. Changes included: - Add an Adjustment Type field on credit/debit notes. - Add the Adjustment Type field to the invoice report so users can clearly identify the type of credit/debit note. - Add Adjustment Type field on account move reversal wizard - For Price Adjustment moves, the EDI reports quantity and unit price as zero on each line while preserving the actual taxable value and tax amounts. - Exclude Price Adjustment moves from invoiced quantity computation in sales documents. task-6370202 Related enterprise Pr - https://github.com/odoo/enterprise/pull/126929 Related Upgrade Pr - https://github.com/odoo/upgrade/pull/11013
This change prevents deletion of records that are still linked to Indian e-Waybill documents, helping businesses avoid accidental loss of compliance-related information. It improves data integrity across invoicing and stock operations where e-Waybills are involved.
Original PR description
task-6445766 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now use a middle-click on the expand button in form dialogs to open the record in a new browser tab. This makes it easier to keep the current workflow open while reviewing or editing related information separately.
Original PR description
This commit adds the ability to detect a middle click on the Expand button to the Dialog API. This is achieved through the `t-custom-click` directive. The expand callback function that is given to the Dialog API, will now receive two parameters: the event and whether it's a middle click. This commit also uses the new API to allow the FormViewDialog and x2ManyFieldDialog form dialogs to expand to a new tab. task-id: 5429014
Website links that open in a new browser tab now include hidden text or updated labels so screen readers can announce this behavior. This helps non-visual users understand what will happen before activating a link, improving accessibility and reducing confusion.
Original PR description
Screen readers generally do not automatically announce that a link opens in a new tab when a user navigates to it, creating a potential barrier for non-visual users who may become disoriented if the current page is replaced without warning. Solution: Add a visually hidden span inside a tags with target=_blank Task-6009931
Point of Sale no longer creates separate rescue sessions when orders arrive after a sales session has closed. Orders are now redirected to an available open session when possible, or staff are notified to reload and resync, reducing duplicate session handling and simplifying operations.
Original PR description
Rescue sessions are not created anymore. Before, they were use to store orders that were sync with sessions after these sessions were closed. Now if we try to sync an order with a closed session, it will either be synced with the current open session (if any) or raise an error if no valid session is available. After that, the frontend will receive a notification from the backend telling that the session is closed and will reload the page and then resync the orders with the new session. Rescue session is thus not needed anymore. task-id: 6332359 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Timesheet Assistant suggestions for Helpdesk tickets now show the actual ticket name and carry it into the timesheet form when added. This makes time entry faster and reduces mistakes caused by unclear labels or lost ticket details, while also avoiding incorrect grouping of unrelated events.
Original PR description
Before this commit, the Timesheet Assistant displayed static labels for Helpdesk Tickets. Furthermore, when a user clicked "Add" on a ticket suggestion, the Timesheet Inline Form did not auto-populate the ticket name, as the source ID was lost during the grouping phase. Task: 6320652 Forward-Port-Of: odoo/enterprise#121662
Quality reporting now helps teams compare how well vendors, products, and control points perform based on yearly pass rates. Buyers can see supplier quality information directly on vendor records, purchase requests, and quality control views, making sourcing and follow-up decisions easier.
Original PR description
Quality reporting did not provide a direct way to evaluate successful checks by vendor, product, or control point. This commit's changes: - Compute Quality Rate as the average pass percentage, with every quality check contributing the same weight regardless of control type. - Add partner and effective-date filters to Quality Check Analysis. - Show the yearly Quality Rate on partner forms and group its report by product. - Add an auto-installed Purchase/Quality bridge that shows the vendor's yearly Quality Rate on RFQs. - Add a Suppliers smart button on control points that opens yearly Quality Rate results grouped by partner. - Count distinct partners from incoming receipts as control point suppliers. task-6392885
Mexican payroll users now get a warning when paid payslips in a pay run are still waiting for their required Payroll CFDI. This helps employers issue documents within the legal deadline based on company size and avoid compliance risk.
Original PR description
RMF Rule 2.7.5 gives Mexican employers a limited number of business days after the payment date to issue Payroll CFDIs, depending on the company's headcount: 3 days up to 50 employees, 5 up to 100, 7 up to 300, 9 up to 500, 11 above. This adds a payroll warning on Mexican payslips in a pay run that are still waiting for their CFDI. One change in hr_payroll: issues were only computed for draft and validated payslips (plus paid ones with wrong data), but a CFDI deadline only starts running once the payslip is paid, so the warning vanished exactly when it mattered. _compute_issues now takes its payslips from a new _get_payslips_to_compute_issues() that localizations can extend. Default behaviour is unchanged, and the Mexican override adds a deliberately narrow set. task-6433985
Studio now uses the shared icon picker already used elsewhere in Odoo, making icon selection more consistent and easier to maintain. Users creating app icons or button boxes can also choose filled icon styles, while internal naming was simplified to better match the current icon system.
Original PR description
Community PR: odoo/odoo#278149 [IMP] web_studio: use the html_editor icon selector --- __Before this commit__ - Studio had its own icon picker (`StudioIconSelector`), a `SelectMenu` built on top of…
Community PR: odoo/odoo#278149 [IMP] web_studio: use the html_editor icon selector --- __Before this commit__ - Studio had its own icon picker (`StudioIconSelector`), a `SelectMenu` built on top of `IconSelector.initFonts()`. That helper is gone: the Material Symbols list now lives in the backend and the html_editor `IconSelector` fetches it on demand, so the whole list is no longer available client-side to feed a `SelectMenu`. __After this commit__ - The Studio component is dropped and the html_editor `IconSelector` is reused directly, wrapped in a `Dropdown` in both places that picked an icon: the app icon creator and the "add a button box" dialog. - The selection to highlight in the grid is rebuilt from the icon name alone, the same way `MediaDialog` does it since the list is fetched lazily. - The picker also offers the filled variant of the icons. It is stored by suffixing the icon name with "_f", which is the ligature of the filled glyph in the font: no renderer has to know about it. [REF] web_enterprise, web_studio: rename "iconClass" to "icon" --- __Before this commit__ - The app icon name was carried around as `iconClass`, from the `webIcon` object down to the `IconCreator` prop, a leftover from the FontAwesome era. - Since the Material Symbols migration that value is a `data-icon` name, not a class: every reader passes it to `t-att-data-icon`. __After this commit__ - The key and the prop are named `icon`.
Managers can now clearly see employees without active contracts in the Attendance Gantt view, where they are highlighted in red with a greyed-out row. The attendance form also shows a warning and links to the employee profile, helping teams resolve missing contract issues faster.
Original PR description
Previously, employees without contracts is not explicit from the attendance gantt view. This made it hard for managers to notice that someone was missing a contract and needed attention. Now these employees are visible with clearly flagged with a red name and fully grayed-out row according to conditions as user have self edit and attendance approver rights. On attendance form displays a warning that employee is not in contract and redirect to Employee Profile. task-6259306
Price adjustment credit and debit notes will no longer change quantity totals in Indian GST HSN reporting or subscription invoicing. This keeps reported quantities aligned with actual goods or services delivered, while financial amounts and taxes continue to be reported correctly.
Original PR description
Price adjustment credit/debit notes are created to adjust total amounts only, they do not alter quantities, since no goods are returned or additional goods supplied. This PR ensures such moves are consistently excluded from quantity-based computations across GST reporting and subscriptions. Changes included: - Exclude price adjustment moves from the HSN quantity in the GSTR-1 HSN summary, both in the generated spreadsheet (HSN sheet) and the JSON sent to the government portal. Taxable value and tax amounts remain unchanged. - Exclude price adjustment moves from sale subscriptions invoiced quantities task-6370202 Related community Pr - https://github.com/odoo/odoo/pull/279532 Related Upgrade Pr - https://github.com/odoo/upgrade/pull/11013
Bulk account assignment in bank reconciliation now completes much faster when many statement lines are selected. This reduces waiting time for accounting teams and makes high-volume reconciliation work more efficient.
Original PR description
Description =========== The bank reconciliation widget sends the bulk "Set Account" action as a single RPC, but the server still processes most of the work separately for every selected statement…
Description
===========
The bank reconciliation widget sends the bulk "Set Account" action as a single RPC, but the server still processes most of the work separately for every selected statement line.
Each iteration searches for recent statement lines and reconciliation models, writes the account on one move line, and posts its matching confirmation independently. The cost therefore grows linearly with the selection size.
Cache reconciliation-rule lookups for the duration of the bulk operation, while updating the cache when rules are created or deleted.
Also assign the account to all selected move lines in one recordset write, avoiding frequent calls to `_compute_reconciled_payment_ids` 1 by 1.
Finally, collect the lines requiring a matching confirmation and create their chatter entries in one batch.
Benchmark
=========
The benchmark measures one server-side bulk Set Account call; fixture creation is excluded from the timings.
| Selected lines | Before | After | Improvement |
|----------------|--------|-------|------------------|
| 500 | 12.5 s | 2.5 s | 5x faster (-80%) |
Benchmark data cardinality:
- 1 company
- 1 isolated bank journal
- 3 accounts: liquidity, suspense, and target expense
- 500 unreconciled bank statement lines
- 500 suspense move lines passed to the method, one per statement line
- 1 target account shared by all selected lines
- 1 journal/company/account cache group
- 1 batched call, executed sequentially in one cursor
- Negative amounts, avoiding automatic bank-fee rule creation
- 500 distinct references shorter than 10 characters, preventing a new reconciliation model from being created
- No taxes on the target account
Blueprint
=========
```xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--
==========================================================
BENCHMARK: Bulk Set Account on Bank Statement Lines
==========================================================
Creates 500 unreconciled statement lines in one isolated bank
journal, then calls set_account_bank_statement_line() once on the
whole recordset, as the bank reconciliation widget's bulk action does.
Negative amounts bypass the unrelated bank-fee rule path. Distinct
labels shorter than 10 characters prevent an automatic reconciliation
model from being created during the run. Without the bulk cache, the
first line only runs the history search and every subsequent line runs
both searches in _check_and_create_reconciliation_rule(). This keeps
the query-count regression visible without changing the scenario.
-->
<record id="benchmark_bulk_set_account_bank_statement_line" model="populate.blueprint">
<field name="name">Benchmark: Bulk Set Account on Bank Statement Lines</field>
<field name="definition_xml" type="xml">
<create model="account.account" count="1" id="bench_bulk_set_account_liquidity" scale="False" parallel="False">
<value name="counter" generator="misc.counter" start="1"/>
<field name="name" eval="f'Benchmark Bulk Set Account Liquidity {counter}'"/>
<field name="code" eval="f'BSAL{counter:03}'" unique="True"/>
<field name="account_type" eval="'asset_cash'"/>
</create>
<create model="account.account" count="1" id="bench_bulk_set_account_suspense" scale="False" parallel="False">
<value name="counter" generator="misc.counter" start="1"/>
<field name="name" eval="f'Benchmark Bulk Set Account Suspense {counter}'"/>
<field name="code" eval="f'BSAS{counter:03}'" unique="True"/>
<field name="account_type" eval="'asset_current'"/>
</create>
<create model="account.account" count="1" id="bench_bulk_set_account_target" scale="False" parallel="False">
<value name="counter" generator="misc.counter" start="1"/>
<field name="name" eval="f'Benchmark Bulk Set Account Target {counter}'"/>
<field name="code" eval="f'BSAT{counter:03}'" unique="True"/>
<field name="account_type" eval="'expense'"/>
</create>
<create model="account.journal" count="1" id="bench_bulk_set_account_journal" scale="False" parallel="False">
<value name="counter" generator="misc.counter" start="1"/>
<field name="name" eval="f'Benchmark Bulk Set Account Journal {counter}'"/>
<field name="code" eval="f'BSA{counter:03}'" unique="True"/>
<field name="type" eval="'bank'"/>
<field name="default_account_id" ref="bench_bulk_set_account_liquidity"/>
<field name="suspense_account_id" ref="bench_bulk_set_account_suspense"/>
</create>
<create model="account.bank.statement.line" count="500" id="bench_bulk_set_account_statement_lines" scale="False" parallel="False">
<value name="counter" generator="misc.counter" start="1"/>
<field name="journal_id" ref="bench_bulk_set_account_journal"/>
<field name="date" eval="'2026-08-18'"/>
<field name="payment_ref" eval="f'{counter:08x}'"/>
<field name="amount" eval="-100.0"/>
</create>
<function model="account.bank.statement.line"
name="set_account_bank_statement_line"
ref="bench_bulk_set_account_statement_lines"
batched="True"
parallel="False"
context="{'account_default_taxes': True}">
<value name="journal_id"
generator="relation.one"
comodel_name="account.journal"
ref="bench_bulk_set_account_journal"/>
<value name="suspense_account_id"
generator="relation.one"
comodel_name="account.account"
ref="bench_bulk_set_account_suspense"/>
<arg eval="[
line.line_ids.filtered_domain([
('account_id', '=', suspense_account_id),
]).id
for line in model.search([
('journal_id', '=', journal_id),
], order='id')
]"/>
<arg generator="relation.one"
comodel_name="account.account"
ref="bench_bulk_set_account_target"/>
</function>
</field>
</record>
</odoo>
```
Reference
=========
task-6480127The Pakistan localization now treats 18% GST for 3rd Schedule sale and purchase taxes as already included in the printed retail price. This prevents GST from being added on top of the listed price and aligns tax calculations with local rules.
Original PR description
Description of the issue/feature this PR addresses: 3rd Schedule goods in Pakistan are taxed on the printed retail price, which already includes GST. The sale and purchase "GST 18% 3rd" taxes in the Pakistani chart of accounts were configured as tax-excluded. Current behavior before PR: The 18% is added on top of the product's sales price. Desired behavior after PR is merged: The 18% is extracted from the retail price. task-6466479 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale now asks the browser to protect offline sales data from automatic cleanup when a device runs low on storage. This reduces the risk of losing unsynced orders on PoS terminals, while keeping startup unaffected because the request runs in the background.
Original PR description
All PoS offline data, including orders not yet synced to the server, lives in indexedDB. By default this storage is "best-effort": when the device runs low on disk space, the browser is allowed to silently evict an entire origin's data. On a PoS terminal holding unsynced orders, such an eviction means losing those orders for good. This PR requests persistent storage with `navigator.storage.persist()` when the data service initializes indexedDB. When granted, the origin's storage is exempted from automatic eviction; data can then only be removed by an explicit user action. The request is best-effort: Chrome grants or denies it silently based on engagement heuristics (it is always granted for an installed PWA), Firefox prompts the user once. The call is therefore not awaited in the startup path and its outcome is only logged. See https://developer.mozilla.org/en-US/docs/Web/API/StorageManager/persist
The web interface’s underlying OWL framework was updated to a newer release. This helps keep Odoo’s user interface technology current and can bring stability, compatibility, and maintainability improvements without introducing a specific new business feature.
Original PR description
Release notes: https://github.com/odoo/owl/releases/tag/v3.0.0-alpha.47 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#284147
The website SEO dialog now detects when translated page content is out of date and prevents users from accidentally confirming translations they have not reviewed. This helps protect translation quality by asking users to review delayed translations in translation mode before editing related SEO image text.
Original PR description
1. Saving the SEO dialog no longer confirms delayed translations. They stay
delayed until the user saves from translation mode, where they can see what
they confirm. (Reverts the logic of 03fa781.)
2. The dialog now loads the page rendered with `edit_translations`, which is the
only render that marks delayed translations, and looks for one in `#wrap`
(the part the dialog reads its images from). When it finds one, it:
- covers the content checks with a message explaining the content is out of
date,
- keeps the alt inputs disabled
task-[6465390](https://www.odoo.com/odoo/project/974/tasks/6465390)Online shoppers can now choose multiple values within the same product filter, such as Lenovo or HP together with a specific storage size, instead of being forced into overly narrow results. The shop filter panel also behaves more consistently, keeping options visible and improving the placement of clear filters for a smoother browsing experience.
Original PR description
Filters are now completely exclusive, which prevent 0 results but also prevents more "open" searches as "Lenovo" OR "HP" AND "512GB SSD". Allow selecting attribute values that are not exclusive if its from the same attribute. Further improvements: 1. move clear filters to below attribute values 2. avoid closing the offcanvas if no products visible 3. avoid putting the selected attributes on top in the offcanvas 4. avoid hiding filters when no products available 5. avoid small displacement in the sidebar filters when selecting a value task-6341310 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Mail activities and messages now load search results in smaller chunks when a result limit is used. This helps affected views open reliably while still respecting access rules, reducing cases where pages stall because too many records are processed at once.
Original PR description
When a limit is applied in the search method, fetch the data in small batches like we do in ir.attachment. This allows to search with a limit on views while applying security access. Without this, simple views cannot be opened because the ORM searches for all records before filtering them in memory. Note that this cannot be avoided for group by queries and that if we don't set a limit, we will eventually still fetch everything in smaller batches. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284235 Forward-Port-Of: odoo/odoo#265203
Belgian payroll can now carry unused employment bonus amounts into the following month when vacation lowers an employee's pay. This helps ensure payroll calculations and related social security reporting reflect the full bonus entitlement more accurately.
Original PR description
Allow unclaimed employment bonuses to be carried over to the next month when vacation reduces remuneration during the month. - Add bonus carry-over salary rules - Update bonus calculations to include previous month amounts - Modify ONSS restructuring to account for carry-over Task Id: 6147223
The web interface now keeps the default grouping option visible in search filters again. This helps users see and manage preconfigured grouped views consistently, avoiding confusion from a recent change that removed that option.
Original PR description
This reverts commit 7413e08c166ef3123ac7ed6623db1fb366f44e3c (#265574) task-6425644 Forward-Port-Of: odoo/odoo#279043
Salary benefit list and form screens have been visually improved to make benefit setup easier to review and manage. The form now also checks numeric benefit values more clearly, helping users enter valid information and reducing setup mistakes.
Original PR description
Visual improvements for list and form views of salary benefits. Add benefit value check for float type in the form view. task-6253384
The messaging menu can now be customized so AI-related views can show their own tabs, such as Automation, and hide unnecessary counters when focused on a single agent. The update also improves Discuss reliability by ordering empty conversations consistently, preventing loading flicker, and keeping restored URLs in sync.
Original PR description
ai_app adds its own "Automation" tab to the messaging menu, shows only AI and Automation tabs when the menu is scoped to a single agent, and hides counters in that scoped view. None of that was possible: the tab list and counters were read straight from the store in the template. Move both behind component getters so they can be overridden. Also fixed: - sort threads with no message by channel creation date instead of leaving them in arbitrary order. - show the empty thread placeholder only once the thread is mounted and loaded, so it no longer flashes while messages load. - sync the discuss `active_id` into the action service state, otherwise `action.restore()` rebuilds the URL from a stale value. - Agent cards and the New button open the agent chat in Discuss, not a form, so adding them to the clickbot exceptions. task-6334162
Self-order and kiosk customers can now add a tip during checkout when online payment is enabled. This helps staff capture gratuities that were previously missed, with tips shown as a separate line on the order and receipt.
Original PR description
Purpose ------- Staff were losing potential tips because customers placing orders through the self-order or kiosk flows. Specification ------------- - Add a tip step to the self-order/kiosk checkout flow, available whenever online payment is enabled. - Customers can pick a quick tip percentage (15%, 20%, 25%) or enter a custom amount/percentage via a numpad popup. - The tip is added as a dedicated line and appears on the receipt. Task-6254832 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Report action screens have been reorganized to be easier for users to understand and manage. This reduces technical clutter when configuring reports, especially in accounting and printing-related settings.
Original PR description
Clean the views of ir.action.report to be more user friendly. Before this commit, the views were very technical oriented. Task [link](https://www.odoo.com/odoo/project.task/6285465) task-6285465
Report action views in Odoo Studio have been simplified to make them easier for users to understand. This reduces technical clutter and helps business users configure reports more confidently.
Original PR description
Clean the views of ir.action.report to be more user friendly. Before this commit, the views were very technical oriented. task-6285465
The FACe electronic invoicing option for Spanish public administration invoices is no longer selected by default, reducing unnecessary steps for most customers. When a user selects FACe for a specific partner, Odoo remembers that choice for future invoices to that partner.
Original PR description
1. The generic wizard was not meant to override correctly the default of extra EDI, this commit fixes this problem. 2. FACe is only relevant for public administrations, so keeping it checked by default added unnecessary noise for the majority of partners that never invoice through it. It is now unchecked by default. The first time FACe is selected for a given partner, the choice is remembered so it stays checked for that partner's subsequent invoices, avoiding the need to re-enable it manually each time. 3. Cleaning some dead code, in particular `_get_ref_string` was never called and should've used `_prepare_default_reversal` instead. task-6345379
Discuss now keeps voice calls inline instead of switching users into a full meeting view, while video calls and meetings still open fullscreen. The messaging interface is also simplified by removing duplicate reaction controls, clearing unnecessary breadcrumbs, and improving the messaging menu layout.
Original PR description
A few design feedback fixes in the Discuss UI:
- Voice calls no longer open the fullscreen meeting view. Starting or joining a call with the phone button now stays inline, both in Discuss and in the chat window. Only video calls and meetings go fullscreen.
- "Open in Discuss" clears the breadcrumbs. Keeping the trail of the app the chat window was opened from ("Events / Marc Demo") was only wasted space.
- Removed the add reaction button displayed next to the reactions of a message: it duplicates the "Add a Reaction" message action, which is always available on hover.
- Removed the w-50 on the messaging menu action button and search bar, so the button takes the width it needs and the search bar gets the rest.
task-6488704
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prBelgian payroll now captures additional apprenticeship employee details, including contract type and contract number. Wage checks and payroll reporting are updated to reflect apprenticeship-specific requirements, helping businesses improve compliance and reduce payroll validation issues.
Original PR description
- add contract types and number to Apprenticeship employees. - update wages checks to adapt Apprenticeship details. Task: 6331079
Deferred account reports now look up related accounts in batches instead of one at a time. This reduces unnecessary database work and can make report generation faster, especially for companies with many accounts.
Original PR description
Browse all source accounts at once when resolving their deferred accounts. This lets the ORM prefetch `deferred_account_id` instead of issuing one query per unique account. Introduced in https://github.com/odoo/enterprise/pull/122696
Hong Kong payroll rental allowance records now use a clearer proof expiry date and rely on the existing document attachment flow for proof uploads. HR teams can see the current rental proof expiry directly on employee records and confirm or reset multiple rental records at once, reducing manual work.
Original PR description
Remove the unused payment_proof_file field, superseded by the attach_document-based proof upload flow, and rename valid_up_to_date to "Proof Expiry Date" for clarity. Also surface the current rental's proof expiry on the employee form, and allow confirming/resetting multiple rentals at once from the list view instead of one by one. Upgrade PR: https://github.com/odoo/upgrade/pull/11039 task-6391432
Belgian payslips now show and use a clearer disposable earnings amount before salary attachments are applied. This makes it easier for payroll teams to verify attachment limits and account for external replacement wage amounts correctly.
Original PR description
Currently, the net amount before salary attachments is unclear, making it difficult to verify attachment limits on Belgian payslips. - Add 'NET_REPLACEMENT_WAGE' input rule for external replacement wage. - Add 'DISPOSABLE_EARNINGS' rule to compute net base for attachments. - Update 'ATTACH_SALARY' to calculate limits from disposable earnings. Task: 6410485
Point of Sale now preserves manually entered line prices in the same tax display mode used by the cashier. This prevents small rounding differences from growing on multi-quantity sales and helps refunds match the original sale amount.
Original PR description
A price set manually on an order line is typed in the tax mode the prices are displayed in. It was then inverted through the taxes to recover a price expressed in the tax mode of the taxes, and that…
A price set manually on an order line is typed in the tax mode the prices are displayed in. It was then inverted through the taxes to recover a price expressed in the tax mode of the taxes, and that result was rounded to the "Product Price" precision before being stored. With a "Tax-Included Price" display, typing 100 on a product taxed at 15% stored 100 / 1.15 = 86.9565... as 86.96. The residual rounds away at a quantity of 1, but it is multiplied by the quantity, so 2 units total 200.01 and 10 units total 1000.50. This commit stores the typed price as it was typed and adds a `document_tax_mode` field on the order line holding the tax mode that price is expressed in. The mode is passed when the base line is created, in the frontend as well as in the backend, so the taxes engine resolves the price inclusion per tax instead of the price being converted beforehand. It is reset as soon as the price is recomputed, so any other price keeps following the tax configuration of the product, and it is carried over to refund lines so that a refund matches what was sold. task-6472425 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr