Nama ERP DocsNama ERP Docs
Home
Namasoft.com
Data Model
GitHub
Home
Namasoft.com
Data Model
GitHub
  • Home

    • Search
    • Guides

      • بعض المعلومات عن استعمال هذا الموقع
      • Utility Links
      • System Minimum Requirements
      • Nama ERP Installation Guide
      • Troubleshooting System Hanging or Unresponsiveness
      • Jasper Reports Complete Guide for Nama ERP
      • Keyboard Shortcuts
      • Layout Names:
      • List Views
      • Approvals System - Approval Definition Full Guide
      • Entity Flows
      • دليل استخدام أداة إنشاء التقارير ونماذج الطباعة
      • BI Module — Dashboards & Analytics
      • Nama ERP BI Module — Technical Reference
      • Virtual Entities — Reusable SQL Building Blocks for Reports & Dashboards
      • الفواتير والضرائب والخصومات
      • Supply Chain
      • Manufacturing
      • Tempo Language Manual
      • Sending Invoices and Documents to Customers
      • SMS and WhatsApp Configuration in Nama ERP
      • Two-Factor Authentication (2FA) Guide
      • Field Filter with Criteria
      • تعديل الترجمات في نظام نما
      • Criteria Based Validation
      • صيغ الحضور والانصراف
      • الربط مع ماكينات الحضور والانصراف
      • Nama ERP Notification System
      • Scheduled Tasks (Task Scheduler)
      • Nama Properties
      • تطبيق الهواتف المحمولة
      • Mobile QR Integrator Guide
      • أعدادات الحقول و الشاشات - Generic Reference Overrider User Guide
      • ReportWizard User Documentation (أداة إنشاء تقرير)
      • ORACLE JDBC Integration Connection in context.xml for integration purposes
      • Nama ERP REST API
      • Criteria from Text Parser (Text Criteria Guide)
      • ضوابط إنشاء طلبات تطوير من قبل أقسام الدعم الفني والتجهيز بالشركة
      • e-commerce integration (Magento)
      • .
    • Examples
    • Reprocessing Transactions
    • Frequently Asked Questions
    • AI Generated Entity Flows Documentation

      • Core
      • Accounting Module
      • AI Module
      • Contracting Module
      • CRM Module
      • EGTax Reader Module
      • Freight Management System Module
      • Hospital Management System Module
      • HR Module
      • e-commerce Integration Module
      • Manufacturing Module
      • POS Module
      • Real Estate Module
      • Service Center Module
      • Supply Chain Module
      • .
    • Release Notes

      • 2016
      • 2017
      • 2018
      • 2019
      • 2020
      • 2021
      • 2022
      • 2025
      • .
    • Video Tutorials

      • Supply Chain Videos
      • Report Wizard Videos
      • Human Resources Videos
      • .

BI Reference — Wizard Mode

Companion to bi-module-technical-reference.md. Load this only when authoring a widget whose wizardDataSource is set.

When a widget has a wizardDataSource, its chartConfigJSON references wizard field IDs instead of raw SQL column names. The backend resolves each ID to a SQL alias from cached metadata; SQL-mode widgets are unaffected by anything here.

1. Metadata caching

When a DashBoardWidgetWizard is saved, its postCommitAction runs ReportWizardQuery.build() once and stores per-field metadata in each line's (system) fieldMetadata JSON:

  • fieldId — wizard field property path
  • chartUsage — Dimension | Measure
  • paramType — Reference, Decimal, Text, Date, Integer, Genericreference, Enum, Boolean
  • referencedEntityType — reference fields only
  • aggregation — None, Sum, Count, Average, Min, Max
  • displayAlias — the SQL alias for the field's primary display column
  • subColumns — reference fields only: aliases of auto-expanded id/code/name1/name2/entityType/value sub-columns
  • sqlLeftHandSide — fully-qualified LHS used for cross-filter WHERE injection
  • arabicTitle / englishTitle — pass-through

Render-time lookup deserializes the cached records — no ReportWizardQuery rebuild.

