Wednesday, September 9, 2026
24 changes · 19.0
Enhancements to existing features
Online shop product searches and filters have been optimized by adding a missing database index. This should make search results load much faster for customers, improving the shopping experience and reducing delays on product listing pages.
Original PR description
### Description: Following commit e9d435d1c865e1f462ce2e4bb2c0715ec97c8b10, some fields were missing proper indexes, causing the e-commerce search to be slow. This commit adds an indexes on `description_ecommerce` to optimize the filters of the query. ### Benchmark: | Nb of product | Before | After | |-----------------|----------|---------| | 747 | 6m 15s | 91 ms | ### Reference: opw-6513905 ___ I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
Fixes an issue where orders shared between trusted Point of Sale setups could keep the wrong session information when the restaurant app was installed. This prevented some valid payments from being accepted, so staff can now complete shared orders with the correct payment methods.
Original PR description
**TL;DR** - in certain cases, Session is not updated on order shared on trusted pos Steps to reproduce: - Install pos_restaurant with demo data. - Have two configs: Cloth Shop and Furniture Shop. -…
**TL;DR** - in certain cases, Session is not updated on order shared on trusted pos Steps to reproduce: - Install pos_restaurant with demo data. - Have two configs: Cloth Shop and Furniture Shop. - Ensure both configs have their own individual payment method (e.g., CASH). - In Cloth Shop, add Furniture Shop as a trusted PoS. - In Cloth Shop, enable "Log in with Employee". - Open Cloth Shop and Furniture Shop in separate browsers (different users). - Refresh Cloth Shop once. - In Cloth Shop, create and save an order. - In Furniture Shop, open that order and try to pay with "CASH". Observation: * A validation error is raised: "The payment method selected is not allowed in the config of the POS session." <img width="320" height="201" alt="image" src="https://github.com/user-attachments/assets/8ca80575-76bf-4ecf-a739-08b03d543ed6" /> - although we can pay the order by a shared payment method Cause: - Refreshing Cloth Shop triggers `notify_synchronisation` due to `setCashierUpdateSession` , which pushes Cloth Shop's `pos.session` record into Furniture Shop's IndexedDB (because Cloth Shop trusts Furniture Shop). https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/pos_hr/static/src/app/services/pos_store.js#L61-L63 - When Cloth Shop saves an order, sync also pushes a copy of that order into Furniture Shop, and passed through `processDynamicRecords` - `processDynamicRecords` ensures that the Record created is in sync with server data, as Furniture Shop now has a local record of session of Cloth Shop, the record keeps `session_id` pointing to Cloth Shop's session, else it would have been left `undefined` - from the `res` we get, we set the session_id on `pos.order ` https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/point_of_sale/static/src/app/utils/devices_synchronisation.js#L127-L139 - However with pos_restaurant installed we get its orveride which stores the result of super() and only returns result early when there are no` pos.order ` records in dynamicRecords. When pos.order records are present (our case), the method proceeds with its own logic but never returns result (or its own output) at the end https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/pos_restaurant/static/src/app/utils/devices_synchronisation.js#L5-L9 - so the corrected data from the super call is silently dropped. - we do not get a change to update the session id - The order keeps Cloth Shop's session ID - Furniture Shop's payment validation checks the order against its session's allowed payment methods, but since the session is still Cloth Shop's, the check fails for methods not shared between Cloth Shop and Furniture Shop (e.g., CASH). Why this is hidden in other cases: - without pos_restaurant, or if Furniture Shop had no prior knowledge of Cloth Shop's session (we made is possible by `Log in with Employee` feature, session_id would stay `undefined` and later get correctly set toFurniture Shop's session in PosOrder.setup(). https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/point_of_sale/static/src/app/models/pos_order.js#L27-L30 or from here https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/point_of_sale/static/src/app/utils/devices_synchronisation.js#L127-L139 - Both safety nets happen to be bypassed here. Fix: * Tighten the early return condition so that data is only discarded when the current configuration is not a restaurant configuration. * Also, A trusted PoS configuration cannot be a restaurant, so not returning later makes sense. opw-6465228 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Code cleanup and technical improvements
The accounting test suite was tidied by removing duplicate helper code and obsolete commented-out tests. This is an internal maintenance change that makes future updates easier without changing how users work with the product.
Original PR description
This commit cleans up the test suite within the `account_accountant` module by removing redundant methods and old commented code. no-task Forward-Port-Of: odoo/enterprise#130723 Forward-Port-Of: odoo/enterprise#130644
Documentation and clarification updates
A new individual contributor license agreement was added for a contributor. This confirms the legal permissions needed for their future contributions to be accepted by the project.
Original PR description
Adding my signed Individual Contributor License Agreement (v1.0) under `doc/cla/individual/khalmuratovm.md` so that my future contributions can be accepted.
This fixes an issue where applying text animation across multiple lines or blocks on a website page could shift centered content out of alignment. Website editors can now animate selected text in these cases without disrupting the page layout.
Original PR description
### Problem: Text animation used a single span around the full selection range. When a selection crossed block elements, this placed headings and paragraphs inside a span, producing invalid HTML and changing their layout. ### Steps to reproduce: 1. Drag & drop a snippet (like the "Cover" block) that contains page centered text 2. Select a range of text spanning multiple block elements within the added snippet 3. Add an animation to the selected text. <img width="800" height="200" alt="image" src="https://github.com/user-attachments/assets/45074927-4d60-4517-b65b-7ba6d667e060" /> ### Solution: This PR splits the selection by block and creates one inline animation wrapper per block instead. The builder applies animation options to the resulting elements as one group, without changing the document's block structure. task-5155887
German Intrastat dispatch reports now correctly use region code 99 when goods originate outside Germany, helping companies meet official reporting requirements. The export also handles German number formatting and weight rounding more reliably, reducing reporting errors.
Original PR description
### Issue: In Germany, the intrastat report requires region code `99` for dispatch moves where the product origin country is not DE Per the official specification (section 5.8 — Region of origin):…
### Issue: In Germany, the intrastat report requires region code `99` for dispatch moves where the product origin country is not DE Per the official specification (section 5.8 — Region of origin): "As for goods with foreign origin, code '99' should be entered" https://erhebungsportal.estatistik.de/Erhebungsportal/api/assets/files?downloadId=0c5422f111104705b021b41616ad1ecc But `99` was not being used in those cases ### Cause: `99` was already the default fallback when no `region_code` is set but `_fill_missing_values` had no condition to override the region code for dispatch moves with a non-DE origin country ### Notes: While fixing this, two additional issues were found when exporting with the German locale (`de_DE`): - `weight` and `supplementary_units` are formatted with a comma as decimal separator by the German locale, causing `float()` to raise a `ValueError` — fixed by normalizing to dot before conversion, as done in other localizations - The dispatch/arrival check was comparing against the translated label (e.g. `'Versand'`) instead of a stable identifier A new `intrastat_type_code` field with static values `arrival` and `dispatch` is added based on the existing `id` values from `default_type`, avoiding locale-dependent comparisons This improvement could be extended to other localizations - Net mass is now rounded to full kilograms per item (see §5.14 of the specification linked above) A weight rounding down to 0 kg is reported as `0` instead of being silently dropped (QWeb `t-out` omits the element when the value is `None`) Totals are computed as the sum of already-rounded per-item values to stay internally consistent ### Steps to reproduce: - Install `sale_management`, `l10n_de_account` and `accountant` - Switch to the DE company - In Settings, configure the Intrastat values: -- Default invoice transaction code: 11 -- Default refund transaction code: 21 -- Intrastat region: 07 - Create 3 products with a commodity code set and country of origin: one DE, one empty, one other country - Create and confirm a Sale Order for all products with a European partner, deliver all, create and send the invoice - Open the Intrastat report (Accounting > Reporting > Taxes & Fiscal > Intrastat) - Set the month to the current month Before the fix, all regions show 07 Expected: non-DE origin products should show 99 opw-6455585
Time off measured in hours now excludes non-working periods from the employee schedule. This prevents absences spanning partially non-working days from using too many hours, improving payroll and leave balance accuracy.
Original PR description
When computing the amount of hours used by a time off, if a time off entry was set in the working schedule it would not be taken into account and the amount of hours used would be wrong. Steps to reproduce: ------------------- * Open any working schedule WS and make sure that the friday has morning set as working time and afternoon as non-working time * Make sure the time off type is configured to use hours and not days * Create a time off of 2 days that includes a friday > Observation: The amount of hours used is 16 hours instead of 12 hours Why the fix: ------------ When now filter out the non working period when computing the work intervals. opw-6469587
The accounting automatic entry wizard now properly matches related destination and accrual entries when changing periods. This prevents leftover non-neutral journal items from cluttering accounting records and improves data consistency.
Original PR description
The previous code wasn't reconciling the destination and accrual moves, leaving potentially non-neutral journal items and their counterpart polluting the DB. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update cleans up references to an old developer option that no longer exists. It helps avoid confusion for administrators and developers by keeping configuration behavior aligned with current Odoo functionality.
Original PR description
The feature was removed in odoo/odoo#115076 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
Duplicating a section in a quotation or sales order now keeps any manually adjusted prices on the copied product lines. This prevents accidental price changes back to default values and helps sales teams avoid quoting errors.
Original PR description
Problem: When duplicating a section containing sale order lines, the system should preserve any manually modified unit prices on those lines. However, the system would reset the unit price back to…
Problem: When duplicating a section containing sale order lines, the system should preserve any manually modified unit prices on those lines. However, the system would reset the unit price back to the product's default because the duplication process triggers a product onchange which resets the unit price on the order line. Solution: This commit ensures the system recognizes when an order line is being copied as part of a section duplication. The system now uses a context flag to safely bypass the default price reset, allowing the original, manually modified price to correctly carry over to the duplicated lines. Steps to reproduce(runbot v19): 1. Create a Quotation and add a product line under a section. 2. Manually modify the unit price on the product line to a custom value (e.g., set $10 to $99). 3. Click the section dropdown menu and click Duplicate. 4. Notice the duplicated product line incorrectly resets its unit price back to the default price ($10) instead of preserving the manually modified price ($99). opw-6421922
This fix stops non-product display lines from sales orders being linked to manufacturing stock movements. It prevents incorrect traceability and keeps manufacturing records tied only to real sale order lines.
Original PR description
Issue: ====== before this commit, user was able to select a display SOL and at MO confirmation the SOL was copied to the stock move, so we end up with a stock move linked to a display SOL, which is not correct. Solution: ========= - add a domain on the SOL field as first guard layer - add check on the SOL on MO confirmation to prevent copying a display SOL to the stock move opw-6473017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286534
This fix restores protection for the company’s designated project documents folder so it cannot be archived accidentally. It helps prevent disruption to project document organization and keeps the expected folder structure available to users.
Original PR description
The company's project folder is supposed to be [impossible](https://github.com/odoo/enterprise/blob/20cc61e69aa3f6a59de1e962b25ce11fa402bf22/documents_project/models/documents_document.py#L44) to archive, by using the `_unlink_except_company_folders` logic. However, the method that adds the company field to the list of fields to check was missing, so it was still possible to archive a folder set as projects folder.
This fixes unstable automated tests by preventing unnecessary password hash refreshes during test logins. It keeps test sessions consistent when several requests happen at the same time, reducing false failures and improving confidence in test results.
Original PR description
The test harness patches the CryptContext object to spend less time hashing to decrease total test runtime. Because the hash parameters have changed, every first login (per transaction) per user will result in a hash rotation. The session_id is also rotated when the password hash rotates. When multiple requests are sent to the server while a session rotation is underway, the session datastore holds either a valid, or expired, or logged-out user session. This is a source of indeterminism in tests that can be prevented by always returning None value for replacement hash. REF Runbot; https://runbot.odoo.com/odoo/error/242811 REF Runbot; https://runbot.odoo.com/odoo/error/233722 Forward-Port-Of: odoo/odoo#287259 Forward-Port-Of: odoo/odoo#285710
The shop floor now prevents users from opening another gear menu dialog while a Manufacturing Order is loading. This avoids disruptive errors on slow connections and makes navigation from work orders more reliable for manufacturing teams.
Original PR description
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. *…
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. * On a work order card, click the **gear** icon to open the menu dialog. * Click **Open Manufacturing Order** on a slow network connection. * Before the MO form view finishes loading, quickly click the **gear** icon again and open another dialog (e.g. Log Note). * The MO form view loads, destroying the shop floor component. * Close the Log Note dialog. **Observed behavior:** * An `UncaughtPromiseError: Component is destroyed` error is thrown because the dialog tries to interact with the shop floor component that has already been destroyed by the navigation to the MO form view. **Cause:** * When the user clicks "Open Manufacturing Order", `doAction` is called to navigate to the MO form view, and `props.close()` immediately closes the menu dialog. However, the shop floor component is still visible while the new view is loading. * During this gap, the gear button remains clickable. If the user opens another dialog (e.g. Log Note), that dialog holds a reference to the shop floor component. When the MO form view finishes mounting, the shop floor is destroyed, and closing the stale dialog triggers operations on the destroyed component. **Fix:** * Add an `actionPending` state flag to `MrpDisplayRecord`. When the user selects "Open Manufacturing Order" from the menu dialog, an `onSelect` callback sets `actionPending` to `true`, which disables the gear button and prevents any new dialog from being opened. * The flag is only set for `openMO` (which navigates away and destroys the component), not for other menu actions like Scrap, Add Component, or Log Note which open wizard dialogs and return to the shop floor. opw-6107579 Forward-Port-Of: odoo/enterprise#130831 Forward-Port-Of: odoo/enterprise#123490
This fixes a spelling mistake in the Helpdesk Auto Assignment group name. The change improves clarity in the interface and avoids confusion for users managing helpdesk settings.
Original PR description
This commit fixes the typo in the "Auto Assignment" group. task-6542450 Forward-Port-Of: odoo/enterprise#130880 Forward-Port-Of: odoo/enterprise#130841
General Ledger exports now use the same search behavior as the on-screen report, so filtered exports include the same account lines users see in the interface. This prevents missing rows in exported reports when users search by partial account names or numbers.
Original PR description
When applying a search filter in the General Ledger, the lines displayed in the UI differ from the ones exported. The discrepancy comes from the fact that the UI search bar filters lines using a simple "contains" logic on the displayed line name, while the backend export relies on the account model’s `_name_search` behavior, just as in the chart of accounts. For example, searching for "40" displays the accounts 400000, 400010, and 124000 but the last one (124000) is not is in the export results. task: 5917435 Forward-Port-Of: odoo/enterprise#117791 Forward-Port-Of: odoo/enterprise#107928
Turkish e-Ledger exports now fill line numbers automatically and keep them continuous across the full fiscal period, even when reports are filed monthly. This helps businesses meet GIB expectations and avoids manual post-export numbering or inconsistent month-by-month sequences.
Original PR description
Before: the `LineNumber` column of the e-Ledger CSV was always empty, left to be filled after the export. Since the ledger is filed monthly, whatever filled it restarted at 1 every month, while GİB expects the numbering to start once, at the beginning of the fiscal period, and to run unbroken until its end. Now: the column is written by the export. An export starting after the first day of the fiscal period is offset by the number of rows that period already counts, so February continues where January stopped, and a full-year export numbers the same rows identically. The lines are also read in ascending date order. They were sorted by the default order of `account.move.line`, the most recent first, so the first row of the file was the last entry of the period and could not be numbered 1. This reverses `EntryNumberCounter` as well, which now counts from the oldest entry. task-6424730 Forward-Port-Of: odoo/enterprise#130727 Forward-Port-Of: odoo/enterprise#127518
This update aligns how Odoo uses PDF processing libraries across supported Ubuntu and newer library versions. It helps prevent document handling issues caused by differences between PDF library APIs, improving reliability without changing business workflows.
Original PR description
Align pypdf usage with the PyPDF2 1.26 API used on Ubuntu Jammy, Odoo 17.0's main supported Ubuntu version, and add the missing compatibility mapping for newer pypdf versions. Forward-Port-Of: odoo/enterprise#130971
Time off requests for fully flexible employees now show the correct number of days when spanning multiple calendar days. This prevents leave balances and approvals from being based on an incorrect one-day duration.
Original PR description
Steps to reproduce: ------------------------------------ 1. Install Time off module 2. Create New Fully Flexible Employee 3. Click on the Time off smart button 4. Create time off for multiple days…
Steps to reproduce: ------------------------------------ 1. Install Time off module 2. Create New Fully Flexible Employee 3. Click on the Time off smart button 4. Create time off for multiple days (eg. Mon - Friday) Observation: ------------------------------------ Number of days still shows 1 Days. Issue: ------------------------------------ Issue occurs because `work_time_per_day_mapped` returns one interval per day for standard and flexible schedules in multi-day time off requests, so the interval count correctly matches the number of leave days. https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/hr_holidays/models/hr_leave.py#L460-L461 However, for fully flexible schedules, it returns a single interval containing the total hours across all days, causing the leave duration to always be computed as 1 day regardless of the actual number of days requested. Solution: ------------------------------------ We extended the condition to also enter the flexible branch when `employee.is_fully_flexible` is True (not just for single-day is_flexible leaves). Inside the branch, instead of hard-coding days = 1, we now compute the actual calendar-day span. Then we subtract any overlapping public holiday days (using a set to handle multi-day PHs and avoid double-counting). Subtract 0.5 for each half-day boundary. The hours computation (via Intervals subtraction) was already correct for multi-day ranges, so we kept that as-is. opw-6060552 Forward-Port-Of: odoo/odoo#255826
Confirmed purchase orders now allow users to update line descriptions consistently, even when the product column is visible. This removes an interface inconsistency that could prevent teams from correcting or clarifying purchase details after confirmation while still keeping locked states protected.
Original PR description
Steps to reproduce the bug: - Create and Confirm a purchase order with any product and a description (name) on the order line - Try to edit the description (name) field Problem: The description field…
Steps to reproduce the bug:
- Create and Confirm a purchase order with any product and a description (name) on the order line
- Try to edit the description (name) field
Problem:
The description field was not editable on a confirmed purchase order when the product_id column was visible, but became editable when product_id was hidden.
The `ProductLabelSectionAndNoteField` widget renders both `product_id` and the description (`name`) in a single cell. When `props.readonly` is true (because `product_id` has `readonly="state in ('purchase', 'to approve', 'done', 'cancel')"`) and the order state is not draft (`isProductClickable` is true), the template rendered the description textarea with a hardcoded `readonly="1"` attribute, making it impossible to edit regardless of the actual intended readonly state for the description.
When `product_id` was column-invisible, the `name` field rendered via its own `section_and_note_text` widget, which correctly used `sectionAndNoteIsReadonly` (blocking only `cancel`, `done`, `posted`) hence the inconsistency.
Solution:
Replace `readonly="1"` with `t-att-readonly="sectionAndNoteIsReadonly"` on the description textarea so its editability follows the same logic as the other cases: blocked only for terminal states (`cancel`, `done`, `posted`), not for `purchase` or `to approve`.
opw-5474986
Forward-Port-Of: odoo/odoo#272277
Forward-Port-Of: odoo/odoo#272102Adds a regression test to ensure inventory screens can skip cleanup work without disabling scheduled stock maintenance. This helps preserve background data cleanup while keeping interactive inventory pages responsive when the skip setting is enabled.
Original PR description
## Purpose Protect the existing separation between interactive stock-quant cleanup and scheduled maintenance. `stock.skip_quant_tasks` lets users open inventory screens without waiting for quant…
## Purpose Protect the existing separation between interactive stock-quant cleanup and scheduled maintenance. `stock.skip_quant_tasks` lets users open inventory screens without waiting for quant maintenance. The scheduler must continue to merge duplicate quants, reconcile reservations and remove eligible zero quants when this setting is enabled. This was the explicit intent of [the original change](https://github.com/odoo/odoo/commit/207ba01819577cf6a2a686fae39dd3d673aec6dd). ## Change Add a regression test covering both values of the setting: - `action_view_quants` and `action_view_inventory` skip maintenance when enabled and call it when disabled. - `_run_scheduler_tasks` calls maintenance in both cases. The final diff contains only the regression test. Runtime behavior is unchanged from the base branch. ## Incident scope Related to opw-6523071. Captured incident stacks show inventory-screen actions entering quant maintenance. They do not establish that the background scheduler caused those requests. The older local restore contains no `stock.skip_quant_tasks` record; the setting at the time of the incident remains unverified. The initial scheduler guard has been removed because it disabled the maintenance path that the setting deliberately preserves. This is a regression-test proposal, not a performance fix for the reported incident. The previous benchmark of an omitted query is not evidence of a faster maintenance implementation. Any optimization of scheduled cleanup requires separate evidence and must retain necessary maintenance. ## Validation The targeted Odoo test passed: 1 test, 0 failures and 0 errors. It checks both menu entry points and the scheduler with the parameter enabled and disabled. `git diff --check` passed. opw-6523071
The AI Copywriter dialog now translates its alternative writing mode labels, so users see those options in their selected language. This improves clarity for multilingual users and makes the editing experience more consistent across Odoo.
Original PR description
Description of the issue/feature this PR addresses: The alternativemodes on the AI Copywriter dialog are not translated Current behavior before PR: <img width="1079" height="250" alt="image" src="https://github.com/user-attachments/assets/fced9432-b557-44de-9b7c-a31547b7a16b" /> Desired behavior after PR is merged: <img width="1078" height="250" alt="image" src="https://github.com/user-attachments/assets/1499836a-924e-425c-b328-27a378eae62a" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287175 Forward-Port-Of: odoo/odoo#230740
SEPA Direct Debit XML files now include a bank-specific identification field only for Nordea countries where it is required. This prevents Italian banks from rejecting payment files due to an unexpected extra field, improving payment processing reliability.
Original PR description
### Issue: An unexpected `<SchmeNm><Cd>CUST</Cd></SchmeNm>` node was added inside `<InitgPty><Id><OrgId><Othr>` for all countries Some Italian banks reject SDD files containing this node ### Cause:…
### Issue: An unexpected `<SchmeNm><Cd>CUST</Cd></SchmeNm>` node was added inside `<InitgPty><Id><OrgId><Othr>` for all countries Some Italian banks reject SDD files containing this node ### Cause: https://github.com/odoo/enterprise/commit/3c3c64b511d07fc1ba33c30363972f5b0f7283d6 added `<SchmeNm><Cd>CUST</Cd></SchmeNm>` unconditionally for all countries The original fix was intended for Nordea (Sweden) only, which requires this node explicitly The assumption that other countries would accept it was incorrect ### Steps to reproduce: - Install `account_sepa_direct_debit` and `l10n_it` - Switch to the IT company - In Settings, set SEPA Direct Debit Creditor Identifier to `BE30ZZZ300D000000042` - Create and confirm a Payment (Method: SEPA Direct Debit, any customer and amount) - Create and validate a Batch Payment with that payment - Open the generated PAIN008 XML Before the fix, `<SchmeNm><Cd>CUST</Cd></SchmeNm>` is present opw-6530996 Forward-Port-Of: odoo/enterprise#130304
Fixed an unwanted horizontal scrollbar that appeared when users inserted content into a spreadsheet, especially on smaller screens. The dialog now uses the right styling for selectors and templates, making the modal cleaner and easier to use.
Original PR description
Opening "Insert in Spreadsheet" displayed an unwanted horizontal scrollbar in the spreadsheet selector. On small viewports, it could also produce a second scrollbar alongside the scrollable modal. The selector reused the `o-spreadsheet-templates-dialog` class, whose styles belong to `documents_spreadsheet`. This applied template-only max-height and overflow rules to the selector and made `spreadsheet_edition` rely on styles from a dependent module. Give selector dialogs their own class and keep the template-specific styles on the template dialog. Move the shared pager layout to `spreadsheet_edition` under a dedicated class, and update both pager consumers and the dashboard document selector. Task: 6526781 Forward-Port-Of: odoo/enterprise#130610 Forward-Port-Of: odoo/enterprise#130114