Skip to content

[MIG] spreadsheet_*: Migration from 18.0 to 19.0#113

Open
susaglam wants to merge 285 commits intoOCA:19.0from
susaglam:19.0
Open

[MIG] spreadsheet_*: Migration from 18.0 to 19.0#113
susaglam wants to merge 285 commits intoOCA:19.0from
susaglam:19.0

Conversation

@susaglam
Copy link
Copy Markdown

@susaglam susaglam commented Apr 16, 2026

Summary

Migrate all four OCA spreadsheet modules from 18.0 to 19.0, including
compatibility fixes discovered during CI validation and runtime testing.
The runtime pass uncovered two additional chart-side-panel crashes in
Odoo 19's o-spreadsheet; the fixes are included in this PR.

Modules migrated

  • spreadsheet_oca (18.0.1.3.0 → 19.0.1.0.0)
  • spreadsheet_dashboard_oca (18.0.1.1.0 → 19.0.1.0.0)
  • spreadsheet_dashboard_purchase_oca (18.0.1.0.0 → 19.0.1.0.0)
  • spreadsheet_dashboard_purchase_stock_oca (18.0.1.0.0 → 19.0.1.0.0)

Python changes

  • Remove "version": 1 from empty spreadsheet data in spreadsheet_abstract.py to match upstream spreadsheet.mixin behavior in Odoo 19

  • Remove loadSpreadsheetDependencies() import and call — Chart.js is now auto-included in spreadsheet.o_spreadsheet bundle via Odoo 19 manifest

  • Migrate _sql_constraints list format to models.Constraint() class attribute in spreadsheet_spreadsheet_tag.py

  • Migrate _() translations to self.env._() in all model files — the new Odoo 19 convention that closes over env context automatically (fixes pylint-odoo W8161 prefer-env-translation):

    • spreadsheet_dashboard_oca/models/spreadsheet_dashboard.py (2 call sites)
    • spreadsheet_oca/models/spreadsheet_abstract.py (1 call site)
    • spreadsheet_oca/models/spreadsheet_spreadsheet.py (1 call site)
    • Removed unused from odoo import _ imports
  • Wrap default=_get_default_color with a lambda in spreadsheet_spreadsheet_tag.py so the default method remains inheritable in subclasses (fixes pylint-odoo E8148 inheritable-method-lambda):

    default=lambda self: self._get_default_color()

JavaScript changes

Core asset & registry migration

  • Fix JS import path: @spreadsheet/assets_backend/helpers@spreadsheet/helpers/helpers (file relocated in Odoo 19)
  • Remove duplicate topbarMenuRegistry.add("file") — already registered by o-spreadsheet core library in Odoo 19
  • Remove duplicate topbarMenuRegistry.addChild("settings") — already registered by core
  • Use safe registry additions (try/catch with .replace() fallback) for chartSubtypeRegistry, chartSidePanelComponentRegistry, sidePanelRegistry, and pivotSidePanelRegistry to prevent "already present in this registry!" crashes

ListView template changes

  • Fix ListView button xpath: in Odoo 19 the web.ListView.Buttons template no longer wraps its children in a <div class="o_list_buttons"> — buttons are direct children of the template root. The old xpath caused an OWL crash (Element cannot be located in element tree) when opening the spreadsheet list view. Target the o_list_button_add button instead.
  • Fix ListView Upload button positioning: target control-panel-create-button slot directly instead of parent element (template structure changed in 19)

Chart side-panel API migration

Discovered at runtime after the module initially installed cleanly: clicking
any chart produced a JS crash that made the whole chart feature unusable.
Two coordinated o-spreadsheet API changes required fixes:

Component prop rename (figureIdchartId) — commit 2e17e44

o-spreadsheet 19.0 renamed the identifying prop on every chart-related
side-panel component:

Component Old prop New prop
ChartTypePicker figureId chartId
GenericChartConfigPanel figureId chartId
LineConfigPanel figureId chartId
BarConfigPanel figureId chartId
ScorecardChartConfigPanel figureId chartId
GaugeChartConfigPanel figureId chartId

New props contract:

static props = { chartId: String, definition, canUpdateChart, updateChart };