2. Data-mapping keys

For every column slot in §3 of the main reference, wizard mode adds a *WizardFieldId sibling:

SQL keyWizard siblingResolves to
categoryColumncategoryWizardFieldIddisplayAlias
labelColumnlabelWizardFieldIdsame
valueColumnvalueWizardFieldIdsame
xColumn / yColumnxWizardFieldId / yWizardFieldIdsame
sizeColumnsizeWizardFieldIdScatter bubble size
innerLabelColumn / outerLabelColumninnerLabelWizardFieldId / outerLabelWizardFieldIdNestedLabelValue rings
innerValueColumn / outerValueColumninnerValueWizardFieldId / outerValueWizardFieldIdNestedLabelValue measures
leftValueColumn / rightValueColumnleftValueWizardFieldId / rightValueWizardFieldIdFunnelComparison
series[].columnseries[].wizardFieldIdsame
maxResultsRankBymaxResultsRankByWizardFieldIdtop-N ranking measure

Both keys present → *Column wins. Tempo / period-comparison columns are not wizard fields; use *Column only — wizardFieldId is silently ignored.

"dataMapping": {
  "type": "CategoryLabelValue",
  "categoryWizardFieldId": "invoice.valueDate",
  "labelWizardFieldId": "customer.customerCategory",
  "valueWizardFieldId": "price.netValue",
  "seriesType": "bar"
}

3. Click-emit & drill-down with wizardFieldId

"clickEmitMapping": [
  { "crossFilterCode": "customerCategoryFilter", "wizardFieldId": "customer.customerCategory" }
]

For each entry with a wizardFieldId:

  1. Sub-column inference — backend fills missing idColumn/codeColumn/name1Column/name2Column/entityTypeColumn/valueColumn/entityType from the cached subColumns + referencedEntityType.
  2. Per-dimension filtering — entry only fires when its wizardFieldId is one of the chart's currently-active dimensions (see §4 below).

Entries without wizardFieldId are always-active (legacy SQL-mode behavior).

4. Active dimensions

The "currently active dimensions" list, in order:

  1. If the request carries drillDownByTargetDimension, that field ID is first.
  2. Then categoryWizardFieldId, labelWizardFieldId, xWizardFieldId, yWizardFieldId — whichever are set in dataMapping.

Duplicates skipped. This list drives:

  • SQL rebuild via ReportWizardQuery.buildForDrillDown(wizard, primary, otherDims). Primary becomes first GROUP BY; others are appended; measures stay.
  • Click/drill filtering (§3 above).
  • Drill-by menu exclusion — already-active dimensions are hidden from the right-click "Drill Down By" menu.

5. Drill-by semantics (Option A)

When user right-clicks → "Drill Down By X":

  1. Category is replaced — drilled dimension takes the primary slot.
  2. Other active dimensions (label, x, y) stay — chart shape preserved.
  3. Drill stack accumulates one entry per drill: (categoryFieldId, clickedValue). Label's clicked value is not added.
  4. Filters accumulate (after two drills: WHERE month='Jan' AND region='West').

Drill menu = wizard.fields filtered to chartUsageType=Dimension AND not in active list AND not in drill stack.

Once drilled, server reads existing chartConfigJSON and surgically overrides dataMapping.categoryColumn with the drilled dimension's displayAlias (and removes categoryWizardFieldId). Everything else — echartOption, valueColumn/valueWizardFieldId, series styling, colors, mappings — is carried through untouched.

6. Cross-filter SQL LHS

A wizard widget's cross-filter LHS (on the binding or on the BICrossFilter) accepts a wizard field path in addition to raw alias.column. Any field reachable from the wizard's main entity works — it doesn't need to be displayed.

Valid LHS values:

  • customer — reference field on main entity. Binds against the referenced ID automatically.
  • customer.salesman.code — property path through two joins. Joins added as needed.
  • valueDate — scalar column on main entity.
  • l.branch_id — raw alias.column (legacy; still works).

The classifier treats two-or-more dots OR a value resolving against the main-table data model as a wizard path; otherwise raw SQL.

