Daily updates from Odoo
Tuesday, August 18, 2026
35 changes · master
New functionality added to Odoo
The Chinese reports module now includes the required VAT return type configuration. This helps businesses using Odoo in China prepare VAT returns with the correct report setup available in the system.
Original PR description
Declare the account.return.type for the Chinese VAT return. task-6012279
Enhancements to existing features
Belgian payroll now includes the required Journalist Pension Fund contributions for both employees and employers. This helps payroll calculations reflect the additional 1% employee contribution and 2% employer cost based on the NSSO gross base.
Original PR description
**What:** - Added the Journalist Pension Fund (Employee) salary rule to calculate an additional 1% contribution based on the employee's NSSO gross base. - Added the Accounting: ONSS Journalist Pension Fund (Employer) salary rule to compute the corresponding 2% employer contribution based on the NSSO base, correctly impacting the total employer cost. task-6424251
The Dutch reporting module now uses the shared Dutch SBR tax identifier stored on partner records instead of its older company-specific field. This reduces duplicate data entry and keeps Dutch tax reporting aligned with the standard identifier setup.
Original PR description
After adding l10n_nl_sbr_ob_nummer to partner identifiers l10n_nl_reports_sbr_ob_nummer needs to be deleted. - Replacing l10n_nl_reports_sbr_ob_nummer with l10n_nl_sbr_ob_nummer - Removing res company view task: [6349626](https://www.odoo.com/odoo/project/967/tasks/6349626)
Employee-related documents now stay better connected to employee records, including automatic linking when files are uploaded from an employee profile. Access rights are also synchronized with employee folders, helping ensure documents uploaded through employee discussions follow the correct permissions.
Original PR description
This PR adds more synchronization between the documents and the employee by implementing the points below. - Add the support of the `hr.employee` model in the res_model of documents. - When coming from the context of the employee, uploading the file leads to linking the employee by default to the res_model. - Synced the access rights of the employee folder when the parent folder changes or when the employee folder is created. - Now, documents uploaded from the chatter of the employee will inherit the access rights from the folder. Task-6072094
Accrual-related settings in accounting reports have been moved to the newer plugin-based approach. This keeps the reporting feature aligned with the platform’s current architecture and helps reduce future maintenance risk without changing the user workflow.
Original PR description
In account reports, accrual context is defined in the env but the env is deprecated. The correct way to do it now is to define a plugin.
The AI website builder can now use database information and add JavaScript when simpler page edits are not enough, enabling richer interactive website content. New review, tracking, pause, and editing safeguards help keep AI-generated scripts manageable and reduce the risk of unsafe or disruptive changes.
Original PR description
[IMP] ai_website: enable ai in website to have access to the database This commit reuses the skill to retrieve information from the db. --- [FIX] ai: replace binary field's raw content with its url…
[IMP] ai_website: enable ai in website to have access to the database This commit reuses the skill to retrieve information from the db. --- [FIX] ai: replace binary field's raw content with its url Instead of using the binary field raw content and overflowing the context, we replace it with the url serving the content. --- [IMP] ai_website: allow ai to add javascript to the page This commit enables ai to add javascript to the page, when it's needed. By default, scripts are added as a last resort. Firstly, AI tries to satisfy the user's prompt with HTML/CSS changes, and when it's not possible, we allow AI to add javascript. Because static analysis of custom js scripts is quite limited, a dedicated LLM safety reviewer is introduced to validate proposed code. To ensure safety, the review fails if any vulnerability or suspicious pattern is detected, or if the reviewer call itself fails. In addition, to make sure ai scripts don't mess up the history, and that we properly clean up everything that ai generated, we prompt AI to wrap every part of the code that changes the DOM interactively in a wrapper `__aiProtectMutations`, which handles mutations done right after this call, so we can easily track the changes made by ai script, in order to easily reset modifications made by ai before saving the page, or when entering the edit mode. Also, in the edit mode this wrapper ignores the mutations made by the script. To make it work more-or-less acceptably without shenanigans, we stop the execution of ai generated scripts on entering the translation mode. Also, we add an option container top button to pause the execution of the ai scripts in a block, so users can easily edit it. We prompt AI not to hardcode strings on state change, but instead have a few different blocks with necessary text and show/hide them with d-none. This way we show every text block when scripts don't run to be able to edit them. task-6144157 --- [IMP] website_knowledge: add docstrings to some controllers Previous commit allows AI website builder to search for and use backend controllers. To make it work better we improve docstrigs of some useful controllers in website_knowledge. task-6144157
Date fields in the Marketing Automation dashboard are now aligned to the left, making them easier to read and consistent with the intended layout. This is a small visual improvement that helps users interpret dashboard information more clearly.
Original PR description
…e fields This commit adapts the alignment of the date fields in the marketing automation dashboard to ensure they are displayed correctly (aligned to left). Task: 6474652
The spreadsheet action button has been renamed from "Insert in spreadsheet" to "Spreadsheet". This makes the interface clearer and more concise for users working with spreadsheet-related views.
Original PR description
This commit renames the old `Insert in spreadsheet` button to `Spreadsheet` to keep it simple. Task: 6477436
Belgian payroll now includes employees' holiday attest balance when calculating paid time off to allocate for the next year. December allocations will require approval instead of being automatically approved, giving HR teams better oversight before finalizing leave balances.
Original PR description
- changed allocations from december to be in "to approve" state instead of approved - added a column for Holiday Attest Balance in holiday pay step and included it in the time off to allocate for next year task-id: 6394281
Payslip lines that rely on quarterly calculations or direct totals now hide misleading amount values and show explanatory text instead. This makes Belgian payslips easier to understand and reduces confusion for payroll users and employees reviewing payslip details.
Original PR description
As some numbers is calculated based on quarter and total amounts are calculated directly we should hide the value of amount col and show info text for those lines Task: 6431856
Belgian payroll users can now see the monthly taxable benefit amount directly in the tooltip for internet, mobile, laptop, and tablet benefits. This makes it easier to understand what will appear on the payslip without checking payroll rule parameters separately, while keeping amounts aligned with indexed values.
Original PR description
[IMP] l10n_be_hr_payroll: display the BIK amount in the field tooltips
The internet, mobile, mobile_amount, laptop and tablet fields hold what
the subscription or the device actually costs the employer, and feed the
employer cost computation.
What the employee is taxed on is a different, flat monthly amount coming
from the bik_* rule parameters. Nothing in the interface showed it, so
the only way to know what would land on the payslip was to go and open
the rule parameter itself.
That amount is now appended to the tooltip of each of those fields:
The employee's internet subscription will be paid up to this amount.
Benefit in kind: 5.00 € / month.
It is resolved in fields_get instead of being written into the field
definitions, so it keeps following the indexation of the rule parameters.
task-6447748UrbanPiper point-of-sale preparation tickets can now follow printer settings that split tickets by individual product. This helps kitchen or preparation teams receive clearer, item-specific tickets instead of one combined order ticket.
Original PR description
Preparation ticket generation now takes an is_split_per_product flag, read from the printer configuration, to print one ticket per product instead of one ticket grouping the whole order. pos_urban_piper overrides _generate_preparation_receipt_data to add its own data on top of the generated receipts. related-https://github.com/odoo/odoo/pull/267412 task-6227300
The empty Commission Plan screen now shows an illustrated explanation of how commission plans are calculated instead of a generic placeholder image. This helps sales and compensation teams understand the setup flow more quickly, with support for mobile layouts and right-to-left languages.
Original PR description
For the Commission Plan's empty screen we've replaced the smiling face guy with an explanation on how a commission plan is calculated in the form of an illustrated diagram. Adapts for mobile and rtl. ⚠️ Note for RTL translations: The `x` position on the translatable lines in the SVG needs to be changed to `75` and `95` respectively ```diff - <tspan x="24.9952" y="109.264">Invoices, </tspan> - <tspan x="10.1241" y="124.264">Sale Orders, ...</tspan> + <tspan x="75" y="109.264">[translation for "Invoices, " ]</tspan> + <tspan x="95" y="124.264">[translation for "Sale Orders, ..."]</tspan> ``` task-6369345
Mexican payroll teams can now choose an alternative ISR withholding method that converts each pay period’s taxable income to a monthly equivalent, applies the monthly tax table, then scales the result back. This helps companies align payslip tax calculations with their preferred local practice while keeping the existing method available.
Original PR description
Some Mexican companies compute the income tax withheld on each payslip scaling up the period taxable income to its monthly equivalent. Here the monthly table is applied, and the resulting tax is scaled back down to the period. This adds a company level switch between the two methods. Both are exposed in the Payroll settings, the days per month being configurable: - 'standard' keeps the current behaviour, looking up the tax table matching the employee's pay schedule. - 'monthly_with_period_factor' derives a period factor by dividing 'l10n_mx_isr_days_per_month' (30.4 by default, i.e. 365 / 12) by the number of days in the pay period, and applies the monthly table to the scaled income. The monthly table itself is already in the database, as the 'monthly' key of the 'l10n_mx_isr_tables' rule parameter, so no new data is introduced and the new method follows the yearly table updates like the existing one does. task-6433348
Resolved issues and error corrections
Invoice and bill numbers now reflect fiscal years that span more than 12 months, such as using a 25-26 year range instead of only 2026. This prevents misleading document numbering and keeps accounting sequences aligned with the company’s configured fiscal year records.
Original PR description
Issue: When a fiscal year begins, for example, the 01/12/2025 and ends the 31/12/2026, the sequence mechanism for the invoices and bills do not take into account that the fiscal year covers more than a year and the sequence starts at INV/2026/0001 instead of INV/25-26/0001. Source of the issue: when computing if the year is stagerred, we took into account only the fiscalyear_last_day and fiscalyear_last_month of the company, instead of checking if there exists any record of account.fiscal.year, and if there is, prioritize the existing records. task-4951257
The timesheet assistant display now keeps durations readable, adds clearer spacing, and prevents long titles from overlapping with time information. This makes timesheet entries easier to scan and reduces visual confusion for users.
Original PR description
- enforce duration in one line - add a gap between the title and duration - wrap title if so long - adapt flex direction of chronological view to avoid overlapping of title and start time --- task-6432434 Forward-Port-Of: odoo/enterprise#128037 Forward-Port-Of: odoo/enterprise#126236
The Belgian payroll accounting test demo data now defines employee working schedules correctly. This helps keep payroll-related tests and sample scenarios reliable, reducing confusion from incorrect demo setup.
Original PR description
The way calendar attendances were defined for the working schedules demo data was incorrect. task-6466997
Shopfloor users can now unplan manufacturing work orders without being blocked by an access error linked to Belgian payroll leave records. This fixes a disruption caused when removing planned work time triggered a payroll-related check the user was not allowed to perform.
Original PR description
After https://github.com/odoo/enterprise/pull/104335 , A search on `hr.leave.allocation` is done, which the normal shopfloor user doesn't have access to. In shopfloor,`leave_id` (a field related to `resource_calender_leaves` in `mrp_workorder`) gets unlinked in a couple of different actions, which then triggers the unlink method added that performs the search consequently. Simple steps to reproduce: - Use shopfloor user - Create MO - Plan workorders - Unplan At unplanning, `leave_id` is unlinked, which then triggers the `on_delete` method in `l10n_be_hr_payroll` that performs the search and throws the access error.
The accounting reports comparison dropdown now keeps a consistent width when users hover over the “Percentage of” selector. This prevents a small visual jump, making the reporting interface feel smoother and more polished.
Original PR description
In the comparison dropdown, the "Percentage of" RecordSelector shows its caret only on hover. Since the caret was not accounted for before hover, the selector slightly resized when the caret appeared. Reserve a small, fixed slot for the caret and toggle its visibility so the dropdown keeps a stable width. task-6268556
Users can now select multiple bank journal lines in the kanban view without triggering an error. This restores a smoother bank reconciliation workflow for teams handling multiple statement lines at once.
Original PR description
Fix a bug where an error is raised when the user tries to multi-select lines (with alt) in the kanban view of bank journals. The view for BankRecStatementLine class was using an other object than rootRef defined in the KanbanRecord class as a t-ref. This made every call to rootRef crash in the parent class. This commit fixes it by using the parent rootRef in the BankRecStatementLine class. task-6462758
Luxembourg payroll now calculates historical payslips using the wage index that applied at the payslip date, rather than today’s index. This helps ensure past salary calculations remain accurate when wage index values change over time.
Original PR description
Historical payslips incorrectly used today's wage index instead of the index active during the payslip period. Now, salary rules evaluate the indexed wage using `payslip.date_to` via the new `_get_l10n_lu_indexed_wage(date)` contract method. Task: 6395557 Forward-Port-Of: odoo/enterprise#125861
Rental orders using custom routes now correctly generate the expected return transfer, even when the route is configured for make-to-order purchasing. This prevents missing return logistics after a rental delivery, helping teams track rented products through the full rental cycle.
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental order for 1 x P and set the the MTO route on the sol - Confirm the order #### > The delivery as well as the purchase for 1 unit of P was generated but the return was not. ### Cause of the issue: The procurement generated to handle both the delivery and the return rental picking are handled by the `_create_procurements`: https://github.com/odoo/enterprise/blob/b0e48baaf99bdc4faefd2ffdd3bd5637fb548593/sale_stock_renting/models/sale_order_line.py#L353-L374 The `route_ids` set and used is the `mto_route` set on the sol: https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L415-L422 https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L282-L297 However, in the present case, the mto route does not contain any rule with a relevant `location_src_id` in the rental location so that the return will not be generated. opw-6361322 Forward-Port-Of: odoo/enterprise#126410 Forward-Port-Of: odoo/enterprise#124097
This update adds a missing dependency so barcode batch quality control loads the related batch picking components reliably. It prevents test and module loading failures without changing day-to-day user workflows.
Original PR description
Before this commit, this bridge patches the barcode picking batch model of stock_barcode_picking_batch while not depending on it. This goes unnoticed in the backend, where every installed module lands in the same bundle, but a Hoot test file only loads the modules of the dependency closure of its addon, so the first test suite added here dies on "error while registering suite". This commit adds the missing dependency. stock_barcode_picking_batch is auto installed on top of stock_barcode and stock_picking_batch, both already required here, so it comes along with this module anyway.
The payroll attendance module now explicitly includes a related attendance planning component it already relies on. This prevents automated tests from failing when they load only the module's declared dependencies, improving reliability without changing day-to-day user behavior.
Original PR description
Before this commit, hr_payroll_attendance patches the gantt view of hr_attendance_gantt while not depending on it. This goes unnoticed in the backend, where every installed module lands in the same bundle, but a Hoot test file only loads the modules of the dependency closure of its addon, so the first test suite added here dies on "error while registering suite". This commit adds the missing dependency. hr_attendance_gantt is auto installed on top of hr_attendance and hr_gantt, both already required here, so it comes along with this module anyway.
The Time Type form now hides the Validity label for companies outside Hong Kong when the related field is not shown. This prevents misaligned fields and makes the payroll configuration screen clearer for users in non-HK companies.
Original PR description
Steps to reproduce: 1. Go to Payroll > Configuration > Time Types. 2. Open a Time Type form for a non-HK company (e.g. Belgium). 3. The "Validity" label appears without its field, misaligning "Selectable in Time Off". Reason: The "Validity" label had no visibility condition. Solution: Hide the "Validity" label when the company is non-HK. Task-6448696
Barcode receipts now keep the correct putaway destination when users scan multiple lots for the same product. This prevents items from being shown or processed as going to the default stock location instead of the intended shelf, reducing warehouse handling errors.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2…
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2 units of that product; putaway sets the reserved move line destination to WH/Stock/Shelf 1. 4. In the Barcode app, scan a first lot, then a second lot. The second lot lands on a separate line at WH/Stock instead of WH/Stock/Shelf 1. Issue --- The first lot reuses the reserved line and keeps its Shelf 1 destination. The second lot cannot reuse it because its tracking number differs, so `_findLine` returns nothing and `_getNewLineDefaultValues` builds a new line with `location_dest_id` set to `_defaultDestLocation()`, the picking's default destination (WH/Stock). https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L1591-L1601 Putaway relocates the destination on the move line at reservation, never on the picking, so only the reserved line carries Shelf 1. Since `groupKey` includes `location_dest_id`, the new line does not group with the first lot and shows separately at WH/Stock. This is not a regression: new lines have always defaulted to the operation destination. https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L239-L241 The new line now inherits the selected line's `location_dest_id`, already relocated by putaway, instead of the default. opw-6317077 Forward-Port-Of: odoo/enterprise#127906 Forward-Port-Of: odoo/enterprise#125309
Odoo now recognizes valid Brazilian electronic invoice XML files even when the main invoice tag has no extra attributes. This prevents legitimate vendor bills from being skipped during import, helping accounting teams process supplier invoices more consistently.
Original PR description
### Issue before this commit: Certain valid Brazilian NF-e (electronic invoice) XML files fail to import because the system silently ignores them during the initial EDI recognition phase. ### Steps to reproduce the issue: 1. Download Accounting and l10n_br_edi 2. Go to Vendor > Bills 3. Try to import both xmls in the ticket 4. One of the two will not be imported correctly ### Cause of the issue: https://github.com/odoo/enterprise/blob/3ed1721b702555e96c9774969927f6517e855704/l10n_br_edi/models/account_move.py#L819-L827 This function relies on a strict byte string search for b"<NFe " while it's also correct if the tag is only `<NFe>`. ### Reason to introduce the fix: To make the initial NF-e file recognition more robust and compliant with standard XML namespace rules, ensuring Odoo successfully processes all valid Brazilian invoices regardless of attribute formatting. opw-6402843 Forward-Port-Of: odoo/enterprise#127851 Forward-Port-Of: odoo/enterprise#126881
This update adds a missing dependency needed by the Time Off Gantt module so its related test suites load correctly. It prevents registration failures during automated testing without changing day-to-day user functionality.
Original PR description
Before this commit, every Hoot suite of hr_holidays_gantt, hr_payroll and planning_holidays dies while being registered:
HootError: error while registering suite "avatar_card" (in parent
suite "@hr_holidays_gantt")
This happens because the gantt cog menu imports @base_import/import_records/import_records while the module does not depend on base_import. A test file only loads the modules of the dependency closure of its addon, so the import resolves to undefined and the file throws as soon as it is loaded.
This commit adds the missing dependency. base_import is auto installed and depends only on web, so it is already there in every database.This fixes a display issue in Referrals where the x icon was missing from job positions when sharing jobs. The change helps users clearly see and use the expected close or remove action in that workflow.
Original PR description
Since https://github.com/odoo/enterprise/pull/112607, the x icon is not displayed on job positions. Steps to reproduce: - Referrals - View Jobs - Share Expected behavior: The x icon should be displayed on job positions. <img width="213" height="188" alt="image" src="https://github.com/user-attachments/assets/14d1e75b-f419-4315-93b3-ef0642351079" /> Current Behavior: The x icon is not displayed on job positions. <img width="558" height="374" alt="image" src="https://github.com/user-attachments/assets/52bffb8b-b7ba-43df-8a44-c507966d5073" /> task-6469820
Belgian DIMONA fields are now shown when employee types are relevant to Belgium or not limited to a country, avoiding missing setup options. The update also prevents mismatched employee type and company countries, reducing payroll configuration errors.
Original PR description
company/country validation DIMONA category and sub-types were hidden whenever the employee type's country was not exactly 'BE', including when no country was set at all. They should be visible whenever the type has no country or BE, and no company or a BE company. Add a `company_country_code` related field to expose the company's country for use in the view invisible domain, and add a constraint raising a validation error if an employee type's country and its related company's country don't match. Task: 6442738 PR community: [odoo/odoo#281923](https://github.com/odoo/odoo/pull/281923)
The Timesheets Assistant now opens in a chronological view so employees can match activities to work more naturally. It also avoids repeated loading, keeps dismissed suggestions from coming back, reduces visual flicker when selecting suggestions, and better recognizes Discord activity from a browser.
Original PR description
## [FIX] timesheet_grid: remove duplicate rpc call Before this commit, the `loadTimesheets` method is called 2 times in a row, that method does a rpc call to load the existing timesheets and so, it…
## [FIX] timesheet_grid: remove duplicate rpc call Before this commit, the `loadTimesheets` method is called 2 times in a row, that method does a rpc call to load the existing timesheets and so, it is not needed to call it 2 times since the rpc will return the exact same result. This commit removes the rpc call when we compute the suggestions to only load the timesheets when we load all the data. ## [FIX] timesheet_grid: show chronological view instead of project view Before this commit, the `by project` view were loaded first in the timesheet assistant action, to group the suggestion by project, the problem is at the beginning the view will not really show a perfect matching and so the user could think the feature does not work and he will not understand how to correctly match the suggestions shown in the view. This commit changes the view loaded by default in Timesheets Assistant to first show the chronological view, that view is more logical for the current user to rethink what he did in the past to correctly map the events to a project and a task when he generates his timesheets thanks to those events. The by project view is still useful afterwards when the system has learned the choices made by the current user. ## [FIX] timesheet_grid: ensure events are consumed forever Before this commit, the suggestions removed by the current user comes back when he changes the date and come back to the day he removes the suggestions. The reason is because a shallow copy of events consumed is made and that copy alters the duration of the initial object. This commit avoids copying the consumed events object to make sure the initial object is not altered when processing the events to remove them if they are removed before by the user. ### Steps to reproduce the issue: 1. install timesheet_grid and Activity watch, makes sure Activity watch collects some activities on your computer. 2. Go to Assistant menu in timesheets app. 3. Remove some suggestions displayed in the right panel. 4. Go to next date. 5. Come back to previous date. ### Expected Behavior: The suggestions removed should not appear again. ### Actual Behavior: The suggestions removed come back in the view. ## [FIX] timesheet_grid: fix flicker when suggestion selected Before this commit, when the user selects a suggestion in timesheet assistant, there is a small flicker appears because the height of the row grows because of the border added to highlight the suggestion selected. This commit reviews a bit the style to make sure the border bottom in the previous element is removed if the element is not selected or if the 2 consecutives suggestions are selected. ## [FIX] timesheet_grid: fix discord rules to handle discord in web Before this commit, when the user uses discord in its browser instead of the app on his computer, the discord rules don't catch the activity watch events because the tab title is different than the windows name in the app. This commit adapts the regex of Discord rules to handle the both use cases. task-[6385639](https://www.odoo.com/odoo/project.task/6385639) Forward-Port-Of: odoo/enterprise#126435 Forward-Port-Of: odoo/enterprise#124855
Spreadsheet pivot tables now apply currency exchange rates when they are inserted. This helps users working with multi-currency data see more accurate financial figures in their reports.
Original PR description
apply currency exchange rates when inserting a pivot in spreadsheet Task: 6022608
The Timesheet Assistant now combines selected suggestions that come from the same rule template into one clearer description. This avoids repetitive text separated by semicolons, making generated timesheet entries easier to read and edit.
Original PR description
In this task, we improved the Timesheet Assistant by merging descriptions generated from the same rule templates. When multiple suggestions are selected that use the same rule template, the assistant now combines them into a single timesheet description instead of joining with ';' Example: Rule template: `Discussing with $1` Before: Discussing with A; Discussing with B After: Discussing with A and B Task-6348575 Forward-Port-Of: odoo/enterprise#127358 Forward-Port-Of: odoo/enterprise#126157
Code cleanup and technical improvements
The Point of Sale enterprise code was updated to use the newer supported framework behavior, replacing a deprecated internal mechanism. This keeps the module aligned with the latest platform standards and reduces future maintenance risk without introducing intended user-facing changes.
Original PR description
Replaced `useLayoutEffect` in `useDelayedValueChange` with native OWL3 `useEffect` because `useLayoutEffect` is deprecated in OWL3. The hook has no DOM/ref access — it arms a `setTimeout` to snapshot a reactive value after a delay. This is a pure side-effect-on-dep-change, making native `useEffect` the correct fit. A `void getCurrentValue()` call at the top of the effect restores the tracking the old dependency array provided, ensuring the timer resets whenever the tracked value changes. When commenting out the useLayoutEffect there was no error, the code we refactored had NO TEST coverage. The only build failure when commented was a lint error (unused-var from the comment pattern) — no functional tests failed. see runbot build with useLayoutEffect commented out: https://runbot.odoo.com/runbot/batch/2622063/build/116410184
This change updates several Enterprise screens to use newer internal lifecycle hooks while keeping the same visible behavior. It reduces reliance on compatibility code, making future maintenance easier without changing how users interact with reports, data cleaning, marketing automation, planning, navigation, or maps.
Original PR description
Enterprise half of odoo/odoo#282760 — same mechanical change, same reasoning. 7 call-sites called the owl2-compat `useLayoutEffect` **with no dependency array**, which makes it an alias for "run on…
Enterprise half of odoo/odoo#282760 — same mechanical change, same reasoning. 7 call-sites called the owl2-compat `useLayoutEffect` **with no dependency array**, which makes it an alias for "run on mount, re-run on every patch". They are translated to `onMounted` + `onPatched`. | site | effect | | --- | --- | | `account_reports/account_return_check_kanban_controller.js` | restore the renderer scroll position | | `data_cleaning/data_cleaning_list_view.js` | toggle control-panel buttons from the selection | | `data_cleaning/data_merge_list_view.js` | idem | | `marketing_automation/marketing_automation_one2many.js` | `applyTabPanelVisibility()` | | `planning/planning_gantt_renderer.js` | add `o_planning_gantt` on the grid | | `web_enterprise/navbar.js` | `_updateMenuAppsIcon()` | | `web_map/map_renderer.js` | `updateMap()` + deferred marker popover | ### Why this is behaviour-preserving Called without a dependency array, the compat `useLayoutEffect` defaults `computeDependencies` to `() => [NaN]`. `NaN !== NaN`, so the diff in its `onPatched` always succeeds and the effect already re-ran on **every** patch. `onMounted` + `onPatched` is therefore an exact translation. Two incidental parts of the shim fall away, both no-ops here: `onWillRender(() => computeDependencies())` reads nothing when there is no dependency array, and `onWillUnmount(() => cleanup && cleanup())` never fires because none of these 7 effects return a cleanup function. Note this argument is specific to the no-dependency-array sites and does *not* generalise to `useLayoutEffect` calls that pass real dependencies. ### One judgement call `account_return_check_kanban_controller` keeps `onPatched`. Its `rendererScrollPositions = null` latch reads like a run-once guard, but it sits inside `if (renderer)`: when the scroll container is not in the DOM yet at mount, the latch stays set and a later patch retries the restore. Keeping both hooks preserves that. ### Conflicts with `web_map/map_renderer.js` is also touched by odoo/enterprise#127921, which converts the *empty*-dependency-array site (`() => []`) in the same `setup()` and deliberately leaves this one alone. The two changes are disjoint but adjacent, so whichever lands second needs a trivial rebase — and once both are in, `useLayoutEffect` is no longer used in that file and its import should go. ### Not in this PR - The no-dependency-array sites whose effect **does** return a cleanup function need the full `onMounted`/`onPatched`/`onWillUnmount` triple and are handled separately (`sale_commission` by the `useChart` hook in odoo/enterprise#128100). - `spreadsheet_edition` is owned by another team and is left alone. - `web_gantt/static/tests/gantt_view_other.test.js` has one more, kept out of a production-code PR. ### Testing Static only: every remaining `useLayoutEffect` call in the tree was re-parsed with balanced-paren argument splitting to confirm no no-dependency-array site is left outside the exclusions above, and every touched file was checked for a missing or newly-unused `useLayoutEffect`/`onMounted`/`onPatched` import. No behaviour change is intended, so no test was added or updated. Part of the `useLayoutEffect` -> OWL3 migration.