# GB5 BI Platform: What This Is and Why

## In one paragraph

GB5 modules generate a lot of operational data — sales, receivables, production, attendance — but
until this platform existed, seeing that data as a chart, KPI, or pivot table on a dashboard meant
a developer hand-building a one-off widget against one specific table, every time. This engine
replaces that with a governed, reusable pattern: a small registry of **BI Catalogs** (datasets a
widget can query — a governed warehouse fact table, an existing GB5 report, or a legacy ad-hoc
query, see "Where data can come from" below), a set of **BI Views** (a saved, reusable
dimension/measure/widget-type definition over one catalog — pick once, reuse everywhere), one
query engine that knows how to aggregate any of them (`RunBIQuery`), and one rendering component
(`gb5-widget`) that turns any query result into a KPI card, a chart, a flat table, or a full
Excel-style pivot table — automatically picking the right shape, or rendering whichever one a
saved BI View specifies. An admin picks a catalog, picks or authors a BI View, and the same engine
and widget shell work for every catalog that gets registered, today and in the future — nobody
writes a new widget per report.

## Vision

Every GB5 module already knows how to *store* its own data correctly. What it has never had is a
single, consistent way to let a non-developer turn that data into something visual — without
someone writing bespoke chart-binding code for each one-off ask. The BI Platform's job is to be
that single way: one governed catalog format, one query contract, one widget shell, reusable
across every module, every client, and every kind of visual (number, chart, table, pivot) —
built once, configured per-need, not rebuilt per-request.

## Why it's called "BI," not "Analysis"

An earlier pass at this engine used "Analysis"-branded names (`MANALYSISCATALOG`,
`RunAnalysisQuery`) — which turned out to collide, in name only, with a completely different,
pre-existing GB5 feature: `MANALYSIS`/`MANALYSISQUERY`, an unrelated ad-hoc drag-and-drop query
designer that has nothing to do with this engine (see "Where data can come from," source #3,
below, for how the two now actually connect). To stop that confusion before real client content
depended on the old names, this engine's own tables and routes were renamed to "BI"
(`MBICATALOG`, `MBIFIELDMAPPING`, new `MBIVIEW`, `/BI/*` routes) — the accurate name for what's
actually been built: a dimensional catalog, dataset governance, chart/pivot/table rendering, and
dashboard integration. The code module folder (`GB5Solution/Analytics/`, this doc set's own
folder) deliberately kept its original name — only the customer/developer-facing naming layer
changed.

## Why "governed," and why that matters

A BI Catalog isn't just "point at a table." Where a catalog resolves to a governed warehouse fact,
each of its measures is classified by **additivity** — whether it's safe to sum a measure across
time/dimensions (a sales value is), safe only within limits (a point-in-time balance is
"semi-additive" — you can sum it across accounts but not across days), or never safe to sum
client-side at all (an average is "non-additive"). This classification is what lets `gb5-widget`'s
KPI card and pivot-table adapter safely refuse to silently sum a balance into a meaningless
number, instead of trusting whoever built the dashboard widget to know that rule by hand. The same
discipline now also applies to catalogs built from an existing report or service: a field-mapping
registry (with the same additivity classification) governs what's queryable and how it aggregates,
reviewed and saved by an admin rather than silently trusted from raw response data.

## Where data can come from (a BI Catalog's three sources)

1. **Warehouse** — a governed Kimball-style fact table (`MWAREHOUSEFACT`/`MWAREHOUSEMEASURE`),
   registered once via migration, with every measure pre-classified for additivity. The most
   performant, most governed source; registering a brand-new fact table is still a
   developer/migration task, not a screen, today.
2. **ApiService** — **any existing GB5 report or service**, turned into a BI Catalog without
   touching that report at all. An admin picks an existing report, the platform samples one real
   call to it and suggests field mappings (which fields look like dimensions, which look like
   measures, and a conservative default aggregation), the admin reviews and saves them. This is
   the bridge that makes "visualize this report I already have" possible without a
   developer — see the Admin Config Guide's field-mapping section.
3. **AnalysisQuery** — a bridge into the separate, pre-existing ad-hoc query designer
   (`MANALYSISQUERY`, the "Where it's called BI, not Analysis" system above): an already-defined
   ad-hoc query's own field/aggregation setup is read and reused as a BI Catalog's dimension/measure
   picker, so work already done in that designer doesn't need to be redone here.

One structural exclusion, by design: a legacy report whose columns are computed at run time (a
"pivoted" report view, `ISDATAPIVOT=1`) can never back a BI Catalog — there's no stable field list
to register mappings against. This is caught and explained clearly at catalog-creation time, not
discovered later as a mysterious failure.

## What a BI View is, and why it's separate from where it's placed

