Skip to content

Comments

[17.0][FIX] spreadsheet_oca: add raiseError function to SpreadsheetRenderer#86

Merged
OCA-git-bot merged 1 commit intoOCA:17.0from
BinhexTeam:17.0-fix-spreadsheet_oca-missing-env-raiseError-function
Dec 5, 2025
Merged

[17.0][FIX] spreadsheet_oca: add raiseError function to SpreadsheetRenderer#86
OCA-git-bot merged 1 commit intoOCA:17.0from
BinhexTeam:17.0-fix-spreadsheet_oca-missing-env-raiseError-function

Conversation

@rrebollo
Copy link

@rrebollo rrebollo commented Nov 29, 2025

Fixes #85 and also deal with some pre-commit complaints.

@BinhexTeam HT14857

@rrebollo rrebollo marked this pull request as draft November 29, 2025 11:10
@rrebollo rrebollo force-pushed the 17.0-fix-spreadsheet_oca-missing-env-raiseError-function branch 3 times, most recently from 5e12fd7 to 7df71ee Compare November 29, 2025 23:12
@rrebollo
Copy link
Author

@chrisandrewmann @pedrobaeza no matter what I do, pre-commit fails in the CI, all green on my local, I have built and rebuilt pre-commit several times. Any chances CI is just crazy for some reason?

@rrebollo
Copy link
Author

I used the output of the failed pre-commit CI job to generate a patch and applied it to the repository, but I’m not entirely at peace with it. For safety, I put it in a separate commit so it can be reviewed or reverted independently.

@rrebollo rrebollo marked this pull request as ready for review November 29, 2025 23:27
@chrisandrewmann
Copy link
Contributor

chrisandrewmann commented Dec 1, 2025

I used the output of the failed pre-commit CI job to generate a patch and applied it to the repository, but I’m not entirely at peace with it. For safety, I put it in a separate commit so it can be reviewed or reverted independently.

I'd ask the opinion of others as i'm not an expert on pre-commit.
Surprised why there would be so many errors as surely the original 17.0 migration PR wouldn't have been accepted for merge previously in that state?

@pedrobaeza
Copy link
Member

Most of them were warnings, not errors. It would be good to have that output gathered in the commit message for knowing which is solving.

@rrebollo
Copy link
Author

rrebollo commented Dec 1, 2025

Most of them were warnings, not errors. It would be good to have that output gathered in the commit message for knowing which is solving.

I'm no sure to get what you mean. Do you want this trace in the commit description or the patch I built from it or ...?

Run pre-commit run --all-files --show-diff-on-failure --color=always
[INFO] Initializing environment for https://github.com/sbidoul/whool.
[INFO] Initializing environment for https://github.com/oca/maintainer-tools.
[INFO] Initializing environment for https://github.com/OCA/odoo-pre-commit-hooks.
[INFO] Initializing environment for local:prettier@2.7.1,@prettier/plugin-xml@2.2.0.
[INFO] Initializing environment for local:eslint@8.24.0,eslint-plugin-jsdoc@.
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[WARNING] repo `https://github.com/pre-commit/pre-commit-hooks` uses deprecated stage names (commit, push) which will be removed in a future version.  Hint: often `pre-commit autoupdate --repo https://github.com/pre-commit/pre-commit-hooks` will fix this.  if it does not -- consider reporting an issue to that repo.
[INFO] Initializing environment for https://github.com/astral-sh/ruff-pre-commit.
[INFO] Initializing environment for https://github.com/OCA/pylint-odoo.
[INFO] Installing environment for https://github.com/sbidoul/whool.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/oca/maintainer-tools.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/OCA/odoo-pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for local.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for local.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/astral-sh/ruff-pre-commit.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/OCA/pylint-odoo.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
forbidden files......................................(no files to check)Skipped
en.po files cannot exist.............................(no files to check)Skipped
init pyproject.toml with whool...........................................Passed
Update pre-commit excluded addons........................................Passed
Fix the manifest website key.............................................Passed
Generate addons README files from fragments.............................Skipped
Generate requirements.txt for an addons directory........................Passed
Checks for Odoo modules..................................................Passed
Checks for .po[t] files..................................................Passed
prettier (with plugin-xml)...............................................Failed
- hook id: prettier
- files were modified by this hook

spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet.xml
spreadsheet_oca/static/src/spreadsheet/bundle/filter.esm.js
spreadsheet_oca/static/src/spreadsheet/graph_controller.esm.js
spreadsheet_oca/static/src/spreadsheet/utils/dynamic_generators.esm.js
spreadsheet_oca/static/src/spreadsheet/pivot_controller.esm.js
spreadsheet_oca/demo/demo_spreadsheet.json
spreadsheet_oca/static/src/spreadsheet/bundle/chart_panel.esm.js
spreadsheet_oca/static/src/spreadsheet/bundle/odoo_panels.esm.js
spreadsheet_oca/static/src/spreadsheet/list_controller.xml
spreadsheet_oca/wizards/spreadsheet_spreadsheet_import.xml
spreadsheet_oca/static/src/spreadsheet_tree/spreadsheet_tree_view.esm.js
spreadsheet_oca/security/security.xml
spreadsheet_oca/data/spreadsheet_spreadsheet_import_mode.xml
spreadsheet_oca/static/src/spreadsheet/list_renderer.esm.js
spreadsheet_oca/static/src/spreadsheet/list_controller.esm.js
spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_renderer.esm.js
spreadsheet_oca/views/spreadsheet_spreadsheet.xml
spreadsheet_oca/static/src/spreadsheet/bundle/filter_panel_datasources.esm.js
spreadsheet_oca/static/src/spreadsheet/bundle/chart_panels.esm.js
spreadsheet_oca/static/src/spreadsheet/spreadsheet_action.esm.js
spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_controlpanel.esm.js
spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_action.esm.js
spreadsheet_oca/static/src/pivot/pivot_table.esm.js
spreadsheet_oca/wizards/spreadsheet_select_row_number.xml

eslint...................................................................Passed
- hook id: eslint
- duration: 0.79s
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
debug statements (python)................................................Passed
fix python encoding pragma...............................................Passed
check for case conflicts.................................................Passed
check docstring is first.................................................Passed
check that executables have shebangs.................(no files to check)Skipped
check for merge conflicts................................................Passed
check for broken symlinks............................(no files to check)Skipped
check xml................................................................Passed
mixed line ending........................................................Passed
ruff.....................................................................Passed
ruff-format..............................................................Passed
pylint with optional checks..............................................Passed
- hook id: pylint_odoo
- duration: 1.67s
Check for Odoo modules using pylint......................................Passed
pre-commit hook(s) made changes.
If you are seeing this message in CI, reproduce locally with: `pre-commit run --all-files`.
To run `pre-commit` as part of git workflow, use `pre-commit install`.
All changes made by hooks:
diff --git a/spreadsheet_oca/data/spreadsheet_spreadsheet_import_mode.xml b/spreadsheet_oca/data/spreadsheet_spreadsheet_import_mode.xml
index 96f7b8f..14335c7 100644
--- a/spreadsheet_oca/data/spreadsheet_spreadsheet_import_mode.xml
+++ b/spreadsheet_oca/data/spreadsheet_spreadsheet_import_mode.xml
@@ -7,7 +7,10 @@
         <field name="code">new</field>
         <field name="name">Create spreadsheet</field>
         <field name="sequence" eval="10" />
-        <field name="group_ids" eval="[(4, ref('spreadsheet_oca.group_user'))]" />
+        <field
+      name="group_ids"
+      eval="[(4, ref('spreadsheet_oca.group_user'))]"
+    />
     </record>
     <record
     id="spreadsheet_import_mode_add"
@@ -16,7 +19,10 @@
         <field name="code">add</field>
         <field name="name">Add to spreadsheet</field>
         <field name="sequence" eval="15" />
-        <field name="group_ids" eval="[(4, ref('spreadsheet_oca.group_user'))]" />
+        <field
+      name="group_ids"
+      eval="[(4, ref('spreadsheet_oca.group_user'))]"
+    />
     </record>
     <record
     id="spreadsheet_import_mode_add_sheet"
@@ -25,6 +31,9 @@
         <field name="code">add_sheet</field>
         <field name="name">Add sheet to spreadsheet</field>
         <field name="sequence" eval="16" />
-        <field name="group_ids" eval="[(4, ref('spreadsheet_oca.group_user'))]" />
+        <field
+      name="group_ids"
+      eval="[(4, ref('spreadsheet_oca.group_user'))]"
+    />
     </record>
 </odoo>