7. Coexistence with legacy widgets

Pre-existing wizard widgets (no *WizardFieldId keys, only *Column) read as before — column names, no per-dimension filtering. Re-saving via the chart designer upgrades the widget if the user picks field IDs.

8. Complete example

{
  "echartOption": {
    "tooltip": {"trigger": "axis", "axisPointer": {"type": "shadow"}},
    "legend": {},
    "xAxis": {"type": "category", "data": "$DATA.categories"},
    "yAxis": {"type": "value"},
    "series": "$DATA.series"
  },
  "dataMapping": {
    "type": "CategoryLabelValue",
    "categoryWizardFieldId": "invoice.valueDate",
    "labelWizardFieldId": "customer.customerCategory",
    "valueWizardFieldId": "price.netValue",
    "seriesType": "bar",
    "stack": "total"
  },
  "clickEmitMapping": [
    { "crossFilterCode": "dateFromFilter",         "wizardFieldId": "invoice.valueDate" },
    { "crossFilterCode": "customerCategoryFilter", "wizardFieldId": "customer.customerCategory" }
  ],
  "drillDownMapping": [
    {
      "key": "categoryDetails",
      "wizardFieldId": "customer.customerCategory",
      "targetWidgetCode": "bi-category-details",
      "enTitle": "Category details", "arTitle": "تفاصيل التصنيف",
      "filters": [
        { "crossFilterCode": "customerCategoryFilter", "wizardFieldId": "customer.customerCategory" }
      ]
    }
  ]
}

Wizard:

{
  "code": "bi-sales-breakdown",
  "type": "EChartDataSource",
  "tableType": "DetailLine",
  "mainTable": "SalesInvoiceLine",
  "fields": [
    {"fieldId": "invoice.valueDate",         "chartUsageType": "Dimension"},
    {"fieldId": "customer.customerCategory", "chartUsageType": "Dimension"},
    {"fieldId": "price.netValue",            "chartUsageType": "Measure", "sqlAggregationType": "Sum"}
  ]
}

9. Runtime slot selection

Wizard widgets expose a runtime selector (toolbar / echarts toolbox icon) so viewers can swap the category dimension, change measures, or add series — session-only.

Mapping typeDimension slotsMeasure slotsMulti-measure series
CategoryValuecategoryWizardFieldIdseries[].wizardFieldId (N)Yes (flexible only)
LabelValuelabelWizardFieldIdvalueWizardFieldIdNo
CategoryLabelValuecategoryWizardFieldId, labelWizardFieldIdvalueWizardFieldIdNo
Scatter—xWizardFieldId, yWizardFieldId, sizeWizardFieldIdNo
HeatmapxWizardFieldId, yWizardFieldIdvalueWizardFieldIdNo
Gauge—valueWizardFieldIdNo
TreelabelWizardFieldIdvalueWizardFieldIdNo

Waterfall, NestedLabelValue, GaugeMulti, Radar, FunnelComparison, Custom, Raw → no runtime selector.

Flexible vs. fixed CategoryValue: a CategoryValue is "flexible" only when every series[] entry is uniform — same type, no yAxisIndex, no stack, no target. Dual-axis / combo bar+line / stacked / with-target charts are fixed: their multi-measure picker is hidden.

No selector in drill-by mode: when the request carries drillDownByTargetDimension, the server omits runtimeSelectorInfo.

Opt-out flags on chartConfigJSON:

  • disableRuntimeDimensionSelection: true — hides dimension pickers (keeps measures).
  • disableRuntimeMeasureSelection: true — hides measure pickers (keeps dimensions).

Setting both true hides the selector entirely.

Click/drill follow active dims: runtime slot changes reshape activeDimensionFieldIds, so click-emit and drill-down entries keyed by wizardFieldId automatically follow the new active dimensions.

AI guidance: prefer wizard-mode keys (*WizardFieldId) whenever wizardDataSource is present so widgets pick up the runtime selector for free.

Edit On github
Last Updated:: 5/10/26, 3:37 AM