Our patches still read this.props.figureIdundefined
getChartDefinition(undefined) throws Chart with id undefined does not exist.
Fix: rename figureIdchartId in chart_panel.esm.js and
chart_panels.esm.js; rename internal helper getFigureDefinition
getChartDefinition; add defensive early-return for a briefly undefined
chartId during initial component mount.

Chart-menu link API rename — commit 4f51879

o-spreadsheet 19.0 restructured the chart → Odoo-menu link into a generic
typed-link API:

// OLD
env.model.getters.getChartOdooMenu(chartId)   // returns menu object
dispatch("LINK_ODOO_MENU_TO_CHART", { chartId, odooMenuId })

// NEW
env.model.getters.getChartOdooLink(chartId)   // returns OdooLink | undefined
// then:
env.model.getters.getIrMenu(link.odooMenuId)
dispatch("UPDATE_ODOO_LINK_TO_CHART", {
  chartId,
  odooLink: { type: "odooMenu", odooMenuId },
})

OdooLink shape (from addons/spreadsheet/static/src/chart/plugins/chart_odoo_link_plugin.js):

type OdooLink =
  | { type: "odooMenu";    odooMenuId: number | string }
  | { type: "dataSource";  dataSourceType: string; dataSourceCoreId: string }
  | undefined   // passing undefined as odooLink unlinks

Symptom before this fix: OWL lifecycle crash on any chart panel render —
TypeError: this.env.model.getters.getChartOdooMenu is not a function at
menuId getter. Fix: resolve via getChartOdooLink with type guard; dispatch
UPDATE_ODOO_LINK_TO_CHART with the typed payload; pass
odooLink: undefined to unlink.

XML / Security changes

  • Remove category_id field from res.groups records in security.xml (field removed in Odoo 19)
  • Remove users field from res.groups records in security.xml (field renamed to user_ids in Odoo 19)
  • Implement Odoo 19 privilege system: create res.groups.privilege record linked to ir.module.category so spreadsheet groups appear in user settings with selectable options (No Access / User / Manager)
  • Rename groups_idgroup_ids on ir.ui.menu records in spreadsheet_spreadsheet.xml (field renamed in Odoo 19)
  • Rename user.groups_iduser.group_ids in all domain rules in security.xml (field renamed in Odoo 19)

Dashboard data fixes

  • spreadsheet_dashboard_purchase_stock_oca/data/files/purchase_dashboard.json: replace date with scheduled_date for the stock.picking list. The date field was renamed to scheduled_date on stock.picking in Odoo 19. Affected:

    • list columns definition
    • list orderBy clause
    • 10 ODOO.LIST(3, *, "date") cell references on the Dashboard sheet

    Without this fix module install fails with:

    field 'date' used in spreadsheet 'Purchase' does not exist
    on model 'stock.picking'
    

Formatting / tooling

  • Prettier: reformat purchase_dashboard.json (compact arrays within printWidth, trailing newline) to pass OCA pre-commit
  • Prettier: multi-line sidePanelRegistry.add() / .replace() object literals in filter.esm.js and filter_panel_datasources.esm.js
  • Prettier: multi-line xpath attribute in list_controller.xml

No changes required

  • Asset bundle names (web.assets_backend, web.assets_backend_lazy) remain valid in Odoo 19.0
  • All Python models already use modern ORM patterns
  • All XML views already use invisible= and <list>
  • All JS code uses ES6/OWL patterns

Testing performed

All items below were manually tested on Odoo 19.0:

  • Install all four modules from a clean database without errors
  • Spreadsheet list / kanban / form views load correctly
  • Create a new spreadsheet and open without errors
  • Import a pivot table from pivot view
  • Import a list from list view (Upload button positioned correctly)
  • Import a graph from graph view
  • Global filters panel works
  • Download spreadsheet as XLSX
  • Purchase dashboard renders the stock.picking Transfers list (previously crashed because of date field)
  • User access control visible in Settings → Users with tiered dropdown (No Access / User / Manager)
  • No JS registry "already present" errors in browser console
  • Insert a chart into a spreadsheet — no Chart with id undefined error
  • Open Bar / Line / Scorecard / Gauge chart side panels — no OWL lifecycle error
  • Change chart type via the type picker — dispatch succeeds
  • Link an Odoo menu via the "Menu Items" dropdown — persists on reload
  • Unlink the menu (clear selection) — getChartOdooLink returns undefined

