> ## Documentation Index
> Fetch the complete documentation index at: https://docs.azalt.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Target

> Goals for indicators with period-based entries, baseline support, and site or organization scope

A Target represents a performance goal for an indicator. Targets can be organization-wide or site-specific, expressed as absolute values or relative percentages, and scheduled by period (yearly, quarterly, monthly, or timestamp).

## Overview

* Link to an indicator (optional but recommended)
* Define a baseline period for relative targets (year, quarter, month)
* Add one or more target entries with period, type, and value
* Scope entries to a specific site or leave them organization-wide
* Optionally store integration metadata (e.g., dataset mappings)

## Data Model

Target (simplified):

```ts theme={null}
// apps/azalt/src/server/db/types/target.ts
interface TargetEntry {
  siteId?: string | null;
  period: 'YEARLY' | 'QUARTERLY' | 'MONTHLY' | 'TIMESTAMP';
  year: number;
  month?: number | null;     // 1-12 for MONTHLY
  quarter?: number | null;   // 1-4 for QUARTERLY
  type: 'ABSOLUTE' | 'RELATIVE_PERCENT';
  targetValue: number;       // numeric or percent (for RELATIVE_PERCENT)
}

interface Target {
  id: string;
  indicatorId: string | null;
  organizationId: string;
  title: string | null;
  baselineYear: number | null;
  baselineQuarter: number | null;
  baselineMonth: number | null;
  metadata: Record<string, unknown> | null; // e.g. { indicatorMappings: { [indicatorId]: { name, field } } }
  targetEntries: TargetEntry[];
  createdAt: Date;
  updatedAt: Date;
}
```

Notes:

* `TIMESTAMP` supports event-based targets in addition to calendar periods.
* If `siteId` is omitted on an entry, it applies at organization level.
* Relative targets interpret `targetValue` as a percentage change from the baseline period.

## Target Entries

Each entry represents a goal for a specific period and (optionally) site:

```json theme={null}
{
  "siteId": "site_123",            // optional
  "period": "MONTHLY",             // YEARLY | QUARTERLY | MONTHLY | TIMESTAMP
  "year": 2025,
  "month": 7,                       // for MONTHLY
  "type": "RELATIVE_PERCENT",      // ABSOLUTE | RELATIVE_PERCENT
  "targetValue": -12.5              // -12.5% reduction vs baseline
}
```

Common patterns:

* Organization target: omit `siteId` on entries
* Site target: set `siteId` per entry; different sites may have different trajectories
* Mixed schedule: combine yearly and monthly entries as needed

## Baseline & Status

* Absolute targets: compare current indicator value vs `targetValue`
* Relative targets: evaluate change required from the baseline period (year/quarter/month)

UI cues (Targets page) summarize status per latest entry in the current year:

* On-track/Warning/Behind for absolute targets (based on % progress)
* Baseline required for relative targets

## API

TRPC procedures (with REST mirrors via OpenAPI):

* `targets.list` → GET `/targets`
* `targets.getById` → GET `/targets/{id}`
* `targets.create` → POST `/targets`
* `targets.update` → PUT `/targets/{id}`
* `targets.delete` → DELETE `/targets/{id}`

Create example:

```json theme={null}
{
  "indicatorId": "ind_abc",
  "title": "Targets for Electricity Intensity",
  "baselineYear": 2024,
  "baselineQuarter": null,
  "baselineMonth": null,
  "metadata": {
    "indicatorMappings": {
      "ind_usage": { "name": "electricity", "field": "kwh" }
    }
  },
  "targetEntries": [
    { "period": "YEARLY", "year": 2025, "type": "ABSOLUTE", "targetValue": 100 },
    { "siteId": "site_1", "period": "MONTHLY", "year": 2025, "month": 12, "type": "RELATIVE_PERCENT", "targetValue": -10 }
  ]
}
```

Access control:

* All operations enforce organization scoping and site-level permissions
* Site IDs in entries must be accessible; otherwise request is rejected

## UI & Workflow

* Page: `/targets` lists groups with inline title edit, indicator preview, and status badges
* Modal: create/edit with preview, per-period entries, and site scoping
* Timeline/List views: visualize progression and trend arrows between entries
* Indicator mappings: optional `metadata.indicatorMappings` to align target context with indicator datasets

## Dashboards & Widgets

* Widgets can reference selected target entries (e.g., draw goal lines)
* Selection is stored in widget settings as `selectedTargetEntries: string[]`

## Query Patterns

* Filter by indicator/site/year on `list`
* Client usually fetches current indicator values to compare against latest target in the current year

## Security

* Organization isolation is enforced in queries
* Site access is validated for any `siteId` present in entries

## Migration History (high level)

* Introduced `Target` with per-row fields (period, type, value)
* Restructured to `targetEntries` (jsonb) to support multiple entries per target
* Added `title`, `organizationId`, and `baselineQuarter`

## See Also

* Concepts: `Dataset`, `Unit`, `Dashboard`, `Widget`
* Server: targets router in `apps/azalt/src/server/api/routers/target`