A **BI View** is a saved definition — which dimensions, which measures, which widget type (KPI
card / chart / table / pivot table), and for a pivot, which fields start on the row axis vs. the
column axis. It's independent of any one dashboard placement (mirroring how GB5's existing
`MREPORT`/`MREPORTVIEW` separates a report from its views) — the same saved BI View can be reused
across more than one dashboard portlet, and a single catalog can back many different BI Views (a
KPI headline number and a full pivot breakdown, both over the same underlying dataset).

## What's already built

See [Analytics_Catalog.md](Analytics_Catalog.md) for full detail and exact verification status per
capability. In short, as of 2026-08-07:

- **BI Catalog registry, dataset resolution, and query engine** (`MBICATALOG`, `IDatasetResolver`,
  `RunBIQuery`) — all three source kinds above are real and wired up (Warehouse and ApiService
  live-verified with real data on GB5DEMO; AnalysisQuery-kind is code-complete, not yet live-tested
  against a real ad-hoc query).
- **BI Views** (`MBIVIEW`) — save a multi-dimension, multi-measure, any-widget-type definition
  once, point any number of dashboard portlets at it. Live-verified end-to-end on GB5DEMO
  (author → save → fetch → list → delete, including the cache-invalidation path).
- **Generalized field-mapping** — turn any existing GB5 report into a BI Catalog
  (`CreateBICatalogFromReportView`), with a live-sample auto-suggest step
  (`SuggestBIFieldMappings`) so an admin reviews and edits a draft instead of typing field metadata
  from scratch. Live-verified against both a clean fixture and a real, legacy-service-backed
  report (which is correctly and clearly rejected — see the Catalog entry for why).
- **Four widget types, one shell** — `gb5-widget` renders a KPI card, an ApexCharts chart, a flat
  table, or a full pivot table (via WebDataRocks — genuine Excel-style row/column crosstab,
  drag-and-drop rearrangement, subtotals) from the exact same query contract, auto-picking a shape
  from the data unless a BI View's own `WidgetType` forces one.
- **Design vs. run modes for the pivot table** — the WebDataRocks toolbar shows only
  export/fullscreen/fields controls when a saved view is being consumed on a dashboard ("run"
  mode), and adds layout/format authoring controls plus a "Save current layout" action when an
  admin is designing a view — never local-file connect/open/save controls, which never fit a
  server-driven system.
- **Type-level governance** — a Portlet Type can declare which widget types it supports
  (`SupportedWidgetTypes`); the config screen filters its own pickers by it. Declarative today
  (client-side filter), not yet a hard server-side gate — see the Developer Playbook for why.
- **The Portlet config screen** — an admin can create a new BI-backed portlet by picking a catalog,
  picking or authoring a BI View (multi-dimension, multi-measure, any widget type), reviewing
  field mappings, seeing a live preview, and saving — no raw API calls, no SQL, no developer needed
  for a routine "show me this measure by this dimension, as a pivot" ask.

## What's next

- **Filter support** — the config screen and query engine still don't let you narrow a widget to
  "this year only" or "this OU only." The query definition already has a `Filters` field; nothing
  reads it yet on the query-engine side.
- **Direct `Menu → BI View` access** — today a BI View is only reachable via
  `Menu → Dashboard → Page → Portlet`. A direct menu entry (bypassing the dashboard/portlet
  layer), likely alongside report-like common facilities such as export and scheduling, is a
  named future need, not yet scoped.
- **Live browser/pixel verification of the pivot table's toolbar-mode split and layout-save
  round-trip** — proven correct at the code level (`tsc --noEmit` clean, targeted unit tests
  asserting exactly which toolbar tabs survive each mode's filter), but not yet click-through
  confirmed in a real browser — blocked by this environment's dev-server memory ceiling, a known,
  pre-existing limitation unrelated to this feature's own code.
- **A screen for turning an existing report into a catalog** — the backend
  (`CreateBICatalogFromReportView`) is live-verified; nothing on the config screen calls it yet, so
  today this source is reachable via direct API call, not yet a button in the UI.
- Snapshots, AI-generated insights, sharing/permissions, alerting, and drill-through lineage were
  named as a longer-term "full BI platform" direction during this rebrand but are explicitly **not**
  scoped or started — each is its own future project.

## How to read the rest of this document set

- If you want to know what a specific piece does and its exact verification status, go to
  [Analytics_Catalog.md](Analytics_Catalog.md).
- If you're setting up a BI-backed widget for a client, go to
  [Analytics_AdminConfigGuide.md](Analytics_AdminConfigGuide.md).
- If you're a developer extending this engine, go to
  [Analytics_DeveloperPlaybook.md](Analytics_DeveloperPlaybook.md).