References

  • o-spreadsheet source, chart_type_picker.ts: static props = { chartId: String, chartPanelStore: Object }
  • o-spreadsheet source, common.ts: ChartSidePanelPropsObject declares chartId: String + updateChart, canUpdateChart, definition
  • Odoo saas-19.2 source, chart_odoo_link_plugin.js: defines the getChartOdooLink getter, UPDATE_ODOO_LINK_TO_CHART command, and OdooLink type (odooMenu | dataSource)

CI status

All 7 checks pass on the latest push:

Check Status
codecov/patch
codecov/project
pre-commit (prettier, eslint, pylint-odoo)
runboat/build
tests / Detect unreleased dependencies
tests / test with OCB
tests / test with Odoo

etobella and others added 30 commits September 24, 2025 14:08
Currently translated at 83.1% (69 of 83 strings)

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/nl/
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/
Currently translated at 100.0% (83 of 83 strings)

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/it/
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/
Currently translated at 100.0% (83 of 83 strings)

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/it/
commands

Steps:
1. Open spreadsheet
2. Press command Ctrl + Z
3. F5 (refresh browse)

An error occurred:
Operation undefined not found

Because missing key `undoneRevisionId` / `redoneRevisionId` in revisions
data

Solutions:
Save all spreadsheet message in commands field
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/
Currently translated at 100.0% (83 of 83 strings)

Translation: spreadsheet-16.0/spreadsheet-16.0-spreadsheet_oca
Translate-URL: https://translation.odoo-community.org/projects/spreadsheet-16-0/spreadsheet-16-0-spreadsheet_oca/it/
- Remove loadSpreadsheetDependencies import and call (Chart.js is now
  auto-included in spreadsheet.o_spreadsheet bundle via manifest)
- Remove "version": 1 from empty spreadsheet data to match upstream
  Odoo 19.0 spreadsheet.mixin behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@OCA-git-bot OCA-git-bot added mod:spreadsheet_dashboard_oca Module spreadsheet_dashboard_oca mod:spreadsheet_dashboard_purchase_stock_oca Module spreadsheet_dashboard_purchase_stock_oca mod:spreadsheet_oca Module spreadsheet_oca mod:spreadsheet_dashboard_purchase_oca Module spreadsheet_dashboard_purchase_oca series:19.0 labels Apr 16, 2026
@susaglam susaglam marked this pull request as draft April 16, 2026 10:39
susaglam and others added 8 commits April 16, 2026 12:58
- Remove category_id field from res.groups records (field removed in
  Odoo 19, replaced by privilege_id on res.groups.privilege)
- Update domain rules: user.groups_id → user.group_ids (field renamed
  in Odoo 19)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ir.ui.menu: groups_id → group_ids (field renamed in Odoo 19)
- _sql_constraints list → models.Constraint() (new format in Odoo 19)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 'users' field was removed from res.groups in Odoo 19. Admin users
get the group through implied_ids chain instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In Odoo 19, o-spreadsheet core already registers "file" and "settings"
in topbarMenuRegistry. Calling .add() with an existing key throws
"file is already present in this registry!". Remove the duplicate
registrations, keep only OCA-specific children (filters, save, download).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In Odoo 19, the "New" button's parent changed from a DOM element to
a <t t-set-slot="control-panel-create-button"> OWL slot. The old xpath
targeting the parent caused the button to render outside the control
panel. Updated xpath to target the button directly within the slot.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In Odoo 19, core spreadsheet registers chart subtypes and side panels
that OCA also registers. Registry.add() throws on duplicate keys.
Use try/catch with fallback to replace() for all registry additions
to safely handle both fresh installs and coexistence with core.

Affected registries: chartSubtypeRegistry, chartSidePanelComponentRegistry,
sidePanelRegistry, pivotSidePanelRegistry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Since category_id was removed from res.groups in Odoo 19, the
spreadsheet groups were not visible in Settings and not automatically
assigned to any user. Fix by adding implied_ids to base.group_user
so all internal users get spreadsheet access by default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the previous implied_ids workaround with the proper Odoo 19
privilege system:
- Create res.groups.privilege record linked to ir.module.category
- Link both User and Manager groups via privilege_id

