Skip to main content
ActivityDefinitions define how complex activities are collected and calculated. Each definition bundles an input schema, a calculation function, and a React UI component, and can be reused across forms and sites.

Quick Start

  1. Create a new ActivityDefinition (Customization → Activity Definitions → New)
  2. Define inputs (manually or via Smart CSV)
  3. Write calculation code (async function returning { value, metadata })
  4. Build the UI (ActivityUI calling onAddActivity(values))
  5. Preview with test context → Save
Minimal calculation template:
Minimal UI template:

What An ActivityDefinition Includes

  • Input schema: strict, typed inputs your UI must collect
  • Calculation code: async JS function that produces a value and metadata
  • UI code: a React component users interact with to provide inputs

Input Schema

Inputs are defined with a compact schema used throughout the app (validation, UI scaffolding, CSV import hints):
Allowed types: "number" | "string". Each input has name, type, required, and an optional example.

Input Naming Guide

  • Use camelCase keys (e.g., fuelType, electricityKwh).
  • Avoid spaces/special characters. CSV Smart mode auto-cleans headers to camelCase.
  • Keep names stable; export columns use these names.
  • Provide example values to improve CSV detection and preview fidelity.

Calculation Code

Store the calculation as a single async function declaration. It must return an object with a numeric value and an object metadata.
Returned value and any numeric metadata are sanitized server-side (NaN/Infinity → 0). Throw user-friendly Error messages to surface validation issues in the UI.

UI Component

The UI is a React component named ActivityUI that accepts a single prop onAddActivity(values) and calls it when the user submits.
Notes
  • Use DatasetItemSelector when an input corresponds to a known dataset (ensure datasetName matches your calculation code).
  • The system provides an AI assistant to draft or refine the UI and calculation code; you can edit the code directly at any time.

UI Code Contract

  • Define function ActivityUI({ onAddActivity }) { ... } in the snippet.
  • Use a click handler: onClick={handleAddActivity}; avoid default form submit flows.
  • No imports; only use components available in scope (Mantine UI and DatasetItemSelector).
  • Keep the component self-contained for the live runtime (no external variables).

Smart CSV Input Detection

When creating a new definition, you can bootstrap inputs from a CSV sample:
  • Upload a CSV file in the “Smart” tab of the New Activity Definition page.
  • The system parses headers and sample rows to infer input names/types and optional examples.
  • It also generates “AI notes” that can seed UI generation. You can then switch to the Manual tab to refine.
This flow fills the same input schema shown above; only name, type, required, and optional example are supported.

Live Preview & Test Context

In the Calculation and UI tabs, you can preview with real data:
  • Calculation preview executes your code with real dataset/KPI/site access through safe server APIs.
  • Configure test context: year, period (YEARLY/QUARTERLY/MONTHLY), periodUnit, and siteId.
  • Any async dataset/KPI/site lookups must be awaited in your calculation.

Public vs. Private Definitions

  • Private (default): visible only to your organization.
  • Public (isCommon): available to all organizations. Creating public definitions requires an ADMIN user.

Calculation Context & Helpers

Inside calculate, these helpers are available:
  • $datasets
    • getItem(datasetName, itemName, year?)
    • getDataset(datasetName, year?)
    • getCoefficient(datasetName, itemName, coefficientKey, year?)
    • getCoefficients(datasetName, year?)
  • $kpis
    • getIndicator(name)
    • getIndicatorById(id)
    • getAllIndicators()
    • getIndicatorsByTag(tag)
    • getIndicatorVariables(indicatorId)
  • $sites
    • getSite(id), getSiteByName(name), getAllSites()
    • getChildSites(parentId), getSitesByCity(city), getSitesByTag(tag)
    • getTotalFloorArea(siteIds), getTotalEmployees(siteIds)
  • $year, $period, $periodUnit, $siteId
All dataset/KPI/site access is enforced with row-level security for the current organization.

Using ActivityDefinitions In Forms

  • Add an ACTIVITY form element and link it to an ActivityDefinition.
  • The element’s key is used by the Activities API to add/import/recalculate data for that specific definition.
  • The UI code is rendered inline and calls onAddActivity(values) which creates a new Activity after running your calculation.
Workflow
  • If a workflow requires approval, submissions in the current period are marked COMPLETED; otherwise they are APPROVED.

When to Recalculate

  • After updating calculation logic, use bulk recalc to align existing activities: activities.recalculateActivities with filters by site/year/period.
  • If datasets used by your calc changed, recalc affected activities for the relevant periods.

Best Practices

  • Validate inputs early and throw user-friendly errors.
  • Always return { value: number, metadata: Record<string, any> }.
  • Keep dataset names consistent between UI and calc code.
  • Prefer numeric primitives in metadata when possible (non-numeric values are fine, but numbers are easier to chart/filter).
  • Use examples in the input schema to guide UI/CSV detection and previews.

Troubleshooting

  • “Function parse failed” → Ensure you saved a full async function calculate(inputValues) { ... } declaration.
  • “Must return ” → Return { value: number, metadata: object } from the function.
  • “Missing dataset item” → Use fallbacks: const ef = (await $datasets.getCoefficient(...)) ?? 0.
  • NaN/Infinity in results → Validate numeric inputs; server normalizes to 0 but fix root cause.
  • Forbidden site during add/import → Check site access/filters.

Performance Tips

  • Prefer fetching all coefficients at once with $datasets.getCoefficients(dataset, $year) if you need many lookups.
  • Avoid multiple awaits in tight loops; compute once and reuse.
  • Keep metadata concise; store detailed objects only when needed.

Metadata Conventions

  • Include units and sources where relevant (e.g., emissionFactorKgCO2ePerKWh, factorSource: "EPA").
  • Keep numbers numeric for charting; use strings for labels/IDs.

See Also

  • Activity Calculation Variables (context helpers and examples)
  • Dataset Access Examples (patterns for datasets/datasets/kpis/$sites usage)

Operational Notes

  • Reusability: a single definition can be used across multiple forms and sites.
  • Consistency: the same calculation logic ensures identical results.
  • Transparency: the calculation function and metadata make assumptions explicit.