Station Dashboard KPIs

ops station kpi analytics

The /oee/stations view answers, at a glance: which jobs are at this station, are any falling behind, and how is the station tracking against standard? It draws from three SQL functions plus the cross-canvas warning rollup.

Functions

get_station_efficiency_kpis(org, station_id, from, to, completed_only)

Single-row aggregate that drives the top KPI cards and the Range Metrics strip on the dashboard.

Range-scoped job metrics use machine-event overlap. A batch is in range when any part of its actual_start_ts to actual_end_ts interval overlaps the selected range; running batches use the current time as their effective end. Completed job metrics such as completed run time, parts, quality, and abort rate use the same overlap rule instead of requiring the job to finish inside the selected range.

FieldDescription
active_jobsRunning jobs currently at the station (live, ignores time range)
jobs_over_stdActive jobs where Touch ≥ standard OR Dwell ≥ standard
earned_hoursΣ(standard_hours × good_parts) for batches in range. NULL when no batches/no standards
actual_hoursΣ(Touch) for batches in range, in hours. NULL when no data
effectiveness_pctearned_hours ÷ actual_hours × 100. NULL-aware (no 0.0 for absent data)
avg_variance_pctAverage per-batch ((Touch − std) ÷ std) × 100 across batches in range
active_operatorsDistinct users currently clocked in on running jobs at the station

completed_only=true filters Earned/Actual to status='completed' batches — flips the dashboard from a live mix to closed batches.

get_station_active_jobs(org, station_id)

One row per running job at the station, enriched for the Active Jobs strip and the Touch chart.

FieldDescription
id, batch_number, work_order, product_*, actual_start_ts, …Standard batch fields
touch_time_minutesΣ Touch on this job. NULL when no operator has ever clocked in
standard_hoursResolved from oee_product_equipment_config (product_id, equipment_id) for this (product, station). NULL means no standard configured — never default-yellow
active_operator_countCurrently-clocked-in users on this job (open oee_time_entries)
time_entriesJSONB array of every operator entry on the job — lets the chart derive Touch(t) client-side without N+1 calls

get_process_flow_station_warnings(org, site_id)

Per-station worst-warning rollup. Drives the yellow/red icons on Process Flow station nodes so a supervisor sees from across the canvas which stations need attention.

Returns one row per station with warning_level ∈ {yellow, red}. Stations without a breached job are absent from the result (never emit none rows). Self-defends org isolation in SQL — never trusts the Express middleware alone.

Endpoints

RouteFunction
GET /api/v1/oee/stations/:id/active-jobsget_station_active_jobs
GET /api/v1/oee/stations/:id/kpis?from=&to=&completed_only=get_station_efficiency_kpis
GET /api/v1/oee/sites/:id/process-flow-warningsget_process_flow_station_warnings

All three: checkToken + checkOrgOwns… middleware, AND a self-defending org check inside the SQL.

Dashboard layout

  • Top KPI cards (4): Effectiveness, Active Jobs, Jobs Over Std, Avg Variance — all from get_station_efficiency_kpis
  • Two-column focus grid: PLC over Touch chart on the left, Active Jobs strip on the right (full grid height)
  • Active Jobs strip: each row focuses the job in the PLC/chart when clicked. The job number itself links to the Job History focus page for that job number.
  • Range Metrics row (4): Earned Hours, Actual Hours, Active Operators, On Pace % — On Pace derived as (active_jobs − jobs_over_std) ÷ active_jobs × 100. The “Completed only” toggle lives in this section’s header — it only scopes Earned/Actual/Effectiveness/Variance, not “right now” counts
  • State Timeline + Event Log below

The equipment-flavored Total Downtime / MTBF / MTTR / Abort Rate row is suppressed for station-type selection — those are asset-reliability metrics, wrong question for a station.

Station comparison

The Stations page supports an explicit comparison mode. Selecting one visible station shows the Compare action in a disabled state. Selecting two or more stations enables Compare, which opens /oee/stations/compare?ids=<station ids> for the selected station rows. The query string carries the station IDs, so the comparison can be reopened for the same site and current date range.

Select visible and deselect visible operate only on the filtered station list. Normal station selection still drives the dashboard; comparison opens only through the Compare action.

The comparison page is station-first. It summarizes the selected station set, then lists each station side by side with current state, active jobs, completed station visits, labor hours, standard hours, effectiveness, average Touch, average Dwell, jobs over standard, and downtime counts. Completed station visits are counted from ended batch or production machine events at that station in the selected range, so the comparison reflects station throughput even when the overall job has not reached a final completed status.

The aggregate KPI row keeps the high-signal comparison fields compact in one row: a combined Jobs card for active jobs, completed station visits, and jobs over standard; then labor hours, standard hours, efficiency, average Touch, and average Dwell. Expanding a row shows station-specific drilldown details such as active operators, lost hours, planned/unplanned downtime, and active job cards.

The side-by-side station table is the primary station summary. It includes current state, active jobs, completed station visits, labor hours, standard hours, efficiency, average Touch, average Dwell, jobs over standard, missing station standards, top product, longest dwell, and downtime.

Below the side-by-side rows, the comparison page includes a station-first workbench for explaining why stations differ. The workbench includes product mix, operator contribution, day-by-day station trends, event/reason mix, and outlier/coverage rows. Product mix combines active job labor and standard-hour data with completed station-visit counts. Operator contribution is derived from active station jobs and their time-entry detail. Station-visit timing is folded into the station summary and outlier rows, including longest dwell and missing-standard coverage.

The comparison page also shows one State History timeline per selected station for the current date range. It shows a combined Event Log for the selected stations with quick filters for all events, production, downtime, incidents, and open events. In comparison mode, the Event Log includes a Station column so the same production, downtime, and activity events can be read without opening each station dashboard separately.

Touch chart axes

Drop-dead simple:

  • x = Hours running (real elapsed time since the job’s actual_start_ts)
  • y = Touch (% of standard)

One curve per active job from (0, 0) to its live (elapsed, Touch%) endpoint. One dashed reference line at y = 100% labelled Standard. Default spotlight: focused job + jobs already over standard render bright; everyone else dims. A Show all toggle brings dimmed curves back to full opacity. Jobs without a configured standard surface as a “N no standard” chip — they can’t plot on the % axis but still appear in the Active Jobs strip.

See Touch and Dwell for the underlying definitions.

NULL semantics

get_station_efficiency_kpis propagates NULL all the way to the frontend whenever a metric has no data to compute over. The KPI tile renders . “0 earned hours” and “no data to compute earned hours” are different states — flattening them with COALESCE(..., 0) was a real bug fixed during PR #3084 polish.

Codebase paths

LayerFile
SQLdatabase/sql_scripts/functions/oee/oee_functions.sql
Backend route registrationbackend/index.ts
Backend handlersbackend/endpoints/oee.ts
Backend queriesbackend/queries/oee.ts
Frontend dashboardfrontend/src/app/features/oee-dashboard/components/oee-dashboard/
Frontend comparison pagefrontend/src/app/features/oee-dashboard/components/station-comparison-page/
Frontend Active Jobs strip…/components/active-jobs-list/
Frontend Touch chart…/components/station-touch-dwell-chart/

See Also