This makes the groups visible in Settings → Users with selectable
options: No Access / User / Manager. Admins can control spreadsheet
access per user.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@susaglam susaglam changed the title 19.0 [MIG] spreadsheet_*: Migration from 18.0 to 19.0 Apr 16, 2026
@susaglam susaglam marked this pull request as ready for review April 16, 2026 12:27
In Odoo 19, the web.ListView.Buttons template no longer wraps its buttons
inside a <div class="o_list_buttons"> — they are now direct children of
the template root. The previous xpath looking for that div fails with
"Element cannot be located in element tree" causing an OWL crash when
opening the spreadsheet list view.

Fix: Position the Upload button after the "New" button (o_list_button_add)
instead, which is available at the root level in the new template.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@susaglam susaglam marked this pull request as draft April 17, 2026 09:03
@susaglam susaglam marked this pull request as ready for review April 17, 2026 09:10
@susaglam susaglam marked this pull request as draft April 17, 2026 09:14
susaglam and others added 2 commits April 17, 2026 11:16
1. spreadsheet_dashboard_purchase_stock_oca: Odoo 19+ stock.picking model
   no longer has a 'date' field — renamed to 'scheduled_date'. The purchase
   dashboard JSON referenced 'date' causing module install to fail:
       field 'date' used in spreadsheet 'Purchase' does not exist
       on model 'stock.picking'

   Updated list columns, orderBy and ODOO.LIST cell references.

2. spreadsheet_oca: prettier formatting for three files that pre-commit
   wanted multi-lined — side panel registrations and an xpath attribute.
   No functional change, purely style.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes reported by OCA pre-commit CI:

1. Prettier (JSON + JS + XML):
   - purchase_dashboard.json reformatted with compact arrays where they fit
     within printWidth, plus trailing newline.
   - filter.esm.js: sidePanelRegistry.add EditFilterPanel multi-lined.

2. Pylint-odoo W8161 (prefer-env-translation):
   Replace `_()` with `self.env._()` which is the new recommended pattern
   for translation in Odoo 19+ (closes over env context automatically).
   - spreadsheet_dashboard_oca/models/spreadsheet_dashboard.py: 2 sites
   - spreadsheet_oca/models/spreadsheet_abstract.py: 1 site
   - spreadsheet_oca/models/spreadsheet_spreadsheet.py: 1 site
   Removed unused `_` imports.

3. Pylint-odoo E8148 (inheritable-method-lambda):
   Wrap `default=_get_default_color` with a lambda to keep the method
   inheritable: `default=lambda self: self._get_default_color()`.
   - spreadsheet_oca/models/spreadsheet_spreadsheet_tag.py

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@susaglam susaglam marked this pull request as ready for review April 17, 2026 09:32
@legalsylvain legalsylvain marked this pull request as draft April 17, 2026 10:54
@susaglam susaglam marked this pull request as ready for review April 17, 2026 19:57
@sonasxo-art
Copy link
Copy Markdown

To Reproduce

Affected versions: Odoo 19.0 with spreadsheet_oca module (19.0 branch)

Steps to reproduce the behavior:

  1. Open Odoo 19.0
  2. Create or open a spreadsheet
  3. Add a chart to the spreadsheet
  4. Attempt to perform operations in the chart panel
  5. Click on interactive elements in the chart panel

Expected behavior
The chart should operate normally without errors.

Actual behavior

  • JavaScript error "Chart with id undefined does not exist" appears
  • Chart panel crashes and becomes unusable
  • The entire chart functionality is affected

Additional context

  • Operating System: Any
  • Odoo Version: 19.0
  • Branch: 19.0
  • Browser: Chrome
  • Date: 2026-04-20 06:51:00 GMT

Fixes runtime error "Chart with id undefined does not exist" when
interacting with chart panels in Odoo 19.0.

Root cause: o-spreadsheet 19.0 renamed the identifying prop on
ChartTypePicker and all config panels (GenericChartConfigPanel,
LineConfigPanel, BarConfigPanel, ScorecardChartConfigPanel,
GaugeChartConfigPanel) from `figureId` to `chartId`. The previous
patch still read `this.props.figureId`, which is undefined in 19.0,
causing getChartDefinition(undefined) to throw.