diff --git a/spreadsheet_oca/demo/demo_spreadsheet.json b/spreadsheet_oca/demo/demo_spreadsheet.json
index 79a0811..fde6c59 100644
--- a/spreadsheet_oca/demo/demo_spreadsheet.json
+++ b/spreadsheet_oca/demo/demo_spreadsheet.json
@@ -10,17 +10,17 @@
       "cols": {},
       "merges": [],
       "cells": {
-        "A1": {"style": 1, "content": "First Value", "border": 1},
-        "A2": {"format": 1, "content": "30.55", "border": 1},
-        "B1": {"style": 1, "content": "Second Value", "border": 1},
-        "B2": {"format": 1, "content": "50", "border": 1},
-        "C1": {"style": 1, "content": "Total", "border": 1},
-        "C2": {"format": 1, "content": "=sum(A2:B2)", "border": 1},
-        "A3": {"border": 2},
-        "B3": {"border": 2},
-        "C3": {"border": 2},
-        "D1": {"border": 3},
-        "D2": {"border": 3}
+        "A1": { "style": 1, "content": "First Value", "border": 1 },
+        "A2": { "format": 1, "content": "30.55", "border": 1 },
+        "B1": { "style": 1, "content": "Second Value", "border": 1 },
+        "B2": { "format": 1, "content": "50", "border": 1 },
+        "C1": { "style": 1, "content": "Total", "border": 1 },
+        "C2": { "format": 1, "content": "=sum(A2:B2)", "border": 1 },
+        "A3": { "border": 2 },
+        "B3": { "border": 2 },
+        "C3": { "border": 2 },
+        "D1": { "border": 3 },
+        "D2": { "border": 3 }
       },
       "conditionalFormats": [],
       "figures": [],
@@ -30,8 +30,8 @@
     }
   ],
   "entities": {},
-  "styles": {"1": {"bold": true, "align": "center"}},
-  "formats": {"1": "[$$]#,##0.00"},
+  "styles": { "1": { "bold": true, "align": "center" } },
+  "formats": { "1": "[$$]#,##0.00" },
   "borders": {
     "1": {
       "top": ["thin", "#000"],
@@ -39,8 +39,8 @@
       "left": ["thin", "#000"],
       "right": ["thin", "#000"]
     },
-    "2": {"top": ["thin", "#000"]},
-    "3": {"left": ["thin", "#000"]}
+    "2": { "top": ["thin", "#000"] },
+    "3": { "left": ["thin", "#000"] }
   },
   "revisionId": "START_REVISION",
   "uniqueFigureIds": true,
diff --git a/spreadsheet_oca/security/security.xml b/spreadsheet_oca/security/security.xml
index a83afd9..2f37faa 100644
--- a/spreadsheet_oca/security/security.xml
+++ b/spreadsheet_oca/security/security.xml
@@ -23,7 +23,9 @@
     <record model="ir.rule" id="spreadsheet_company_rule">
         <field name="name">Spreadsheet Company Rule</field>
         <field name="model_id" ref="model_spreadsheet_spreadsheet" />
-        <field name="domain_force">[('company_id', 'in', company_ids + [False])]</field>
+        <field
+      name="domain_force"
+    >[('company_id', 'in', company_ids + [False])]</field>
     </record>
     <record model="ir.rule" id="spreadsheet_owner_rule">
         <field name="name">Spreadsheet Owner</field>
@@ -55,12 +57,20 @@
     <record model="ir.rule" id="spreadsheet_manager_rule">
         <field name="name">Spreadsheet Manager</field>
         <field name="model_id" ref="model_spreadsheet_spreadsheet" />
-        <field name="groups" eval="[(4, ref('spreadsheet_oca.group_manager'))]" />
+        <field
+      name="groups"
+      eval="[(4, ref('spreadsheet_oca.group_manager'))]"
+    />
         <field name="domain_force">[(1,'=', 1)]</field>
     </record>
     <record model="ir.rule" id="spreadsheet_import_mode_rule">
         <field name="name">Spreadsheet Import mode</field>
-        <field name="model_id" ref="model_spreadsheet_spreadsheet_import_mode" />
-        <field name="domain_force">[('group_ids','in', user.groups_id.ids)]</field>
+        <field
+      name="model_id"
+      ref="model_spreadsheet_spreadsheet_import_mode"
+    />
+        <field
+      name="domain_force"
+    >[('group_ids','in', user.groups_id.ids)]</field>
     </record>
 </odoo>
diff --git a/spreadsheet_oca/static/src/pivot/pivot_table.esm.js b/spreadsheet_oca/static/src/pivot/pivot_table.esm.js
index c95fcd6..7dc50bd 100644
--- a/spreadsheet_oca/static/src/pivot/pivot_table.esm.js
+++ b/spreadsheet_oca/static/src/pivot/pivot_table.esm.js
@@ -1,8 +1,8 @@
 /** @odoo-module */
 /* Copyright 2024 Tecnativa - Carlos Roca
  * License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
-import {SpreadsheetPivotTable} from "@spreadsheet/pivot/pivot_table";
-import {patch} from "@web/core/utils/patch";
+import { SpreadsheetPivotTable } from "@spreadsheet/pivot/pivot_table";
+import { patch } from "@web/core/utils/patch";
 
 patch(SpreadsheetPivotTable.prototype, {
   get _dynamic_cols() {
@@ -53,7 +53,9 @@ patch(SpreadsheetPivotTable.prototype, {
       const vals = JSON.stringify(values);
       const maxLength = Math.max(...cols.map((col) => col.length));
       for (let i = 0; i < maxLength; i++) {
-        const cellValues = cols.map((col) => JSON.stringify((col[i] || {}).values));
+        const cellValues = cols.map((col) =>
+          JSON.stringify((col[i] || {}).values)
+        );
         if (cellValues.includes(vals)) {
           return i;
         }
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panel.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panel.esm.js
index 40f36f7..c4c8b68 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panel.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panel.esm.js
@@ -1,10 +1,10 @@
 /** @odoo-module */
 
 import * as spreadsheet from "@odoo/o-spreadsheet";
-import {patch} from "@web/core/utils/patch";
+import { patch } from "@web/core/utils/patch";
 
-const {chartRegistry} = spreadsheet.registries;
-const {ChartPanel} = spreadsheet.components;
+const { chartRegistry } = spreadsheet.registries;
+const { ChartPanel } = spreadsheet.components;
 export function isOdooKey(code) {
   return code.startsWith("odoo_");
 }
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panels.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panels.esm.js
index 7bc6d02..6071aea 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panels.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/chart_panels.esm.js
@@ -1,15 +1,18 @@
 /** @odoo-module */
 
 import * as spreadsheet from "@odoo/o-spreadsheet";
-import {Domain} from "@web/core/domain";
+import { Domain } from "@web/core/domain";
 
-import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
-import {_t} from "@web/core/l10n/translation";
-import {patch} from "@web/core/utils/patch";
-import {useService} from "@web/core/utils/hooks";
+import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
+import { _t } from "@web/core/l10n/translation";
+import { patch } from "@web/core/utils/patch";
+import { useService } from "@web/core/utils/hooks";
 
