Quick Start
- Create a new ActivityDefinition (Customization → Activity Definitions → New)
- Define inputs (manually or via Smart CSV)
- Write calculation code (async function returning
{ value, metadata }) - Build the UI (
ActivityUIcallingonAddActivity(values)) - Preview with test context → Save
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):"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
examplevalues 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 numericvalue and an object metadata.
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 namedActivityUI that accepts a single prop onAddActivity(values) and calls it when the user submits.
- Use
DatasetItemSelectorwhen an input corresponds to a known dataset (ensuredatasetNamematches 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.
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, andsiteId. - 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
Insidecalculate, these helpers are available:
$datasetsgetItem(datasetName, itemName, year?)getDataset(datasetName, year?)getCoefficient(datasetName, itemName, coefficientKey, year?)getCoefficients(datasetName, year?)
$kpisgetIndicator(name)getIndicatorById(id)getAllIndicators()getIndicatorsByTag(tag)getIndicatorVariables(indicatorId)
$sitesgetSite(id),getSiteByName(name),getAllSites()getChildSites(parentId),getSitesByCity(city),getSitesByTag(tag)getTotalFloorArea(siteIds),getTotalEmployees(siteIds)
$year,$period,$periodUnit,$siteId
Using ActivityDefinitions In Forms
- Add an ACTIVITY form element and link it to an ActivityDefinition.
- The element’s
keyis 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.
- If a workflow requires approval, submissions in the current period are marked
COMPLETED; otherwise they areAPPROVED.
When to Recalculate
- After updating calculation logic, use bulk recalc to align existing activities:
activities.recalculateActivitieswith 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 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.