Changes in chart_panel.esm.js:
- Rename figureId variable & prop reference to chartId throughout
- Rename helper getFigureDefinition → getChartDefinition for clarity
- Add defensive early return when chartId is falsy in onTypeChange
  and filterCategoriesChartType to avoid crashes during initial mount

Changes in chart_panels.esm.js:
- Rename this.props.figureId to this.props.chartId in menuId getter
  and both LINK_ODOO_MENU_TO_CHART dispatch calls

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@susaglam
Copy link
Copy Markdown
Author

susaglam commented Apr 21, 2026

To Reproduce

Affected versions: Odoo 19.0 with spreadsheet_oca module (19.0 branch)

Steps to reproduce the behavior:

  1. Open Odoo 19.0
  2. Create or open a spreadsheet
  3. Add a chart to the spreadsheet
  4. Attempt to perform operations in the chart panel
  5. Click on interactive elements in the chart panel

Expected behavior The chart should operate normally without errors.

Actual behavior

  • JavaScript error "Chart with id undefined does not exist" appears
  • Chart panel crashes and becomes unusable
  • The entire chart functionality is affected

Additional context

  • Operating System: Any
  • Odoo Version: 19.0
  • Branch: 19.0
  • Browser: Chrome
  • Date: 2026-04-20 06:51:00 GMT

thanks for the report. Commit fixes it.

Root cause: o-spreadsheet 19.0 renamed the chart identifier prop from
figureId to chartId on ChartTypePicker and all config panels
(GenericChartConfigPanel, LineConfigPanel, BarConfigPanel,
ScorecardChartConfigPanel, GaugeChartConfigPanel). Our patches
still read this.props.figureIdundefinedgetChartDefinition(undefined) throws.

Fix:

  • this.props.figureIdthis.props.chartId in both chart_panel.esm.js
    and chart_panels.esm.js
  • Added if (!chartId) return super.onTypeChange(type) defensive guard
  • Renamed internal helper getFigureDefinitiongetChartDefinition for consistency

References:

  • ChartTypePicker.ts in o-spreadsheet core: static props = { chartId: String, chartPanelStore: Object }

Please pull and retest.

… API

Fixes OWL lifecycle crash when opening any chart side panel:
  TypeError: this.env.model.getters.getChartOdooMenu is not a function
    at get menuId (chart_panels.esm.js:41)

Discovered after the earlier figureId → chartId fix (commit b777caa /
2e17e44) let the panel render far enough to hit this second API change.

Root cause: Odoo 19+ / saas-19.2 restructured chart-link storage.

Getter rename:
  env.model.getters.getChartOdooMenu(chartId)  # returns menu obj
    → env.model.getters.getChartOdooLink(chartId)  # returns OdooLink | undefined

Command rename:
  dispatch("LINK_ODOO_MENU_TO_CHART", {chartId, odooMenuId})
    → dispatch("UPDATE_ODOO_LINK_TO_CHART", {chartId, odooLink})

OdooLink shape:
  { type: "odooMenu", odooMenuId: number | string }
  | { type: "dataSource", dataSourceType, dataSourceCoreId }
  | undefined  # for unlink

Changes:
- `menuId` getter: resolve via getChartOdooLink, check link.type ==
  "odooMenu", then getIrMenu(link.odooMenuId). Returns false if no link
  or link is a dataSource rather than a menu.
- `updateMenu(menuId)`: dispatch UPDATE_ODOO_LINK_TO_CHART with proper
  typed odooLink payload (or undefined to unlink).

Refs:
- Odoo saas-19.2 source: addons/spreadsheet/static/src/chart/plugins/chart_odoo_link_plugin.js

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mod:spreadsheet_dashboard_oca Module spreadsheet_dashboard_oca mod:spreadsheet_dashboard_purchase_oca Module spreadsheet_dashboard_purchase_oca mod:spreadsheet_dashboard_purchase_stock_oca Module spreadsheet_dashboard_purchase_stock_oca mod:spreadsheet_oca Module spreadsheet_oca series:19.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.