-const {LineBarPieConfigPanel, ScorecardChartConfigPanel, GaugeChartConfigPanel} =
-  spreadsheet.components;
+const {
+  LineBarPieConfigPanel,
+  ScorecardChartConfigPanel,
+  GaugeChartConfigPanel,
+} = spreadsheet.components;
 
 const menuChartProps = {
   setup() {
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/filter.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/filter.esm.js
index 1cefb52..99f9677 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/filter.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/filter.esm.js
@@ -1,19 +1,19 @@
 /** @odoo-module **/
 
 import * as spreadsheet from "@odoo/o-spreadsheet";
-import {Component, onWillStart, useState} from "@odoo/owl";
-import {_lt, _t} from "@web/core/l10n/translation";
-import {FilterValue} from "@spreadsheet/global_filters/components/filter_value/filter_value";
-import {ModelFieldSelector} from "@web/core/model_field_selector/model_field_selector";
-import {ModelSelector} from "@web/core/model_selector/model_selector";
-import {RELATIVE_DATE_RANGE_TYPES} from "@spreadsheet/helpers/constants";
-import {globalFiltersFieldMatchers} from "@spreadsheet/global_filters/plugins/global_filters_core_plugin";
-import {useService} from "@web/core/utils/hooks";
+import { Component, onWillStart, useState } from "@odoo/owl";
+import { _lt, _t } from "@web/core/l10n/translation";
+import { FilterValue } from "@spreadsheet/global_filters/components/filter_value/filter_value";
+import { ModelFieldSelector } from "@web/core/model_field_selector/model_field_selector";
+import { ModelSelector } from "@web/core/model_selector/model_selector";
+import { RELATIVE_DATE_RANGE_TYPES } from "@spreadsheet/helpers/constants";
+import { globalFiltersFieldMatchers } from "@spreadsheet/global_filters/plugins/global_filters_core_plugin";
+import { useService } from "@web/core/utils/hooks";
 
-const {topbarMenuRegistry} = spreadsheet.registries;
+const { topbarMenuRegistry } = spreadsheet.registries;
 const uuidGenerator = new spreadsheet.helpers.UuidGenerator();
 
-topbarMenuRegistry.add("file", {name: _t("File"), sequence: 10});
+topbarMenuRegistry.add("file", { name: _t("File"), sequence: 10 });
 topbarMenuRegistry.addChild("filters", ["file"], {
   name: _t("Filters"),
   sequence: 70,
@@ -40,14 +40,14 @@ topbarMenuRegistry.addChild("settings", ["file"], {
   icon: "o-spreadsheet-Icon.COG",
 });
 
-const {sidePanelRegistry} = spreadsheet.registries;
+const { sidePanelRegistry } = spreadsheet.registries;
 
 export class FilterPanel extends Component {
   onEditFilter(filter) {
-    this.env.openSidePanel("EditFilterPanel", {filter});
+    this.env.openSidePanel("EditFilterPanel", { filter });
   }
   onAddFilter(type) {
-    this.env.openSidePanel("EditFilterPanel", {filter: {type: type}});
+    this.env.openSidePanel("EditFilterPanel", { filter: { type: type } });
   }
 }
 
@@ -70,7 +70,7 @@ export class EditFilterPanel extends Component {
       type: this.props.filter.type,
       defaultValue: this.props.filter.defaultValue,
       rangeType: this.props.filter.rangeType || "year",
-      modelName: {technical: this.props.filter.modelName, label: null},
+      modelName: { technical: this.props.filter.modelName, label: null },
       objects: {},
     });
     this.relativeDateRangeTypes = RELATIVE_DATE_RANGE_TYPES;
@@ -84,7 +84,9 @@ export class EditFilterPanel extends Component {
       this.state.modelName.label = modelLabel[0] && modelLabel[0].display_name;
     }
     var ModelFields = [];
-    for (var [objectType, objectClass] of Object.entries(globalFiltersFieldMatchers)) {
+    for (var [objectType, objectClass] of Object.entries(
+      globalFiltersFieldMatchers
+    )) {
       for (const objectId of objectClass.getIds()) {
         var fields = objectClass.getFields(objectId);
         this.state.objects[objectType + "_" + objectId] = {
@@ -112,22 +114,25 @@ export class EditFilterPanel extends Component {
   }
   get dateRangeTypes() {
     return [
-      {type: "fixedPeriod", description: _t("Month / Quarter")},
-      {type: "relative", description: _t("Relative Period")},
-      {type: "from_to", description: _t("From / To")},
+      { type: "fixedPeriod", description: _t("Month / Quarter") },
+      { type: "relative", description: _t("Relative Period") },
+      { type: "from_to", description: _t("From / To") },
     ];
   }
   get dateOffset() {
     return [
-      {value: 0, name: ""},
-      {value: -1, name: _lt("Previous")},
-      {value: -2, name: _lt("Before Previous")},
-      {value: 1, name: _lt("Next")},
-      {value: 2, name: _lt("After next")},
+      { value: 0, name: "" },
+      { value: -1, name: _lt("Previous") },
+      { value: -2, name: _lt("Before Previous") },
+      { value: 1, name: _lt("Next") },
+      { value: 2, name: _lt("After next") },
     ];
   }
   onChangeFieldMatchOffset(object, ev) {
-    this.state.objects[object.id].fieldMatch.offset = parseInt(ev.target.value, 10);
+    this.state.objects[object.id].fieldMatch.offset = parseInt(
+      ev.target.value,
+      10
+    );
   }
   onModelSelected(ev) {
     this.state.modelName.technical = ev.technical;
@@ -138,7 +143,9 @@ export class EditFilterPanel extends Component {
     this.state.defaultValue = undefined;
   }
   onSave() {
-    const action = this.props.filter.id ? "EDIT_GLOBAL_FILTER" : "ADD_GLOBAL_FILTER";
+    const action = this.props.filter.id
+      ? "EDIT_GLOBAL_FILTER"
+      : "ADD_GLOBAL_FILTER";
     this.env.openSidePanel("FilterPanel", {});
     var filter = {
       id: this.props.filter.id || uuidGenerator.uuidv4(),
@@ -151,7 +158,7 @@ export class EditFilterPanel extends Component {
     var filterMatching = {};
     Object.values(this.state.objects).forEach((object) => {
       filterMatching[object.type] = filterMatching[object.type] || {};
-      filterMatching[object.type][object.objectId] = {...object.fieldMatch};
+      filterMatching[object.type][object.objectId] = { ...object.fieldMatch };
     });
     this.env.model.dispatch(action, {
       id: filter.id,
@@ -182,7 +189,7 @@ export class EditFilterPanel extends Component {
 }
 
 EditFilterPanel.template = "spreadsheet_oca.EditFilterPanel";
-EditFilterPanel.components = {ModelSelector, ModelFieldSelector};
+EditFilterPanel.components = { ModelSelector, ModelFieldSelector };
 
 sidePanelRegistry.add("EditFilterPanel", {
   title: "Edit Filter",
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/filter_panel_datasources.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/filter_panel_datasources.esm.js
index 58cc72b..5e764e1 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/filter_panel_datasources.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/filter_panel_datasources.esm.js
@@ -1,18 +1,21 @@
 /** @odoo-module **/
 
 import * as spreadsheet from "@odoo/o-spreadsheet";
-import {Component, onWillStart, onWillUpdateProps} from "@odoo/owl";
-import {makeDynamicCols, makeDynamicRows} from "../utils/dynamic_generators.esm";
-import {Domain} from "@web/core/domain";
-import {DomainSelector} from "@web/core/domain_selector/domain_selector";
-import {DomainSelectorDialog} from "@web/core/domain_selector_dialog/domain_selector_dialog";
-import {FormViewDialog} from "@web/views/view_dialogs/form_view_dialog";
-import {_t} from "@web/core/l10n/translation";
-import {formatDate} from "@web/core/l10n/dates";
-import {useService} from "@web/core/utils/hooks";
+import { Component, onWillStart, onWillUpdateProps } from "@odoo/owl";
+import {
+  makeDynamicCols,
+  makeDynamicRows,
+} from "../utils/dynamic_generators.esm";
+import { Domain } from "@web/core/domain";
+import { DomainSelector } from "@web/core/domain_selector/domain_selector";
+import { DomainSelectorDialog } from "@web/core/domain_selector_dialog/domain_selector_dialog";
+import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog";
+import { _t } from "@web/core/l10n/translation";
+import { formatDate } from "@web/core/l10n/dates";
+import { useService } from "@web/core/utils/hooks";
 
-const {DateTime} = luxon;
-const {sidePanelRegistry, topbarMenuRegistry} = spreadsheet.registries;
+const { DateTime } = luxon;
+const { sidePanelRegistry, topbarMenuRegistry } = spreadsheet.registries;
 
 topbarMenuRegistry.addChild("data_sources", ["data"], (env) => {
   let sequence = 100;
@@ -34,7 +37,7 @@ topbarMenuRegistry.addChild("data_sources", ["data"], (env) => {
     name: env.model.getters.getListDisplayName(listId),
     sequence: sequence++,
     execute: (child_env) => {
-      child_env.model.dispatch("SELECT_ODOO_LIST", {listId: listId});
+      child_env.model.dispatch("SELECT_ODOO_LIST", { listId: listId });
       child_env.openSidePanel("ListPanel", {});
     },
     icon: "spreadsheet_oca.ListIcon",
@@ -118,15 +121,15 @@ export class PivotPanelDisplay extends Component {
       sheetId: this.env.model.getters.getActiveSheetId(),
       table: tableStructure,
     });
-    this.env.model.dispatch("REFRESH_PIVOT", {id: this.props.pivotId});
+    this.env.model.dispatch("REFRESH_PIVOT", { id: this.props.pivotId });
   }
 
   async insertDynamicPivot() {
     const datasourceModel = await this.env.model.getters
       .getPivotDataSource(this.props.pivotId)
       .copyModelWithOriginalDomain();
-    var {cols, rows, measures} = datasourceModel.getTableStructure().export();
-    const {dynamic_rows, number_of_rows, dynamic_cols, number_of_cols} =
+    var { cols, rows, measures } = datasourceModel.getTableStructure().export();
+    const { dynamic_rows, number_of_rows, dynamic_cols, number_of_cols } =
       await new Promise((resolve) => {
         this.dialog.add(
           FormViewDialog,
@@ -145,7 +148,7 @@ export class PivotPanelDisplay extends Component {
               });
             },
           },
-          {onClose: () => resolve(false)}
+          { onClose: () => resolve(false) }
         );
       });
     if (!dynamic_rows && !dynamic_cols) {
@@ -181,14 +184,17 @@ export class PivotPanelDisplay extends Component {
       sheetId: this.env.model.getters.getActiveSheetId(),
       table,
     });
-    this.env.model.dispatch("REFRESH_PIVOT", {id: this.props.pivotId});
+    this.env.model.dispatch("REFRESH_PIVOT", { id: this.props.pivotId });
   }
   delete() {
-    this.env.askConfirmation(_t("Are you sure you want to delete this pivot?"), () => {
-      this.env.model.dispatch("REMOVE_PIVOT", {
-        pivotId: this.props.pivotId,
-      });
-    });
+    this.env.askConfirmation(
+      _t("Are you sure you want to delete this pivot?"),
+      () => {
+        this.env.model.dispatch("REMOVE_PIVOT", {
+          pivotId: this.props.pivotId,
+        });
+      }
+    );
   }
 }
 
@@ -258,11 +264,14 @@ export class ListPanelDisplay extends Component {
     });
   }
   delete() {
-    this.env.askConfirmation(_t("Are you sure you want to delete this list?"), () => {
-      this.env.model.dispatch("REMOVE_ODOO_LIST", {
-        listId: this.props.listId,
-      });
-    });
+    this.env.askConfirmation(
+      _t("Are you sure you want to delete this list?"),
+      () => {
+        this.env.model.dispatch("REMOVE_ODOO_LIST", {
+          listId: this.props.listId,
+        });
+      }
+    );
   }
 }
 
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/odoo_panels.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/odoo_panels.esm.js
index 0397e03..6f105a9 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/odoo_panels.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/odoo_panels.esm.js
@@ -1,14 +1,14 @@
 /** @odoo-module */
 
 import * as spreadsheet from "@odoo/o-spreadsheet";
-import {Domain} from "@web/core/domain";
-import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
-import {_t} from "@web/core/l10n/translation";
-import {useService} from "@web/core/utils/hooks";
+import { Domain } from "@web/core/domain";
+import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
+import { _t } from "@web/core/l10n/translation";
+import { useService } from "@web/core/utils/hooks";
 
-const {chartSidePanelComponentRegistry} = spreadsheet.registries;
-const {LineBarPieDesignPanel} = spreadsheet.components;
-const {Component} = owl;
+const { chartSidePanelComponentRegistry } = spreadsheet.registries;
+const { LineBarPieDesignPanel } = spreadsheet.components;
+const { Component } = owl;
 
 export class OdooPanel extends Component {
   setup() {
@@ -73,7 +73,7 @@ export class OdooPanel extends Component {
   }
 }
 OdooPanel.template = "spreadsheet_oca.OdooPanel";
-OdooPanel.components = {Many2XAutocomplete};
+OdooPanel.components = { Many2XAutocomplete };
 
 class OdooStackablePanel extends OdooPanel {
   onChangeStacked(ev) {
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet.xml b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet.xml
index bfec383..5b15b9e 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet.xml
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet.xml
@@ -14,7 +14,10 @@
     </t>
     <t t-name="spreadsheet_oca.PivotPanel" owl="1">
         <t t-if="pivotId">
-            <PivotPanelDisplay pivotId="pivotId" pivotDefinition="pivotDefinition" />
+            <PivotPanelDisplay
+        pivotId="pivotId"
+        pivotDefinition="pivotDefinition"
+      />
         </t>
         <t t-else="1">
         </t>
@@ -25,16 +28,22 @@
                 <div
           class="o_spreadsheet_oca_datasource_panel_field_title"
         >Pivot name</div>
-                <span t-esc="env.model.getters.getPivotDisplayName(props.pivotId)" />
+                <span
+          t-esc="env.model.getters.getPivotDisplayName(props.pivotId)"
+        />
             </div>
             <div class="o_spreadsheet_oca_datasource_panel_field">
-                <div class="o_spreadsheet_oca_datasource_panel_field_title">Model</div>
+                <div
+          class="o_spreadsheet_oca_datasource_panel_field_title"
+        >Model</div>
                 <div><t t-esc="modelLabel" /> (<t
             t-esc="props.pivotDefinition.model"
           />)</div>
             </div>
             <div class="o_spreadsheet_oca_datasource_panel_field">
-                <div class="o_spreadsheet_oca_datasource_panel_field_title">Domain</div>
+                <div
+          class="o_spreadsheet_oca_datasource_panel_field_title"
+        >Domain</div>
                 <DomainSelector
           resModel="props.pivotDefinition.model"
           domain="domain"
@@ -48,7 +57,11 @@
                 <div
           class="o_spreadsheet_oca_datasource_panel_field_title"
         >Dimensions</div>
-                <t t-foreach="pivotDimensions" t-as="dimension" t-key="dimension">
+                <t
+          t-foreach="pivotDimensions"
+          t-as="dimension"
+          t-key="dimension"
+        >
                     <div t-esc="dimension" />
                 </t>
             </div>
@@ -76,7 +89,9 @@
             <div class="o_spreadsheet_oca_pivot_panel_info">
                 Last updated at <t t-esc="lastUpdate" />
             </div>
-            <div class="o_spreadsheet_oca_datasource_panel_field o-sidePanelButtons">
+            <div
+        class="o_spreadsheet_oca_datasource_panel_field o-sidePanelButtons"
+      >
                 <button
           t-on-click="insertPivot"
           class="btn btn-info"
@@ -107,16 +122,22 @@
                 <div
           class="o_spreadsheet_oca_datasource_panel_field_title"
         >List name</div>
-                <span t-esc="env.model.getters.getListDisplayName(props.listId)" />
+                <span
+          t-esc="env.model.getters.getListDisplayName(props.listId)"
+        />
             </div>
             <div class="o_spreadsheet_oca_datasource_panel_field">
-                <div class="o_spreadsheet_oca_datasource_panel_field_title">Model</div>
+                <div
+          class="o_spreadsheet_oca_datasource_panel_field_title"
+        >Model</div>
                 <div><t t-esc="modelLabel" /> (<t
             t-esc="props.listDefinition.model"
           />)</div>
             </div>
             <div class="o_spreadsheet_oca_datasource_panel_field">
-                <div class="o_spreadsheet_oca_datasource_panel_field_title">Domain</div>
+                <div
+          class="o_spreadsheet_oca_datasource_panel_field_title"
+        >Domain</div>
                 <DomainSelector
           resModel="props.listDefinition.model"
           domain="domain"
@@ -129,7 +150,9 @@
             <div class="o_spreadsheet_oca_pivot_panel_info">
                 Last updated at <t t-esc="lastUpdate" />
             </div>
-            <div class="o_spreadsheet_oca_datasource_panel_field o-sidePanelButtons">
+            <div
+        class="o_spreadsheet_oca_datasource_panel_field o-sidePanelButtons"
+      >
                 <button
           t-on-click="() => this.delete()"
           class="btn btn-danger"
@@ -188,7 +211,11 @@
           t-on-change="onDateRangeChange"
           class="o_input"
         >
-                    <t t-foreach="dateRangeTypes" t-as="range" t-key="range.type">
+                    <t
+            t-foreach="dateRangeTypes"
+            t-as="range"
+            t-key="range.type"
+          >
                         <option
               t-att-selected="state.rangeType === range.type ? 1 : 0"
               t-att-value="range.type"
@@ -278,7 +305,9 @@
                 <span t-esc="object.name" /> - <span t-esc="object.tag" />
             </div>
             <div class="d-flex justify-content-between">
-                <div class="spreadsheet_oca_filter_value flex-column flex-grow-1">
+                <div
+          class="spreadsheet_oca_filter_value flex-column flex-grow-1"
+        >
                     <ModelFieldSelector
             path="object.fieldMatch.chain || ''"
             resModel="object.model"
@@ -291,13 +320,20 @@
                 </div>
             </div>
 
-            <div class="spreadsheet_oca_filter_value" t-if="state.type === 'date'">
+            <div
+        class="spreadsheet_oca_filter_value"
+        t-if="state.type === 'date'"
+      >
                 <select
           t-model="object.fieldMatch.offset"
           t-on-change="(ev) => this.onChangeFieldMatchOffset(object, ev)"
           class="o_input"
         >
-                    <t t-foreach="dateOffset" t-as="offset" t-key="offset.value">
+                    <t
+            t-foreach="dateOffset"
+            t-as="offset"
+            t-key="offset.value"
+          >
                         <option
               t-att-selected="offset.value === object.fieldMatch.offset ? 1 : 0"
               t-att-value="offset.value"
@@ -310,7 +346,10 @@
         </div>
         <div class="o-sidePanelButtons">
             <button t-on-click="onRemove" class="btn btn-danger">Remove</button>
-            <button t-on-click="onCancel" class="btn btn-warning">Cancel</button>
+            <button
+        t-on-click="onCancel"
+        class="btn btn-warning"
+      >Cancel</button>
             <button t-on-click="onSave" class="btn btn-primary">Save</button>
         </div>
     </t>
@@ -336,7 +375,10 @@
     <t t-name="spreadsheet_oca.Breadcrumbs.Small" owl="1">
         <ol class="breadcrumb">
             <t t-if="breadcrumbs.length > 1">
-                <t t-set="breadcrumb" t-value="breadcrumbs[breadcrumbs.length - 2]" />
+                <t
+          t-set="breadcrumb"
+          t-value="breadcrumbs[breadcrumbs.length - 2]"
+        />
                 <li
           class="breadcrumb-item o_back_button btn btn-secondary"
           t-on-click.prevent="() => this.onBreadcrumbClicked(breadcrumb.jsId)"
@@ -356,7 +398,10 @@
     <t t-name="spreadsheet_oca.Breadcrumbs" owl="1">
         <t t-set="currentBreadcrumbs" t-value="breadcrumbs.slice(-1)" />
         <t t-set="visiblePathBreadcrumbs" t-value="breadcrumbs.slice(-3, -1)" />
-        <t t-set="collapsedBreadcrumbs" t-value="breadcrumbs.slice(0, -3).reverse()" />
+        <t
+      t-set="collapsedBreadcrumbs"
+      t-value="breadcrumbs.slice(0, -3).reverse()"
+    />
         <t t-set="breadcrumb" t-value="currentBreadcrumbs[0] || {}" />
 
         <div
@@ -381,7 +426,9 @@
             t-if="collapsedBreadcrumbs.length"
             class="breadcrumb-item d-inline-flex min-w-0"
           >
-                        <Dropdown togglerClass="'btn btn-light btn-sm px-1 p-0'">
+                        <Dropdown
+              togglerClass="'btn btn-light btn-sm px-1 p-0'"
+            >
                             <t t-set-slot="toggler">
                                 <i class="fa fa-ellipsis-h" />
                             </t>
@@ -509,9 +556,13 @@
                 data-bs-toggle="dropdown"
                 aria-expanded="false"
               >
-                                 <span class="visually-hidden">Toggle Dropdown</span>
+                                 <span
+                  class="visually-hidden"
+                >Toggle Dropdown</span>
                             </button>
-                            <ul class="dropdown-menu o_control_panel_collapsed_create">
+                            <ul
+                class="dropdown-menu o_control_panel_collapsed_create"
+              >
                                 <t t-slot="layout-buttons" />
                                 <t t-slot="control-panel-always-buttons" />
                             </ul>
@@ -523,7 +574,9 @@
                         </div>
                     </div>
                     <t t-if="env.config.noBreadcrumbs">
-                        <section class="o_control_panel_breadcrumbs_actions d-contents">
+                        <section
+              class="o_control_panel_breadcrumbs_actions d-contents"
+            >
                             <t t-slot="control-panel-additional-actions" />
                             <t t-slot="control-panel-status-indicator" />
                         </section>
@@ -564,7 +617,10 @@
                   t-set="activeView"
                   t-value="env.config.viewSwitcherEntries.find((view) => view.active)"
                 />
-                                <i class="oi-fw" t-att-class="activeView.icon" />
+                                <i
+                  class="oi-fw"
+                  t-att-class="activeView.icon"
+                />
                             </t>
                             <t
                 t-foreach="env.config.viewSwitcherEntries"
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_action.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_action.esm.js
index 55f8dae..8e7a263 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_action.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_action.esm.js
@@ -1,17 +1,20 @@
 /** @odoo-module **/
 
 import * as spreadsheet from "@odoo/o-spreadsheet";
-import {makeDynamicCols, makeDynamicRows} from "../utils/dynamic_generators.esm";
-import {ListDataSource} from "@spreadsheet/list/list_data_source";
-import {PivotDataSource} from "@spreadsheet/pivot/pivot_data_source";
-import {SpreadsheetControlPanel} from "./spreadsheet_controlpanel.esm";
-import {SpreadsheetRenderer} from "./spreadsheet_renderer.esm";
-import {registry} from "@web/core/registry";
-import {useService} from "@web/core/utils/hooks";
+import {
+  makeDynamicCols,
+  makeDynamicRows,
+} from "../utils/dynamic_generators.esm";
+import { ListDataSource } from "@spreadsheet/list/list_data_source";
+import { PivotDataSource } from "@spreadsheet/pivot/pivot_data_source";
+import { SpreadsheetControlPanel } from "./spreadsheet_controlpanel.esm";
+import { SpreadsheetRenderer } from "./spreadsheet_renderer.esm";
+import { registry } from "@web/core/registry";
+import { useService } from "@web/core/utils/hooks";
 
 const uuidGenerator = new spreadsheet.helpers.UuidGenerator();
 const actionRegistry = registry.category("actions");
-const {Component, onMounted, onWillStart, useSubEnv} = owl;
+const { Component, onMounted, onWillStart, useSubEnv } = owl;
 
 export class ActionSpreadsheetOca extends Component {
   setup() {
@@ -36,7 +39,7 @@ export class ActionSpreadsheetOca extends Component {
             this.model,
             "get_spreadsheet_data",
             [[this.spreadsheetId]],
-            {context: {bin_size: false}}
+            { context: { bin_size: false } }
           )
         ) || {};
     });
@@ -60,7 +63,7 @@ export class ActionSpreadsheetOca extends Component {
       this.orm.call(this.model, "write", [this.spreadsheetId, data]);
     } else {
       this.spreadsheetId = await this.orm.call(this.model, "create", [data]);
-      this.router.pushState({spreadsheet_id: this.spreadsheetId});
+      this.router.pushState({ spreadsheet_id: this.spreadsheetId });
     }
   }
   /**
@@ -80,7 +83,7 @@ export class ActionSpreadsheetOca extends Component {
       }
       context[key] = searchParams.context[key];
     }
-    return {...searchParams, context};
+    return { ...searchParams, context };
   }
   async importDataGraph(spreadsheet_model) {
     var sheetId = spreadsheet_model.getters.getActiveSheetId();
@@ -144,8 +147,9 @@ export class ActionSpreadsheetOca extends Component {
       while (row >= 0) {
         for (var col = maxcols; col >= 0; col--) {
           if (
-            spreadsheet_model.getters.getCell({sheetId, col, row}) !== undefined &&
-            spreadsheet_model.getters.getCell({sheetId, col, row}).content
+            spreadsheet_model.getters.getCell({ sheetId, col, row }) !==
+              undefined &&
+            spreadsheet_model.getters.getCell({ sheetId, col, row }).content
           ) {
             filled = true;
             break;
@@ -158,10 +162,10 @@ export class ActionSpreadsheetOca extends Component {
       }
       row += 1;
     }
-    return {sheetId, row};
+    return { sheetId, row };
   }
   async importDataList(spreadsheet_model) {
-    var {sheetId, row} = this.importCreateOrReuseSheet(spreadsheet_model);
+    var { sheetId, row } = this.importCreateOrReuseSheet(spreadsheet_model);
     const dataSourceId = uuidGenerator.uuidv4();
     var list_info = {
       metaData: {
@@ -202,7 +206,7 @@ export class ActionSpreadsheetOca extends Component {
     });
   }
   async importDataPivot(spreadsheet_model) {
-    var {sheetId, row} = this.importCreateOrReuseSheet(spreadsheet_model);
+    var { sheetId, row } = this.importCreateOrReuseSheet(spreadsheet_model);
     const dataSourceId = uuidGenerator.uuidv4();
     const colGroupBys = this.import_data.metaData.colGroupBys.concat(
       this.import_data.metaData.expandedColGroupBys
@@ -227,7 +231,7 @@ export class ActionSpreadsheetOca extends Component {
       pivot_info
     );
     await dataSource.load();
-    var {cols, rows, measures} = dataSource.getTableStructure().export();
+    var { cols, rows, measures } = dataSource.getTableStructure().export();
     if (this.import_data.dyn_number_of_rows) {
       const indentations = rows.map((r) => r.indent);
       const max_indentation = Math.max(...indentations);
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_controlpanel.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_controlpanel.esm.js
index 800375b..37a92b5 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_controlpanel.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_controlpanel.esm.js
@@ -1,9 +1,9 @@
 /** @odoo-module **/
 
-import {Component} from "@odoo/owl";
-import {ControlPanel} from "@web/search/control_panel/control_panel";
+import { Component } from "@odoo/owl";
+import { ControlPanel } from "@web/search/control_panel/control_panel";
 
-const {useState} = owl;
+const { useState } = owl;
 
 export class SpreadsheetName extends Component {
   setup() {
@@ -13,7 +13,7 @@ export class SpreadsheetName extends Component {
   }
   _onNameChanged(ev) {
     if (ev.target.value) {
-      this.env.saveRecord({name: ev.target.value});
+      this.env.saveRecord({ name: ev.target.value });
     }
     this.state.name = ev.target.value;
   }
diff --git a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_renderer.esm.js b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_renderer.esm.js
index 1331bdd..d2121f1 100644
--- a/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_renderer.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/bundle/spreadsheet_renderer.esm.js
@@ -1,21 +1,21 @@
 /** @odoo-module **/
 
 import * as spreadsheet from "@odoo/o-spreadsheet";
-import {Component} from "@odoo/owl";
-import {ConfirmationDialog} from "@web/core/confirmation_dialog/confirmation_dialog";
-import {DataSources} from "@spreadsheet/data_sources/data_sources";
-import {Dialog} from "@web/core/dialog/dialog";
-import {Field} from "@web/views/fields/field";
-import {_t} from "@web/core/l10n/translation";
-import {createDefaultCurrencyFormat} from "@spreadsheet/currency/helpers";
-import {loadSpreadsheetDependencies} from "@spreadsheet/assets_backend/helpers";
-import {migrate} from "@spreadsheet/o_spreadsheet/migration";
-import {useService} from "@web/core/utils/hooks";
-import {useSetupAction} from "@web/webclient/actions/action_hook";
-import {waitForDataLoaded} from "@spreadsheet/helpers/model";
+import { Component } from "@odoo/owl";
+import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
+import { DataSources } from "@spreadsheet/data_sources/data_sources";
+import { Dialog } from "@web/core/dialog/dialog";
+import { Field } from "@web/views/fields/field";
+import { _t } from "@web/core/l10n/translation";
+import { createDefaultCurrencyFormat } from "@spreadsheet/currency/helpers";
+import { loadSpreadsheetDependencies } from "@spreadsheet/assets_backend/helpers";
+import { migrate } from "@spreadsheet/o_spreadsheet/migration";
+import { useService } from "@web/core/utils/hooks";
+import { useSetupAction } from "@web/webclient/actions/action_hook";
+import { waitForDataLoaded } from "@spreadsheet/helpers/model";
 
-const {Spreadsheet, Model} = spreadsheet;
-const {useSubEnv, onWillStart} = owl;
+const { Spreadsheet, Model } = spreadsheet;
+const { useSubEnv, onWillStart } = owl;
 const uuidGenerator = new spreadsheet.helpers.UuidGenerator();
 
 class SpreadsheetTransportService {
@@ -26,18 +26,21 @@ class SpreadsheetTransportService {
     this.res_id = res_id;
     this.channel = "spreadsheet_oca;" + this.model + ";" + this.res_id;
     this.bus_service.addChannel(this.channel);
-    this.bus_service.addEventListener("notification", this.onNotification.bind(this));
+    this.bus_service.addEventListener(
+      "notification",
+      this.onNotification.bind(this)
+    );
     this.listeners = [];
   }
-  onNotification({detail: notifications}) {
-    for (const {payload, type} of notifications) {
+  onNotification({ detail: notifications }) {
+    for (const { payload, type } of notifications) {
       if (
         type === "spreadsheet_oca" &&
         payload.res_model === this.model &&
         payload.res_id === this.res_id
       ) {
         // What shall we do if no callback is defined (empty until onNewMessage...) :/
-        for (const {callback} of this.listeners) {
+        for (const { callback } of this.listeners) {
           // eslint-disable-next-line callback-return
           callback(payload);
         }
@@ -45,10 +48,13 @@ class SpreadsheetTransportService {
     }
   }
   sendMessage(message) {
-    this.orm.call(this.model, "send_spreadsheet_message", [[this.res_id], message]);
+    this.orm.call(this.model, "send_spreadsheet_message", [
+      [this.res_id],
+      message,
+    ]);
   }
   onNewMessage(id, callback) {
-    this.listeners.push({id, callback});
+    this.listeners.push({ id, callback });
   }
   leave(id) {
     this.listeners = this.listeners.filter((listener) => listener.id !== id);
@@ -71,7 +77,7 @@ export class SpreadsheetRenderer extends Component {
         ["symbol", "full_name", "position", "name", "decimal_places"],
         {
           order: "active DESC, full_name ASC",
-          context: {active_test: false},
+          context: { active_test: false },
         }
       );
       return odooCurrencies.map((currency) => {
@@ -103,7 +109,7 @@ export class SpreadsheetRenderer extends Component {
     this.spreadsheet_model = new Model(
       migrate(this.props.record.spreadsheet_raw),
       {
-        custom: {env: this.env, orm: this.orm, dataSources},
+        custom: { env: this.env, orm: this.orm, dataSources },
         defaultCurrencyFormat,
         external: {
           loadCurrencies: this.loadCurrencies,
@@ -128,7 +134,10 @@ export class SpreadsheetRenderer extends Component {
       askConfirmation: this.askConfirmation.bind(this),
       downloadAsXLXS: this.downloadAsXLXS.bind(this),
     };
-    if (!("raiseError" in this.env) || typeof this.env.raiseError !== "function") {
+    if (
+      !("raiseError" in this.env) ||
+      typeof this.env.raiseError !== "function"
+    ) {
       subEnv.raiseError = this.raiseError.bind(this);
     }
     useSubEnv(subEnv);
@@ -142,12 +151,12 @@ export class SpreadsheetRenderer extends Component {
     });
     dataSources.addEventListener("data-source-updated", () => {
       const sheetId = this.spreadsheet_model.getters.getActiveSheetId();
-      this.spreadsheet_model.dispatch("EVALUATE_CELLS", {sheetId});
+      this.spreadsheet_model.dispatch("EVALUATE_CELLS", { sheetId });
     });
   }
   onSpreadsheetSaved() {
     const data = this.spreadsheet_model.exportData();
-    this.env.saveRecord({spreadsheet_raw: data});
+    this.env.saveRecord({ spreadsheet_raw: data });
     this.spreadsheet_model.leaveSession();
   }
   askConfirmation(content, confirm) {
@@ -174,8 +183,8 @@ export class SpreadsheetRenderer extends Component {
   raiseError(body, callBack) {
     this.dialog.add(
       ConfirmationDialog,
-      {title: _t("Odoo Spreadsheet"), body},
-      {onClose: callBack}
+      { title: _t("Odoo Spreadsheet"), body },
+      { onClose: callBack }
     );
   }
 }
@@ -188,7 +197,7 @@ SpreadsheetRenderer.components = {
 };
 SpreadsheetRenderer.props = {
   record: Object,
-  res_id: {type: Number, optional: true},
+  res_id: { type: Number, optional: true },
   model: String,
-  importData: {type: Function, optional: true},
+  importData: { type: Function, optional: true },
 };
diff --git a/spreadsheet_oca/static/src/spreadsheet/graph_controller.esm.js b/spreadsheet_oca/static/src/spreadsheet/graph_controller.esm.js
index 3340bd7..e0de39d 100644
--- a/spreadsheet_oca/static/src/spreadsheet/graph_controller.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/graph_controller.esm.js
@@ -1,7 +1,7 @@
 /** @odoo-module **/
-import {GraphRenderer} from "@web/views/graph/graph_renderer";
+import { GraphRenderer } from "@web/views/graph/graph_renderer";
 
-import {patch} from "@web/core/utils/patch";
+import { patch } from "@web/core/utils/patch";
 
 patch(GraphRenderer.prototype, {
   onSpreadsheetButtonClicked() {
diff --git a/spreadsheet_oca/static/src/spreadsheet/list_controller.esm.js b/spreadsheet_oca/static/src/spreadsheet/list_controller.esm.js
index 86a5fc3..28a124f 100644
--- a/spreadsheet_oca/static/src/spreadsheet/list_controller.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/list_controller.esm.js
@@ -1,7 +1,7 @@
 /** @odoo-module **/
-import {ListController} from "@web/views/list/list_controller";
+import { ListController } from "@web/views/list/list_controller";
 
-import {patch} from "@web/core/utils/patch";
+import { patch } from "@web/core/utils/patch";
 
 patch(ListController.prototype, {
   onSpreadsheetButtonClicked() {
diff --git a/spreadsheet_oca/static/src/spreadsheet/list_controller.xml b/spreadsheet_oca/static/src/spreadsheet/list_controller.xml
index c6a3159..c4ec798 100644
--- a/spreadsheet_oca/static/src/spreadsheet/list_controller.xml
+++ b/spreadsheet_oca/static/src/spreadsheet/list_controller.xml
@@ -1,7 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <templates xml:space="preserve">
     <t t-inherit="web.ListView.Buttons" t-inherit-mode="extension" owl="1">
-        <xpath expr="//button[hasclass('o_list_button_discard')]/.." position="after">
+        <xpath
+      expr="//button[hasclass('o_list_button_discard')]/.."
+      position="after"
+    >
                 <t t-if="!env.isSmall">
                     <button
           type="button"
diff --git a/spreadsheet_oca/static/src/spreadsheet/list_renderer.esm.js b/spreadsheet_oca/static/src/spreadsheet/list_renderer.esm.js
index 05b535a..ace2b3e 100644
--- a/spreadsheet_oca/static/src/spreadsheet/list_renderer.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/list_renderer.esm.js
@@ -1,8 +1,8 @@
 /** @odoo-module **/
-import {useBus, useService} from "@web/core/utils/hooks";
-import {ListRenderer} from "@web/views/list/list_renderer";
-import {omit} from "@web/core/utils/objects";
-import {patch} from "@web/core/utils/patch";
+import { useBus, useService } from "@web/core/utils/hooks";
+import { ListRenderer } from "@web/views/list/list_renderer";
+import { omit } from "@web/core/utils/objects";
+import { patch } from "@web/core/utils/patch";
 
 patch(ListRenderer.prototype, {
   setup() {
@@ -33,7 +33,10 @@ patch(ListRenderer.prototype, {
               model: model.resModel,
               domain: model.domain,
               orderBy: model.orderBy,
-              context: omit(model.context, ...Object.keys(this.userService.context)),
+              context: omit(
+                model.context,
+                ...Object.keys(this.userService.context)
+              ),
               columns: this.getSpreadsheetColumns(),
               fields: model.fields,
               name: this.env.config.getDisplayName(),
@@ -50,6 +53,6 @@ patch(ListRenderer.prototype, {
         (col) => col.type === "field" && fields[col.name].type !== "binary"
         // We want to avoid binary fields
       )
-      .map((col) => ({name: col.name, type: fields[col.name].type}));
+      .map((col) => ({ name: col.name, type: fields[col.name].type }));
   },
 });
diff --git a/spreadsheet_oca/static/src/spreadsheet/pivot_controller.esm.js b/spreadsheet_oca/static/src/spreadsheet/pivot_controller.esm.js
index 02e8407..2d43518 100644
--- a/spreadsheet_oca/static/src/spreadsheet/pivot_controller.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/pivot_controller.esm.js
@@ -1,8 +1,8 @@
 /** @odoo-module **/
 
-import {PivotRenderer} from "@web/views/pivot/pivot_renderer";
-import {_lt} from "@web/core/l10n/translation";
-import {patch} from "@web/core/utils/patch";
+import { PivotRenderer } from "@web/views/pivot/pivot_renderer";
+import { _lt } from "@web/core/l10n/translation";
+import { patch } from "@web/core/utils/patch";
 
 patch(PivotRenderer.prototype, {
   isComparingInfo() {
diff --git a/spreadsheet_oca/static/src/spreadsheet/spreadsheet_action.esm.js b/spreadsheet_oca/static/src/spreadsheet/spreadsheet_action.esm.js
index 73bbced..aa0d420 100644
--- a/spreadsheet_oca/static/src/spreadsheet/spreadsheet_action.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/spreadsheet_action.esm.js
@@ -1,12 +1,16 @@
 /** @odoo-module **/
 
-import {loadSpreadsheetAction} from "@spreadsheet/assets_backend/spreadsheet_action_loader";
-import {registry} from "@web/core/registry";
+import { loadSpreadsheetAction } from "@spreadsheet/assets_backend/spreadsheet_action_loader";
+import { registry } from "@web/core/registry";
 
 const actionRegistry = registry.category("actions");
 
 const loadSpreadsheetActionOca = async (env, context) => {
-  await loadSpreadsheetAction(env, "action_spreadsheet_oca", loadSpreadsheetActionOca);
+  await loadSpreadsheetAction(
+    env,
+    "action_spreadsheet_oca",
+    loadSpreadsheetActionOca
+  );
   return {
     ...context,
     target: "current",
diff --git a/spreadsheet_oca/static/src/spreadsheet/utils/dynamic_generators.esm.js b/spreadsheet_oca/static/src/spreadsheet/utils/dynamic_generators.esm.js
index 84e8d8a..4ad37d7 100644
--- a/spreadsheet_oca/static/src/spreadsheet/utils/dynamic_generators.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet/utils/dynamic_generators.esm.js
@@ -83,7 +83,9 @@ export function makeDynamicCols(fields, number_of_cols, measures) {
       fields: fields?.length
         ? fields.map((f) => (f.startsWith("#") ? f : `#${f}`))
         : [],
-      values: fields?.length ? Array(fields.length).fill(colNum.toString()) : [],
+      values: fields?.length
+        ? Array(fields.length).fill(colNum.toString())
+        : [],
       width: 1,
       offset: fields?.length || 1,
     };
diff --git a/spreadsheet_oca/static/src/spreadsheet_tree/spreadsheet_tree_view.esm.js b/spreadsheet_oca/static/src/spreadsheet_tree/spreadsheet_tree_view.esm.js
index 7ad2658..0b9d6b3 100644
--- a/spreadsheet_oca/static/src/spreadsheet_tree/spreadsheet_tree_view.esm.js
+++ b/spreadsheet_oca/static/src/spreadsheet_tree/spreadsheet_tree_view.esm.js
@@ -1,13 +1,13 @@
 /** @odoo-module **/
 
-import {Component} from "@odoo/owl";
-import {FileUploader} from "@web/views/fields/file_handler";
-import {ListController} from "@web/views/list/list_controller";
-import {_t} from "@web/core/l10n/translation";
-import {listView} from "@web/views/list/list_view";
-import {registry} from "@web/core/registry";
-import {standardWidgetProps} from "@web/views/widgets/standard_widget_props";
-import {useService} from "@web/core/utils/hooks";
+import { Component } from "@odoo/owl";
+import { FileUploader } from "@web/views/fields/file_handler";
+import { ListController } from "@web/views/list/list_controller";
+import { _t } from "@web/core/l10n/translation";
+import { listView } from "@web/views/list/list_view";
+import { registry } from "@web/core/registry";
+import { standardWidgetProps } from "@web/views/widgets/standard_widget_props";
+import { useService } from "@web/core/utils/hooks";
 
 class SpreadsheetFileUploader extends Component {
   setup() {
@@ -33,7 +33,7 @@ class SpreadsheetFileUploader extends Component {
         "spreadsheet.spreadsheet",
         "create_document_from_attachment",
         ["", this.attachmentIdsToProcess],
-        {context: this.env.searchModel.context}
+        { context: this.env.searchModel.context }
       );
     } finally {
       // Ensures attachments are cleared on success as well as on error
@@ -58,11 +58,11 @@ SpreadsheetFileUploader.components = {
 SpreadsheetFileUploader.template = "spreadsheet_oca.SpreadsheetFileUploader";
 SpreadsheetFileUploader.props = {
   ...standardWidgetProps,
-  acceptedFileExtensions: {type: String, optional: true},
-  record: {type: Object, optional: true},
-  togglerTemplate: {type: String, optional: true},
-  slots: {type: Object, optional: true},
-  linkText: {type: String, optional: true},
+  acceptedFileExtensions: { type: String, optional: true },
+  record: { type: Object, optional: true },
+  togglerTemplate: { type: String, optional: true },
+  slots: { type: Object, optional: true },
+  linkText: { type: String, optional: true },
 };
 SpreadsheetFileUploader.defaultProps = {
   acceptedFileExtensions:
diff --git a/spreadsheet_oca/views/spreadsheet_spreadsheet.xml b/spreadsheet_oca/views/spreadsheet_spreadsheet.xml
index f9e72d2..5657169 100644
--- a/spreadsheet_oca/views/spreadsheet_spreadsheet.xml
+++ b/spreadsheet_oca/views/spreadsheet_spreadsheet.xml
@@ -4,7 +4,9 @@
 <odoo>
 
     <record model="ir.ui.view" id="spreadsheet_spreadsheet_search_view">
-        <field name="name">spreadsheet.spreadsheet.search (in spreadsheet_oca)</field>
+        <field
+      name="name"
+    >spreadsheet.spreadsheet.search (in spreadsheet_oca)</field>
         <field name="model">spreadsheet.spreadsheet</field>
         <field name="arch" type="xml">
             <search>
@@ -14,7 +16,9 @@
     </record>
 
     <record model="ir.ui.view" id="spreadsheet_spreadsheet_tree_view">
-        <field name="name">spreadsheet.spreadsheet.tree (in spreadsheet_oca)</field>
+        <field
+      name="name"
+    >spreadsheet.spreadsheet.tree (in spreadsheet_oca)</field>
         <field name="model">spreadsheet.spreadsheet</field>
         <field name="arch" type="xml">
             <tree js_class="spreadsheet_tree">
@@ -31,13 +35,19 @@
     </record>
 
     <record model="ir.ui.view" id="spreadsheet_spreadsheet_form_view">
-        <field name="name">spreadsheet.spreadsheet.tree (in spreadsheet_oca)</field>
+        <field
+      name="name"
+    >spreadsheet.spreadsheet.tree (in spreadsheet_oca)</field>
         <field name="model">spreadsheet.spreadsheet</field>
         <field name="arch" type="xml">
             <form>
                 <header />
                 <sheet>
-                    <div name="button_box" id="button_box" class="oe_button_box">
+                    <div
+            name="button_box"
+            id="button_box"
+            class="oe_button_box"
+          >
                         <button
               name="open_spreadsheet"
               type="object"
@@ -57,7 +67,10 @@
               />
                         </group>
                         <group string="Write Access">
-                            <field name="contributor_ids" widget="many2many_tags" />
+                            <field
+                name="contributor_ids"
+                widget="many2many_tags"
+              />
                             <field
                 name="contributor_group_ids"
                 widget="many2many_tags"
@@ -65,7 +78,10 @@
                         </group>
                         <group string="Read Access">
                             <field name="reader_ids" widget="many2many_tags" />
-                            <field name="reader_group_ids" widget="many2many_tags" />
+                            <field
+                name="reader_group_ids"
+                widget="many2many_tags"
+              />
                         </group>
                         <group colspan="4">
                             <field
@@ -81,7 +97,10 @@
         </field>
     </record>
 
-    <record model="ir.actions.act_window" id="spreadsheet_spreadsheet_act_window">
+    <record
+    model="ir.actions.act_window"
+    id="spreadsheet_spreadsheet_act_window"
+  >
         <field name="name">Spreadsheets</field>
         <field name="res_model">spreadsheet.spreadsheet</field>
         <field name="view_mode">tree,form</field>
@@ -92,8 +111,13 @@
     <record model="ir.ui.menu" id="spreadsheet_spreadsheet_menu">
         <field name="name">Spreadsheets</field>
         <field name="action" ref="spreadsheet_spreadsheet_act_window" />
-        <field name="web_icon">spreadsheet_oca,static/description/icon.png</field>
-        <field name="groups_id" eval="[(4, ref('spreadsheet_oca.group_user'))]" />
+        <field
+      name="web_icon"
+    >spreadsheet_oca,static/description/icon.png</field>
+        <field
+      name="groups_id"
+      eval="[(4, ref('spreadsheet_oca.group_user'))]"
+    />
         <field name="sequence" eval="16" />
     </record>
 
diff --git a/spreadsheet_oca/wizards/spreadsheet_select_row_number.xml b/spreadsheet_oca/wizards/spreadsheet_select_row_number.xml
index 165660b..8c1d060 100644
--- a/spreadsheet_oca/wizards/spreadsheet_select_row_number.xml
+++ b/spreadsheet_oca/wizards/spreadsheet_select_row_number.xml
@@ -9,13 +9,19 @@
                 <sheet>
                     <group>
                         <field name="dynamic_rows" />
-                        <field name="number_of_rows" invisible='not dynamic_rows' />
+                        <field
+              name="number_of_rows"
+              invisible='not dynamic_rows'
+            />
                         <field name="can_have_dynamic_cols" invisible="1" />
                         <field
               name="dynamic_cols"
               invisible='not can_have_dynamic_cols'
             />
-                        <field name="number_of_cols" invisible='not dynamic_cols' />
+                        <field
+              name="number_of_cols"
+              invisible='not dynamic_cols'
+            />
                     </group>
                 </sheet>
             </form>
diff --git a/spreadsheet_oca/wizards/spreadsheet_spreadsheet_import.xml b/spreadsheet_oca/wizards/spreadsheet_spreadsheet_import.xml
index 5078dc4..1f4fdf9 100644
--- a/spreadsheet_oca/wizards/spreadsheet_spreadsheet_import.xml
+++ b/spreadsheet_oca/wizards/spreadsheet_spreadsheet_import.xml
@@ -61,7 +61,11 @@
             class="btn-primary"
             type="object"
           />
-                    <button string="Cancel" class="btn-default" special="cancel" />
+                    <button
+            string="Cancel"
+            class="btn-default"
+            special="cancel"
+          />
                 </footer>
             </form>
         </field>

@pedrobaeza
Copy link
Member

@rrebollo I can assure you that those changes done by your pre-commit are not needed. Something weird is in your side that are formatting files other way. Please rollback that and let the GitHub CI to mark the failures.

@rrebollo
Copy link
Author

rrebollo commented Dec 1, 2025

@pedrobaeza the problem is after the first commit in this PR my local pre-commit passed all green. The trace I just posted is an extract from OCA github CI/CD. So if I rollback the pre-commit test will simply not pass here. Would that be ok for you? From time to time I have my issues with local pre-commit but not often. I work with doodba-copier-template (from your company) as base project. Linux Mint 22.2 (ubuntu noble based). pre-commit through pipx over python 3.11.8 with nvm 24.

@pedrobaeza
Copy link
Member

It's not possible that all that changes are not included previously in the repository. Something is not working right if so... Please restrict the PR to the change you want to do and let's see the CI error.

@rrebollo
Copy link
Author

rrebollo commented Dec 1, 2025

@pedrobaeza I reverted the last commit, so now you can see the failing pre-commit test although local pre-commit:

image

@pedrobaeza
Copy link
Member

I still see 24 files changes, so it doesn't seem correct.

@pedrobaeza pedrobaeza added this to the 17.0 milestone Dec 1, 2025
@pedrobaeza
Copy link
Member

I think the mistake is in the other commit.

@rrebollo rrebollo force-pushed the 17.0-fix-spreadsheet_oca-missing-env-raiseError-function branch 3 times, most recently from 188e2bd to 022ff50 Compare December 1, 2025 21:49
@rrebollo rrebollo force-pushed the 17.0-fix-spreadsheet_oca-missing-env-raiseError-function branch 3 times, most recently from 137b659 to 87c0136 Compare December 3, 2025 03:07
@rrebollo
Copy link
Author

rrebollo commented Dec 3, 2025

@pedrobaeza,

The changes have been pushed to this PR.


Workaround & Local Hook Status

I am still facing failures with the local pre-commit hooks.

  • Workaround: To ensure CI passes, I had to manually skip the prettier hook and apply the required formatting directly to the added code.
  • Local Environment Context: For troubleshooting purposes, note that my local pre-commit installation is managed via pipx using Python 3.11.8 (as 3.12 was causing errors). This version is older than the one used in the GitHub CI environment.

I am continuing to investigate the underlying cause of the local hook failures.


I will let you know once I have found a solution. Thanks for your guidance and patience.

@rrebollo
Copy link
Author

rrebollo commented Dec 3, 2025

@pedrobaeza,

Following up on my previous update:

Configuration Context Finding

I find it noteworthy that the majority of the OCA repositories in branch 17.0 (e.g., stock-logistics-workflow) contain a file .prettierrc.yml in the root directory, but this file is missing in the spreadsheet repository.

  • I tested this by manually adding the configuration file, but it did not resolve the underlying local hook failure (which still required manual skipping).
  • I am simply providing this as a notable configuration difference that may be relevant to the hook's execution environment.

Reference example of the missing file:
https://github.com/OCA/stock-logistics-workflow/raw/refs/heads/17.0/.prettierrc.yml

I am continuing to investigate the cause of the local hook failures.

Copy link
Contributor

@chrisandrewmann chrisandrewmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me now

@pedrobaeza
Copy link
Member

@etobella do you consider this bugfix correct? In a first sight, it seems a bit weird to provide on own error class.

Copy link
Member

@etobella etobella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After testing it locally, I made the following:

1- Merge 2 cells
2- Copy 2 other cells
3- Paste on the merged cell.

Locally we receive:

image

With the PR:

image

So the result is as expected.

Also, After reviewing o_spreadsheet code from odoo, they added a env.raiseError, but never defined it.

@rrebollo rrebollo force-pushed the 17.0-fix-spreadsheet_oca-missing-env-raiseError-function branch from 87c0136 to 42ecd6a Compare December 5, 2025 14:47
Copy link
Member

@etobella etobella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@pedrobaeza
Copy link
Member

Please fw-port it to 18 if applicable.

/ocabot merge patch

@OCA-git-bot
Copy link
Contributor

This PR looks fantastic, let's merge it!
Prepared branch 17.0-ocabot-merge-pr-86-by-pedrobaeza-bump-patch, awaiting test results.

@OCA-git-bot OCA-git-bot merged commit 4721aed into OCA:17.0 Dec 5, 2025
7 checks passed
@OCA-git-bot
Copy link
Contributor

Congratulations, your PR was merged at ea7b874. Thanks a lot for contributing to OCA. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants