From 8c5a43f3b8b244a6d1ec8eeb91539c29b771ec6c Mon Sep 17 00:00:00 2001 From: david kiania Date: Fri, 5 Jun 2026 18:11:03 +0300 Subject: [PATCH] chore(db): purge unused ops + dwh_gold schemas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the dormant ops (workshop / tickets / dispatch / SLA / odometer) and dwh_gold (nightly ETL aggregates) schemas plus their dependents — features never implemented, no live writer or scheduled refresh. - Prod DB (already applied): DROP SCHEMA ops/dwh_gold CASCADE, plus tracksolid.dispatch_log, v_sla_inflight, v_utilisation_daily. - migrations/12_drop_ops.sql + 13_drop_dwh_gold.sql (forward, all IF EXISTS) registered in run_migrations.py for rebuild durability. - grafana: removed 8 now-broken panels (In-flight SLA, Idle Cost, Utilisation Heatmap, Row 7 Field-Service SLAs) from daily_operations; panel count 21 -> 13. - docs: scrubbed CLAUDE.md, PLATFORM_OVERVIEW.html (-19KB), DATA_FLOW.md; pre-drop seed snapshot in docs/reports/260605_ops_purge_backup.md. The separate tracksolid_dwh server (31.97.44.246:5888) is unrelated and untouched. Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 27 +- docs/DATA_FLOW.md | 240 ++++ docs/PLATFORM_OVERVIEW.html | 2 +- docs/reports/260605_ops_purge_backup.md | 47 + .../daily_operations_dashboard.json | 1103 ++++++++++++----- migrations/12_drop_ops.sql | 30 + migrations/13_drop_dwh_gold.sql | 23 + run_migrations.py | 2 + 8 files changed, 1152 insertions(+), 322 deletions(-) create mode 100644 docs/DATA_FLOW.md create mode 100644 docs/reports/260605_ops_purge_backup.md create mode 100644 migrations/12_drop_ops.sql create mode 100644 migrations/13_drop_dwh_gold.sql diff --git a/CLAUDE.md b/CLAUDE.md index 5ad556c..9718983 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -56,7 +56,7 @@ See `docs/CONNECTIONS.md` for the full shape. Summary: - **SSH:** `ssh -i ~/.ssh/id_ed25519 kianiadee@stage.rahamafresh.com` - **DB name:** `tracksolid_db` · **DB user:** `postgres` (internal) · `tracksolid_owner` (app) · `grafana_ro` (read-only) -- **DB schemas:** `tracksolid` (live, single source of truth) · `dwh_gold` (aggregates) · `ops` (workshop / tickets / odometer) · `infrastructure`. The legacy `tracksolid_2` schema no longer exists — migrations 02–06 applied 2026-04-18. +- **DB schemas:** `tracksolid` (live, single source of truth) · `reporting` (map-dashboard read layer) · `infrastructure`. The legacy `tracksolid_2` schema no longer exists (migrations 02–06, 2026-04-18); the `ops` and `dwh_gold` schemas were purged 2026-06-05 (migrations 12/13) as unused. - **DB access:** `DATABASE_URL` points to `timescale_db:5432` (internal Docker network — not reachable locally). Use `docker exec` pattern above. See `docs/CONNECTIONS.md` for full reference. - **DWH target DB:** `tracksolid_dwh` at `31.97.44.246:5888` (separate PostGIS instance, public IP). Users: `dwh_owner` (bronze writes + `dwh_control`), `grafana_ro` (reads bronze/silver/gold/`dwh_control`). Always connect with `sslmode=require`. Fed by the n8n `dwh_extract` + `dwh_load_bronze` workflows — see `docs/DWH_PIPELINE.md`. - **Container naming:** Coolify appends a random suffix. Always resolve with: @@ -93,10 +93,11 @@ dwh/ # DWH migrations for tracksolid_dwh@31.97.44.246:588 # 261002_bronze_constraints_audit.sql — ON CONFLICT key assertion # 261003_dwh_roles.sql — role contract assertion # 261004_dwh_observability_views.sql — freshness/failure views -migrations/ # Numbered SQL migrations 02–10, applied in order by run_migrations.py +migrations/ # Numbered SQL migrations 02–13, applied in order by run_migrations.py # 02 full schema · 03 webhook · 04 distance fix · 05 enhancements # 06 ops/analytics · 07 views · 08 config · 09 trips enrichment - # 10_driver_clock_views.sql · 10_pgbouncer_auth.sql + # 10_driver_clock_views.sql · 10_pgbouncer_auth.sql · 11 reporting + # 12 drop ops schema · 13 drop dwh_gold schema (both 2026-06-05) Dockerfile # Custom image for ingest/webhook containers pyproject.toml # Python project + uv dependency spec backup/ # pg_dump sidecar scripts and config @@ -126,12 +127,13 @@ tracksolid.alarms -- Alarm events (alarm_type, alarm_name, alarm_time tracksolid.obd_readings -- OBD diagnostics (push only, awaiting webhook registration) tracksolid.device_events -- Power on/off tamper events (push only) tracksolid.ingestion_log -- API call audit trail — 875 runs / 24h, 0 failures at last check (2026-04-19) -tracksolid.dispatch_log -- Dispatch decisions for SLA tracking (migration 06; empty until ops integration) -tracksolid.schema_migrations -- Applied files: 02,03,04,05,06 (last 06 on 2026-04-18) -dwh_gold.fact_daily_fleet_metrics -- Nightly ETL aggregates per vehicle per day (run refresh_daily_metrics) -ops.service_log -- Workshop service history (migration 06) -ops.odometer_readings -- Physical odometer captures (migration 06) -ops.tickets -- Ticket skeleton for ops integration (migration 06; empty) +tracksolid.schema_migrations -- Applied migrations 02–13 +-- PURGED 2026-06-05 (migrations 12 + 13): the dormant `ops` schema (tickets, service_log, +-- odometer_readings, cost_rates, kpi_targets, vw_service_forecast), tracksolid.dispatch_log, +-- and the `dwh_gold` schema (dim_vehicles, fact_daily_fleet_metrics, refresh_daily_metrics). +-- Those workshop/dispatch/SLA/utilisation features were never implemented. Do NOT reintroduce +-- references to ops.* or dwh_gold.* — they no longer exist. (The separate tracksolid_dwh DB +-- at 31.97.44.246:5888 is unrelated and untouched.) ``` Full DDL: `02_tracksolid_full_schema_rev.sql` + migrations `03`–`06`. @@ -146,8 +148,8 @@ tracksolid.v_currently_idle -- §2.2 idle lens tracksolid.v_driver_aggregates_daily -- §3.1 + §3.2 aggression index source tracksolid.v_fleet_km_daily -- §7 Panel 5 distance trend tracksolid.v_alarms_daily -- §7 Panel 7 alarm frequency -tracksolid.v_utilisation_daily -- §7 Panel 8 utilisation heatmap (gated on dwh_gold ETL) -tracksolid.v_sla_inflight -- §4.5 SLA panels (gated on ops.tickets) +-- v_utilisation_daily (dwh_gold) and v_sla_inflight (ops) were DROPPED 2026-06-05 with +-- their schemas (migrations 12/13); their Grafana panels were removed from the dashboard. ``` All views carry a `COMMENT ON VIEW` referencing their spec — `\d+ tracksolid.v_*` shows the provenance. @@ -222,7 +224,7 @@ dwh_control.v_watermark_lag -- Grafana: extract vs. load lag per table 7. **Secrets from env only.** Connection strings, API keys, and passwords live in `.env`. Reference variable names from `docs/CONNECTIONS.md`, never values. 8. **Two developers, one incoming.** Write code and docs that a second developer (mixed technical/operations background) can follow without prior context. 9. **Forgejo API auth:** credentials stored in macOS keychain. Retrieve with `git credential fill` (host=repo.rahamafresh.com). Use basic auth against `https://repo.rahamafresh.com/api/v1` directly — no `tea` or `gh` needed. -10. **Single live schema.** All live data lives in `tracksolid`. Aggregates live in `dwh_gold`; workshop/ticket integrations live in `ops`. Do not reintroduce references to the retired `tracksolid_2` schema. +10. **Single live schema.** All live data lives in `tracksolid`; the map-dashboard read layer lives in `reporting`. Do not reintroduce references to the retired `tracksolid_2`, `ops`, or `dwh_gold` schemas (the latter two purged 2026-06-05, migrations 12/13). --- @@ -256,6 +258,5 @@ Latest full snapshot: `docs/reports/260412_baseline_report.md` | MEDIUM | Investigate 44 silent devices (only 19 of 63 reporting) — SIM installed? Activated? | | MEDIUM | Co-develop client KPI framework (see `docs/KPI_FRAMEWORK.md`) | | LOW | Populate geofences — depot boundaries, city zones | -| LOW | Schedule nightly ETL: `SELECT dwh_gold.refresh_daily_metrics(CURRENT_DATE - 1)` (cron or n8n) | | HIGH | Deploy DWH bronze pipeline: apply `dwh/26100{1,2,3,4}.sql` to `tracksolid_dwh`, import + wire the two n8n workflows, verify first run via `dwh_control.v_table_freshness`. Runbook: `docs/DWH_PIPELINE.md` | | MEDIUM | Rotate `dwh_owner` / `grafana_ro` passwords on `tracksolid_dwh` — plaintext in `dwh/260423_dwh_ddl_v1.sql` is a pre-existing flaw to clean up separately | diff --git a/docs/DATA_FLOW.md b/docs/DATA_FLOW.md new file mode 100644 index 0000000..1314cda --- /dev/null +++ b/docs/DATA_FLOW.md @@ -0,0 +1,240 @@ +# Data Flow — Ingestion → Aggregation → Views → Functions → Consumers + +**Scope:** the *live* fleet pipeline only (`tracksolid` + `reporting`). The `ops` and +`dwh_gold` schemas were **purged on 2026-06-05** (migrations 12/13) — those workshop / +dispatch / SLA / utilisation features were never implemented. They are shown below only as +a struck-out "removed" footnote for historical context. (The *separate* `tracksolid_dwh` +server at 31.97.44.246:5888 is unrelated and was not touched.) + +**Verified against prod 2026-06-05** (TimescaleDB hypertable + continuous-aggregate +catalog, `pg_depend` view graph, ingestion `INSERT` targets, `dashboard_api` queries, +Grafana panel SQL). Key facts that surprised the docs: + +- Only `position_history` (and the empty/planned `heartbeats`, `fuel_readings`, + `temperature_readings`) are **hypertables**. `trips` and `alarms` are **plain tables**. +- `tracksolid.v_mileage_daily_cagg` is a **real TimescaleDB continuous aggregate**, not a + plain view — and it currently has **no downstream consumer**. +- `reporting.v_trips` is a **matview**, refreshed every 5 min by the in-process + `dashboard_api` background loop (FIX-D02), pg advisory-lock `920145`. + +--- + +## Mermaid + +```mermaid +flowchart TD + API["Tracksolid / Jimi API
poll + push webhooks · OAuth2"] + + subgraph ING["Ingestion — ts_shared_rev.py: get_conn() · api_post() · clean*()"] + IM["ingest_movement_rev.py"] + IE["ingest_events_rev.py"] + WR["webhook_receiver_rev.py"] + end + API --> IM & IE & WR + + subgraph L1["L1 · Base tables + hypertables — schema: tracksolid (single source of truth)"] + LP["live_positions
current fix / IMEI"] + PH[("position_history
HYPERTABLE · high-res GPS trail")] + TR["trips
plain table — NOT a hypertable"] + DV["devices
vehicle / driver registry"] + AL["alarms
plain table"] + ILOG["ingestion_log · api_token_cache"] + EMPTY["heartbeats* · fuel_readings* · temperature_readings* (HYPERTABLES, empty)
device_events · fault_codes · obd_readings · parking_events · lbs_readings · geofences (empty)"] + end + IM --> LP & PH & TR & DV + IM --> ILOG + IE --> AL + WR --> EMPTY + + subgraph L2["L2 · Aggregation"] + CAGG[("v_mileage_daily_cagg
CONTINUOUS AGGREGATE")] + VT[("reporting.v_trips
MATVIEW · ix_v_trips_trip_id")] + RLOG["reporting.refresh_log"] + end + PH -->|Timescale cont-agg policy| CAGG + TR --> VT + DV --> VT + VT -->|"REFRESH CONCURRENTLY every 300s
(dashboard_api loop, adv-lock 920145)"| RLOG + + subgraph L3L["L3 · Reporting views — fed by v_trips matview"] + FILT["v_filter_vehicles · v_filter_drivers
v_filter_cost_centres · v_filter_cities"] + SUMM["v_daily/weekly/monthly_summary
v_*_cost_centre · v_trips_today"] + VLP["v_live_positions"] + end + VT --> FILT & SUMM + LP --> VLP + + subgraph L3R["L3 · Grafana views — tracksolid.* (read base tables directly)"] + GV["v_fleet_today · v_fleet_status · v_active_dispatch_map
v_currently_idle · v_alarms_daily · v_fleet_km_daily
v_ingestion_health · v_vehicles_not_moved_today
v_driver_aggregates_daily · v_fleet_trace · v_driver_clock_*"] + end + LP --> GV + TR --> GV + DV --> GV + AL --> GV + PH --> GV + + subgraph L4["L4 · Functions — reporting.* (the only API entrypoints)"] + FLP["fn_live_positions(cost_centre, acc_status)"] + FVT["fn_vehicle_track(vehicle_number, hours)"] + FTM["fn_trips_for_map(veh[], driver, cc, city, start, end)"] + NP["normalize_plate(p) · helper"] + end + LP --> FLP + DV --> FLP + PH --> FVT + VT --> FTM + NP -.-> FTM + + subgraph L5["L5 · Consumers"] + DAPI["dashboard_api_rev.py
FastAPI :8890 · 2 workers"] + SPA["SPAs: liveposition.* · fleetintelligence.*
(rustfs / S3 single-file maps)"] + GRAF["Grafana"] + end + FLP --> DAPI + FVT --> DAPI + FTM --> DAPI + FILT --> DAPI + DAPI -->|"HTTPS · fleetapi.rahamafresh.com"| SPA + GV --> GRAF + + CAGG -.->|no consumer yet| NONE(["⚠ unconsumed — no panel / API reads it"]) + + subgraph PARK["REMOVED 2026-06-05 — purged via migrations 12 / 13 (never implemented)"] + GONE["ops.* (tickets · dispatch_log · service_log · odometer_readings · cost_rates · kpi_targets · vw_service_forecast)
dwh_gold.* (dim_vehicles · fact_daily_fleet_metrics · refresh_daily_metrics)
tracksolid.v_sla_inflight · tracksolid.v_utilisation_daily + their Grafana panels"] + end + + classDef hyper fill:#e1f0ff,stroke:#3b82f6,color:#0b3d91; + classDef mat fill:#fff3cd,stroke:#d4a017,color:#664d03; + classDef cagg fill:#e7f7e7,stroke:#2e9e2e,color:#1e5e1e; + classDef parked fill:#f0f0f0,stroke:#999,stroke-dasharray:5 5,color:#555; + classDef warn fill:#fdecea,stroke:#d93025,color:#a52714; + class PH hyper; + class VT mat; + class CAGG cagg; + class PARK,GONE parked; + class NONE warn; +``` + +--- + +## ASCII + +``` + ╔══════════════════════════════════════════════╗ + ║ TRACKSOLID / JIMI API ║ + ║ (poll + push webhooks, OAuth2) ║ + ╚════════════════════╤═════════════════════════╝ + │ + ┌──────────────────────────┬───────────┴───────────┬────────────────────────────┐ + ▼ ▼ ▼ ▼ +┌─────────────────┐ ┌────────────────────┐ ┌──────────────────────┐ +│ ingest_movement │ │ ingest_events │ │ webhook_receiver │ (all via ts_shared_rev.py: +│ _rev.py │ │ _rev.py │ │ _rev.py │ get_conn() pool, api_post(), +└────────┬────────┘ └─────────┬──────────┘ └──────────┬───────────┘ clean*() , token cache) + │ │ │ + │ writes │ writes │ writes (push) + ▼ ▼ ▼ +╔════════════════════════════════════════════════════════════════════════════════════════════╗ +║ L1 · BASE TABLES + HYPERTABLES schema: tracksolid (single source of truth) ║ +║ ║ +║ live_positions ── current fix / IMEI (plain) api_token_cache (auth) ║ +║ position_history ◀═══ HYPERTABLE (high-res GPS trail, partitioned by gps_time) ║ +║ trips ── trip summaries (plain table — NOT a hypertable) ║ +║ devices ── vehicle/driver registry (plain) ║ +║ alarms ── alarm events (plain table) ║ +║ ingestion_log ── API audit trail (plain) ║ +║ heartbeats*, fuel_readings*, temperature_readings* ◀═ HYPERTABLES (empty / planned push) ║ +║ device_events, fault_codes, obd_readings, parking_events, lbs_readings, geofences (empty) ║ +╚══════╤══════════════════════════╤══════════════════════════════════╤════════════════════════╝ + │ │ │ + │ TimescaleDB │ matview refresh │ direct reads + │ cont-agg policy │ (in-app loop) │ (Grafana SQL) + ▼ ▼ ▼ +╔══════════════════╗ ╔════════════════════════════════╗ ╔══════════════════════════════════╗ +║ L2 · AGGREGATION ║ ║ L2 · AGGREGATION (matview) ║ ║ L3 · GRAFANA VIEWS (tracksolid.*) ║ +║ ║ ║ ║ ║ read base tables directly ║ +║ v_mileage_daily ║ ║ reporting.v_trips [MATVIEW] ║ ║ ║ +║ _cagg ║ ║ ◀── trips + devices ║ ║ v_fleet_today v_fleet_status ║ +║ CONTINUOUS AGG ║ ║ unique ix_v_trips_trip_id ║ ║ v_active_dispatch_map ║ +║ ◀═ position_ ║ ║ ║ ║ v_currently_idle v_alarms_daily ║ +║ history ║ ║ REFRESH … CONCURRENTLY every ║ ║ v_fleet_km_daily v_ingestion_health║ +║ (auto refresh ║ ║ VTRIPS_REFRESH_INTERVAL_S=300 ║ ║ v_vehicles_not_moved_today ║ +║ policy) ║ ║ by dashboard_api bg asyncio ║ ║ v_driver_aggregates_daily ║ +╚════════╤═════════╝ ║ loop, pg advisory-lock 920145 ║ ║ v_fleet_trace ║ + │ ║ │ ║ ║ v_driver_clock_daily/_today/_attnd ║ + │ ║ └──▶ reporting.refresh_log ║ ╚══════════════╤═════════════════════╝ + │ ╚═══════════════╤════════════════╝ │ + │ │ │ + │ ▼ │ + │ ╔════════════════════════════════════════════╗ │ + │ ║ L3 · REPORTING VIEWS (← v_trips matview) ║ │ + │ ║ v_filter_vehicles v_filter_drivers ║ │ + │ ║ v_filter_cost_centres v_filter_cities ║ │ + │ ║ v_daily/weekly/monthly_summary ║ │ + │ ║ v_*_cost_centre v_trips_today ║ │ + │ ║ v_live_positions (view, ← live_positions) ║ │ + │ ╚════════════════════════╤═══════════════════╝ │ + │ │ │ + │ ╔══════════════════════════════════╧═══════════════════╗ │ + │ ║ L4 · FUNCTIONS (schema reporting — API entrypoints) ║ │ + │ ║ ║ │ + │ ║ fn_live_positions(cost_centre, acc_status) ║ │ + │ ║ ◀── live_positions + devices ║ │ + │ ║ fn_vehicle_track(vehicle_number, hours) ║ │ + │ ║ ◀── position_history (hypertable trail) ────────╫─────┘ (also reads L1) + │ ║ fn_trips_for_map(veh[],driver,cc,city,start,end) ║ + │ ║ ◀── reporting.v_trips (matview) ║ + │ ║ normalize_plate(p) ── helper used by the above ║ + │ ╚════════════════════════════╤══════════════════════════╝ + │ │ + ▼ ▼ + (cagg currently ╔═══════════════════════════════════════════════╗ + unconsumed — ║ L5 · CONSUMERS ║ + no panel/API yet) ║ ║ + ║ dashboard_api_rev.py (FastAPI :8890, ×2 wkrs) ║ + ║ POST /webhook/fleet-dashboard → fn_trips_for_map + v_filter_* + ║ GET /webhook/live-positions → fn_live_positions + ║ GET /webhook/live-positions/track → fn_vehicle_track + ║ │ ║ + ║ ▼ HTTPS (fleetapi.rahamafresh.com) ║ + ║ SPAs: liveposition.* · fleetintelligence.* ║ + ║ (rustfs/S3 single-file maps) ║ + ║ ║ + ║ Grafana ──SQL──▶ tracksolid.v_* (L3 right) ║ + ╚═══════════════════════════════════════════════╝ + + + ┌─ REMOVED 2026-06-05 · purged via migrations 12 / 13 (never implemented) ───────────────┐ + │ ops.* : tickets, dispatch_log, service_log, odometer_readings, │ + │ cost_rates, kpi_targets, vw_service_forecast │ + │ dwh_gold.* : dim_vehicles, fact_daily_fleet_metrics, refresh_daily_metrics() │ + │ tracksolid : v_sla_inflight, v_utilisation_daily (+ their Grafana panels removed) │ + │ → Schemas dropped from prod. The separate tracksolid_dwh server is unrelated/untouched.│ + └────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## How to read it + +- **L1** is where ingestion lands. Only `position_history` (and three empty/planned + hypertables) are TimescaleDB hypertables; `trips`/`alarms` are ordinary tables. +- **Two aggregation mechanisms** run in parallel: the TimescaleDB **continuous aggregate** + `v_mileage_daily_cagg` (refreshed by a Timescale policy off `position_history`), and the + **`reporting.v_trips` matview** (refreshed every 5 min by the in-process `dashboard_api` + loop — the FIX-D02 self-refresher that replaced the dead n8n job). +- **L4 functions are the only thing the API calls.** SPAs never touch tables directly: + SPA → `dashboard_api` → `fn_*` → (matview / tables). +- **Grafana** takes the right-hand path, reading the `tracksolid.v_*` analytics views + straight off L1. + +## Caveats / housekeeping notes + +1. **`v_mileage_daily_cagg` has no consumer** — nothing in the API or Grafana reads it. It + is a live continuous aggregate maintaining itself for nobody. Candidate for removal or + wiring into a panel. +2. **`ops` and `dwh_gold` were purged** (2026-06-05, migrations 12/13) along with + `v_utilisation_daily`, `v_sla_inflight`, and their Grafana panels — the features were + never implemented. +3. See the companion housekeeping audit (2026-06-05) for the full unused-object list; the + only clean ad-hoc drop is `public.trips_viz_v1`. diff --git a/docs/PLATFORM_OVERVIEW.html b/docs/PLATFORM_OVERVIEW.html index 600e3b4..a4ad785 100644 --- a/docs/PLATFORM_OVERVIEW.html +++ b/docs/PLATFORM_OVERVIEW.html @@ -84,7 +84,7 @@ proxy container. The dashboard_api enforces CORS for both SPA origins.

Operational note. dashboard_api currently runs as a standalone Traefik-labelled container reusing the app image with dashboard_api_rev.py bind-mounted. The durable form is the compose dashboard_api service (already in docker-compose.yaml) once the branch is merged and the fleetapi domain is set in Coolify.

4 · Read-API reference (dashboard_api)

Base: https://fleetapi.rahamafresh.com · all responses JSON · CORS limited to the two SPA origins.

MethodPathParamsReturnsNotes
GET/health{status: ok}Liveness probe.
GET/webhook/live-positionscost_centre?, acc_status?{summary, geojson}Live Positions map feed → reporting.fn_live_positions. ~80 vehicle point features.
GET/webhook/live-positions/trackvehicle_number, hours(1-24)GeoJSON Feature (LineString)One vehicle's recent trail. Alias: /webhook/vehicle-track.
GET/webhook/vehicle-trackvehicle_number, hoursGeoJSON FeatureAlias of live-positions/track (kept for compatibility).
GET/webhook/fleet-dashboard{drivers, cost_centres, cities, vehicles}Filter options for the Fleet Intelligence UI.
POST/webhook/fleet-dashboardform-urlencoded: period|start_date|end_date, vehicle_numbers, driver, cost_centre, assigned_citytrips GeoJSON payloadTrips for the map → reporting.fn_trips_for_map. period preset: today|7d|30d|custom. Body parsed by Content-Type — the SPA posts application/x-www-form-urlencoded; JSON also accepted.
-
Fix (2026-06-05). The POST handler originally read the body as JSON only, but the SPA sends x-www-form-urlencoded; the mismatch silently dropped every filter so the map always returned the whole fleet. Now parsed by Content-Type (parse_qs for form bodies). Commit f1387d1.

5 · Database schema

tracksolid · Live data — the single source of truth. Ingested from the Tracksolid API.

18 table(s) · 17 view(s) · 1 function(s) documented.

tracksolid.alarmstable344,356 rows

Alarm events (alarm_type, alarm_name, alarm_time).

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('alarms_id_seq'::regclass)
imeitext
alarm_typetext
alarm_timetimestamp with time zone
geomgeometry(Point,4326)
latdouble precision
lngdouble precision
speednumeric(7,2)
acc_statustext
updated_attimestamp with time zonenow()
alarm_nametext
sourcetext'poll'::text
severitytextAlarm severity level: critical | warning | info
geofence_idtextTracksolid geofence ID if this is a geofence alarm
geofence_nametextHuman-readable geofence name
acknowledged_attimestamp with time zoneTimestamp when alarm was acknowledged by an operator
acknowledged_bytextUsername or ID of operator who acknowledged the alarm
tracksolid.api_token_cachetable1 rows

OAuth2 token cache for the Jimi/Tracksolid API.

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('api_token_cache_id_seq'::regclass)
accounttextNOT NULL
access_tokentextNOT NULL
refresh_tokentext
app_keytext
expires_attimestamp with time zoneNOT NULL
obtained_attimestamp with time zoneNOT NULLnow()
updated_attimestamp with time zoneNOT NULLnow()
tracksolid.device_eventstable0 rows

Device network connection and disconnection events from /pushevent webhook.

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('device_events_id_seq'::regclass)
imeitextNOT NULL
event_typetextNOT NULLLOGIN = device connected to network; LOGOUT = device disconnected
event_timetimestamp with time zoneNOT NULL
timezonetext
created_attimestamp with time zoneNOT NULLnow()
tracksolid.devicestable181 rows

Device / driver / vehicle registry. One row per tracker (IMEI). Source of plate, driver, SIM, model.

ColumnTypeNullDefaultComment
imeitextNOT NULL
device_nametext
mc_typetext
mc_type_use_scopetext
vehicle_nametext
vehicle_numbertext
vehicle_modelstext
vehicle_icontext
vintext
engine_numbertext
vehicle_brandtext
fuel_100kmnumeric(6,2)
driver_nametext
driver_phonetext
simtext
iccidtext
imsitext
accounttext
customer_nametext
device_group_idtext
device_grouptext
activation_timetimestamp with time zone
expirationtimestamp with time zone
enabled_flagsmallintNOT NULL1
statustext'active'::text
citytext
current_mileage_kmnumeric(12,2)
created_attimestamp with time zoneNOT NULLnow()
updated_attimestamp with time zoneNOT NULLnow()
last_synced_attimestamp with time zone
vehicle_categorytextVehicle type: truck | van | motorcycle | car | other
cost_centretextBusiness unit or department this vehicle belongs to
assigned_routetextRegular route name or ID for route-based reporting
depot_geomgeometry(Point,4326)Home base/depot coordinates (WGS84)
depot_addresstextHuman-readable depot address
assigned_citytextOperating territory code: NBO (Nairobi) | MBA (Mombasa) | KLA (Kampala). Used for city-cohort analytics and geographic drift detection.
tracksolid.dispatch_logtable0 rows

Persistent record of every dispatch decision. Powers SLA metrics: dispatch latency, depart delay, time-to-site, wrench time.

ColumnTypeNullDefaultComment
dispatch_idbigintNOT NULLnextval('dispatch_log_dispatch_id_seq'::regclass)
ticket_idtextNOT NULL
imeitextNOT NULL
driver_nametext
job_latdouble precisionNOT NULL
job_lngdouble precisionNOT NULL
job_geomgeometry(Point,4326)
assigned_attimestamp with time zoneNOT NULLnow()
first_movement_attimestamp with time zoneFirst trip start after assigned_at. Back-filled nightly from trips.
on_site_attimestamp with time zoneTime vehicle entered 150 m radius of job_geom. Back-filled nightly.
resolved_attimestamp with time zoneTicket close time from the ops system (ops.tickets.closed_at).
cancelled_attimestamp with time zone
distance_kmnumeric(8,2)
created_attimestamp with time zoneNOT NULLnow()
tracksolid.fault_codestable0 rows

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('fault_codes_id_seq'::regclass)
imeitextNOT NULL
reported_attimestamp with time zoneNOT NULL
fault_codetextNOT NULL
status_flagsinteger
latdouble precision
lngdouble precision
geomgeometry(Point,4326)
event_timetimestamp with time zone
created_attimestamp with time zoneNOT NULLnow()
tracksolid.fuel_readingshypertable~0 rows

Fuel/oil sensor readings from /pushoil webhook. Unit varies per sensor: cm | % | V | L.

ColumnTypeNullDefaultComment
imeitextNOT NULL
reading_timetimestamp with time zoneNOT NULL
sensor_pathtextSensor channel identifier from the device (path field in API payload)
valuenumeric(10,3)
unittextMeasurement unit: cm (tank depth), % (percentage), V (voltage), L (litres)
latdouble precision
lngdouble precision
geomgeometry(Point,4326)
created_attimestamp with time zoneNOT NULLnow()
tracksolid.geofencestable0 rows

Geofence boundary definitions synced from the Tracksolid platform.

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('geofences_id_seq'::regclass)
fence_idtext
fence_nametextNOT NULL
fence_typetextcircle | polygon
geomgeometry(Geometry,4326)
radius_mnumeric(10,2)Radius in metres — only applicable for circle type geofences
descriptiontext
created_attimestamp with time zoneNOT NULLnow()
updated_attimestamp with time zoneNOT NULLnow()
tracksolid.heartbeatshypertable~0 rows

Device heartbeat hypertable.

ColumnTypeNullDefaultComment
imeitextNOT NULL
gate_timetimestamp with time zoneNOT NULL
power_levelsmallint
gsm_signalsmallint
acc_statussmallint
power_statussmallint
fortifysmallint
created_attimestamp with time zoneNOT NULLnow()
tracksolid.ingestion_logtable274,181 rows

API call audit trail — one row per ingestion run.

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('ingestion_log_id_seq'::regclass)
run_attimestamp with time zoneNOT NULLnow()
endpointtextNOT NULL
imei_countintegerNOT NULL0
rows_upsertedintegerNOT NULL0
rows_insertedintegerNOT NULL0
duration_msintegerNOT NULL0
successbooleanNOT NULLtrue
error_codetext
error_messagetext
tracksolid.lbs_readingstable0 rows

Cell tower / WiFi positioning fallback data from /pushlbs webhook. Used when GPS signal is unavailable.

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('lbs_readings_id_seq'::regclass)
imeitextNOT NULL
gate_timetimestamp with time zoneNOT NULL
post_typetextPositioning technology: WIFI | LBS (cell tower)
lbs_datajsonbRaw JSON payload containing MCC, MNC, and cell tower list for approximate geocoding.
created_attimestamp with time zoneNOT NULLnow()
tracksolid.live_positionstable179 rows

Latest fix per IMEI, refreshed every 60s by ingest_movement. Feeds reporting.v_live_positions.

ColumnTypeNullDefaultComment
imeitextNOT NULL
geomgeometry(Point,4326)
latdouble precision
lngdouble precision
pos_typetext
confidencesmallint
gps_timetimestamp with time zone
hb_timetimestamp with time zone
speednumeric(7,2)
directionnumeric(6,2)
acc_statustext
gps_signalsmallint
gps_numsmallint
elec_quantitynumeric(5,2)
power_valuenumeric(5,2)
battery_power_valnumeric(5,2)
tracker_oiltext
temperaturenumeric(8,2)
current_mileagenumeric(12,2)
device_statustext
expire_flagtext
activation_flagtext
loc_desctext
recorded_attimestamp with time zoneNOT NULLnow()
updated_attimestamp with time zoneNOT NULLnow()
tracksolid.obd_readingstable0 rows

OBD diagnostics — push only via /pushobd webhook.

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('obd_readings_id_seq'::regclass)
imeitext
reading_timetimestamp with time zone
engine_rpmintegerEngine RPM from OBD PID 0x0C
fuel_level_pctnumeric(5,2)Fuel tank level % from OBD PID 0x2F
updated_attimestamp with time zonenow()
car_typesmallint
acc_statesmallint
status_flagsinteger
latdouble precision
lngdouble precision
geomgeometry(Point,4326)
obd_datajsonbRaw obdJson from Jimi push. Contains dataID1..N fields (engine RPM, coolant temp, fuel level, etc.)
coolant_temp_cnumeric(6,2)Coolant temperature °C from OBD PID 0x05
battery_voltagenumeric(5,2)Battery voltage (V) from OBD PID 0x42
intake_pressurenumeric(6,2)Intake manifold pressure kPa from OBD PID 0x0B
throttle_pctnumeric(5,2)Throttle position % from OBD PID 0x11
vehicle_speednumeric(7,2)Vehicle speed km/h from OBD PID 0x0D
engine_load_pctnumeric(5,2)Calculated engine load % from OBD PID 0x04
tracksolid.parking_eventstable0 rows

Stop events with duration + address.

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('parking_events_id_seq'::regclass)
imeitextNOT NULL
event_typetext
start_timetimestamp with time zoneNOT NULL
end_timetimestamp with time zone
duration_secondsinteger
geomgeometry(Point,4326)
addresstext
updated_attimestamp with time zonenow()
tracksolid.position_historyhypertable~3,596,013 rows

All GPS fixes (hypertable, partitioned by gps_time). source='poll' (60s) or 'track_list' (30m high-res).

ColumnTypeNullDefaultComment
imeitextNOT NULL
gps_timetimestamp with time zoneNOT NULL
geomgeometry(Point,4326)
latdouble precision
lngdouble precision
speednumeric(7,2)
directionnumeric(6,2)
acc_statustext
satellitesmallint
current_mileagenumeric(12,2)
recorded_attimestamp with time zonenow()
altitudenumeric(8,2)
post_typesmallint
sourcetext'poll'::text
tracksolid.schema_migrationstable9 rows

ColumnTypeNullDefaultComment
filenametextNOT NULL
applied_attimestamp with time zoneNOT NULLnow()
tracksolid.temperature_readingshypertable~0 rows

Temperature and humidity sensor readings from /pushtem webhook. For cold-chain / refrigerated cargo monitoring.

ColumnTypeNullDefaultComment
imeitextNOT NULL
reading_timetimestamp with time zoneNOT NULL
temperaturenumeric(6,2)
humidity_pctnumeric(5,2)
created_attimestamp with time zoneNOT NULLnow()
tracksolid.tripstable43,765 rows

Trip summaries: distance_km, driving time, avg/max speed, route geometry + addresses (FIX-M20).

ColumnTypeNullDefaultComment
idbigintNOT NULLnextval('trips_id_seq'::regclass)
imeitextNOT NULL
start_timetimestamp with time zoneNOT NULL
end_timetimestamp with time zone
start_geomgeometry(Point,4326)
end_geomgeometry(Point,4326)
distance_kmnumeric(12,2)Trip distance in kilometres. Corrected from mm storage on migration 04 (2026-04-10).
avg_speed_kmhnumeric(7,2)
max_speed_kmhnumeric(7,2)
updated_attimestamp with time zonenow()
fuel_consumed_lnumeric(8,2)
idle_time_sinteger
driving_time_sintegerrunTimeSecond from API: total driving time in seconds
trip_seqinteger
sourcetext'poll'::textpoll = from API polling, push = from webhook push
route_geomgeometry(LineString,4326)Full GPS route polyline built at ingest from position_history points where gps_time BETWEEN start_time AND end_time. NULL when fewer than 2 fixes are available for the trip window.
start_addresstextReverse-geocoded human-readable address near start_geom (Nominatim). NULL on lookup failure; address is best-effort, not authoritative.
end_addresstextReverse-geocoded human-readable address near end_geom (Nominatim). NULL on lookup failure; address is best-effort, not authoritative.
vehicle_platetextDenormalised tracksolid.devices.vehicle_number cached at trip-insert time. Avoids a join for trip displays; refreshed only on next ingest.
waypoints_countintegerNumber of position_history fixes that contributed to route_geom. Audit aid: 0 or 1 means route_geom is NULL or degenerate.
tracksolid.v_active_dispatch_mapview

01_BusinessAnalytics.md §4.3 All Active Vehicles Map. Geomap source.

ColumnTypeNullDefaultComment
imeitext
vehicle_numbertext
vehicle_nametext
driver_nametext
driver_phonetext
assigned_citytext
latdouble precision
lngdouble precision
speednumeric(7,2)
directionnumeric(6,2)
acc_statustext
last_fixtimestamp without time zone
statustext
tracksolid.v_alarms_dailyview

01_BusinessAnalytics.md §7 Panel 7 Alarm Frequency. Stacked-by-alarm_name time series.

ColumnTypeNullDefaultComment
daydate
alarm_nametext
alarm_countbigint
tracksolid.v_currently_idleview

01_BusinessAnalytics.md §2.2 idle lens. Engine on, speed <2 km/h, fix in last 15m.

ColumnTypeNullDefaultComment
imeitext
vehicle_numbertext
driver_nametext
assigned_citytext
latdouble precision
lngdouble precision
sincetimestamp without time zone
idle_secondsinteger
tracksolid.v_driver_aggregates_dailyview

01_BusinessAnalytics.md §3.1 (speeding) + §3.2 (harsh driving). Daily grain; panels window via $__timeFilter(day).

ColumnTypeNullDefaultComment
imeitext
driver_nametext
vehicle_numbertext
assigned_citytext
daydate
kmnumeric
tripsbigint
events_80bigint
events_100bigint
events_120bigint
harsh_eventsbigint
speeding_per_100kmnumeric
harsh_per_100kmnumeric
tracksolid.v_driver_attendance_dailyview

ColumnTypeNullDefaultComment
report_datedate
driver_nametext
vehicle_numbertext
cost_centretext
assigned_citytext
reporting_timetime without time zone
start_addresstext
start_latdouble precision
start_lngdouble precision
statustext
mins_from_startinteger
tracksolid.v_driver_clock_dailyview

Driver clock-in / clock-out daily series. One row per IMEI per Africa/Nairobi date with at least one trip. Reporting/closing times are derived from trip start_time/end_time bounded by local-date start; closing_ts may cross midnight UTC. No policy embedded — n8n applies tardiness rules and cost-centre filtering. See plan i-would-like-to-wobbly-volcano (2026-05-04).

ColumnTypeNullDefaultComment
imeitext
driver_nametext
vehicle_numbertext
cost_centretext
assigned_citytext
report_datedate
reporting_timetime without time zone
closing_timetime without time zone
reporting_tstimestamp with time zone
closing_tstimestamp with time zone
start_latdouble precision
start_lngdouble precision
start_addresstext
end_latdouble precision
end_lngdouble precision
end_addresstext
trips_countbigint
total_kmnumeric
drive_hoursnumeric
tracksolid.v_driver_clock_todayview

Today snapshot of v_driver_clock_daily, filtered to (NOW() AT TIME ZONE 'Africa/Nairobi')::date. Refreshes as trips land throughout the day.

ColumnTypeNullDefaultComment
imeitext
driver_nametext
vehicle_numbertext
cost_centretext
assigned_citytext
report_datedate
reporting_timetime without time zone
closing_timetime without time zone
reporting_tstimestamp with time zone
closing_tstimestamp with time zone
start_latdouble precision
start_lngdouble precision
start_addresstext
end_latdouble precision
end_lngdouble precision
end_addresstext
trips_countbigint
total_kmnumeric
drive_hoursnumeric
tracksolid.v_fleet_km_dailyview

01_BusinessAnalytics.md §7 Panel 5 Distance Trend. City-cohort cut built in.

ColumnTypeNullDefaultComment
daydate
assigned_citytext
kmnumeric
active_vehiclesbigint
tripsbigint
tracksolid.v_fleet_statusview

ColumnTypeNullDefaultComment
imeitext
vehicle_numbertext
driver_nametext
latdouble precision
lngdouble precision
geomgeometry(Point,4326)
speednumeric(7,2)
acc_statustext
gps_timetimestamp with time zone
connectivity_statustext
seconds_since_fixinteger
tracksolid.v_fleet_todayview

01_BusinessAnalytics.md §9 Fleet Readiness Scorecard. One row per device with today's roll-up.

ColumnTypeNullDefaultComment
imeitext
driver_nametext
vehicle_numbertext
vehicle_nametext
assigned_citytext
enabled_flagsmallint
km_todaynumeric
trips_todaybigint
drive_hoursnumeric
idle_hoursnumeric
first_departuretime without time zone
last_returntime without time zone
alarms_todaybigint
last_fixtimestamp without time zone
last_speednumeric(7,2)
did_not_moveboolean
tracksolid.v_fleet_traceview

ColumnTypeNullDefaultComment
gidbigint
driver_nametext
vehicle_nametext
device_nametext
imeitext
geomgeometry(Point,4326)
latnumeric
lngnumeric
start_timetimestamp without time zone
end_timetimestamp without time zone
day_localdate
hour_localinteger
dow_localinteger
gps_time_utctimestamp with time zone
recorded_attimestamp with time zone
speednumeric(7,2)
directionnumeric(6,2)
current_mileagenumeric(12,2)
stationaryboolean
trip_idbigint
tracksolid.v_ingestion_healthview

ColumnTypeNullDefaultComment
endpointtext
run_attimestamp with time zone
successboolean
error_messagetext
seconds_agointeger
tracksolid.v_mileage_daily_caggview

ColumnTypeNullDefaultComment
buckettimestamp with time zone
imeitext
dist_kmnumeric
avg_speednumeric
tracksolid.v_sla_inflightview

01_BusinessAnalytics.md §4.5 Field-Service SLA Metrics. Open tickets + last 24h resolved.

ColumnTypeNullDefaultComment
ticket_idtext
customertext
prioritytext
job_typetext
statustext
created_attimestamp with time zone
assigned_attimestamp with time zone
closed_attimestamp with time zone
assigned_imeitext
driver_nametext
first_movement_attimestamp with time zone
on_site_attimestamp with time zone
resolved_attimestamp with time zone
dispatch_minsnumeric
enroute_minsnumeric
onsite_minsnumeric
resolution_minsnumeric
ticket_stagetext
tracksolid.v_trips_enrichedview

tracksolid.trips with computed daily_seq (Nth trip per IMEI per local Africa/Nairobi day) and trip_date_eat. Replaces reliance on the device-supplied trip_seq column, which is NULL for poll-ingested trips.

ColumnTypeNullDefaultComment
idbigint
imeitext
start_timetimestamp with time zone
end_timetimestamp with time zone
start_geomgeometry(Point,4326)
end_geomgeometry(Point,4326)
distance_kmnumeric(12,2)
avg_speed_kmhnumeric(7,2)
max_speed_kmhnumeric(7,2)
updated_attimestamp with time zone
fuel_consumed_lnumeric(8,2)
idle_time_sinteger
driving_time_sinteger
trip_seqinteger
sourcetext
route_geomgeometry(LineString,4326)
start_addresstext
end_addresstext
vehicle_platetext
waypoints_countinteger
trip_date_eatdate
daily_seqbigint
tracksolid.v_utilisation_dailyview

01_BusinessAnalytics.md §7 Panel 8 Utilisation Heatmap. Empty until nightly ETL runs.

ColumnTypeNullDefaultComment
daydate
imeitext
vehicle_numbertext
driver_nametext
assigned_citytext
total_distance_kmnumeric(12,2)
total_drive_hoursnumeric(8,2)
total_idle_hoursnumeric(8,2)
alarm_countinteger
overspeed_countinteger
utilisation_pctnumeric
tracksolid.v_vehicles_not_moved_todayview

01_BusinessAnalytics.md §2.3. Enabled vehicles with zero trips today.

ColumnTypeNullDefaultComment
imeitext
vehicle_nametext
vehicle_numbertext
driver_nametext
assigned_citytext
last_seentimestamp without time zone
speednumeric(7,2)
tracksolid.set_updated_at(…)function · plpgsql

arguments()
returnstrigger

reporting · Read layer that backs the map dashboards (consumed by dashboard_api).

2 table(s) · 12 view(s) · 4 function(s) documented.

reporting.refresh_logtable3,558 rows

One row per REFRESH MATERIALIZED VIEW CONCURRENTLY reporting.v_trips. Written by dashboard_api's built-in refresher (source='dashboard_api', every 5 min); the retired n8n job (source='n8n') was the previous writer. Read MAX(refreshed_at) for staleness.

ColumnTypeNullDefaultComment
refreshed_attimestamp with time zoneNOT NULLnow()
sourcetextNOT NULL'n8n'::text
duration_msinteger
row_countinteger
notestext
reporting.v_tripsmatview31,670 rows

Canonical trip view, MATERIALIZED for dashboard read latency (see header diagnostic note). All timestamps in Africa/Nairobi. LEFT JOINs devices so trips with no device row keep NULL cost_centre rather than disappearing. Refresh via n8n every 5 min; see reporting.refresh_log. See 260519_trips_kepler_deployment.md §Phase 1+6.

ColumnTypeNullDefaultComment
trip_idbigint
imeitext
device_nametext
vehicle_numbertext
vehicle_modelstext
vehicle_categorytext
cost_centretext
assigned_citytext
assigned_drivertext
start_timetimestamp without time zone
end_timetimestamp without time zone
trip_datedate
start_hourinteger
start_dowinteger
daily_seqbigint
distance_kmnumeric(12,2)
avg_speed_kmhnumeric(7,2)
max_speed_kmhnumeric(7,2)
idle_time_sinteger
driving_time_sinteger
fuel_consumed_lnumeric(8,2)
waypoints_countinteger
start_addresstext
end_addresstext
start_geomgeometry(Point,4326)
end_geomgeometry(Point,4326)
route_geomgeometry(LineString,4326)
route_geojsonjson
is_meaningful_routeboolean
updated_attimestamp without time zone
reporting.v_daily_cost_centreview

Cost-centre × day rollup. Excludes trips with NULL cost_centre.

ColumnTypeNullDefaultComment
trip_datedate
cost_centretext
active_vehiclesbigint
active_driversbigint
trip_countbigint
total_kmnumeric
driving_hoursnumeric
idle_hoursnumeric
idle_pctnumeric
km_per_vehiclenumeric
reporting.v_daily_summaryview

Vehicle × day rollup. Filtered by is_meaningful_route. day_routes_geojson is the daily multi-line geometry for long-range Kepler.gl fallback.

ColumnTypeNullDefaultComment
trip_datedate
cost_centretext
assigned_citytext
vehicle_numbertext
assigned_drivertext
trip_countbigint
total_kmnumeric
driving_hoursnumeric
idle_hoursnumeric
idle_pctnumeric
first_trip_starttimestamp without time zone
last_trip_endtimestamp without time zone
avg_speed_kmhnumeric
max_speed_kmhnumeric
day_routes_geojsonjson
reporting.v_filter_citiesview

Assigned-city dropdown source for the n8n dashboard. Distinct non-null cities.

ColumnTypeNullDefaultComment
assigned_citytext
reporting.v_filter_cost_centresview

Cost-centre dropdown source for the n8n dashboard. Distinct non-null centres.

ColumnTypeNullDefaultComment
cost_centretext
reporting.v_filter_driversview

Driver dropdown source for the n8n dashboard. Distinct non-null drivers.

ColumnTypeNullDefaultComment
drivertext
reporting.v_filter_vehiclesview

Vehicle dropdown source for the n8n dashboard. Plate is the value; drivers column lists every driver historically associated with the vehicle. cost_centre and assigned_city carry the vehicle's most-recent assignment so the frontend can auto-set those dependent dropdowns.

ColumnTypeNullDefaultComment
vehicle_numbertext
driverstext
cost_centretext
assigned_citytext
reporting.v_live_positionsview

Latest known fix per vehicle, deduped to one primary IMEI per normalised plate. Provenance: 260521_liveposition_deployment.md §Phase 1.

ColumnTypeNullDefaultComment
imeitext
vehicle_numbertext
assigned_drivertext
cost_centretext
assigned_citytext
vehicle_categorytext
vehicle_modelstext
mc_typetext
device_kindtext
latdouble precision
lngdouble precision
speednumeric(7,2)
directionnumeric(6,2)
acc_statustext
device_statustext
gps_signalsmallint
gps_numsmallint
current_mileagenumeric(12,2)
loc_desctext
gps_timetimestamp with time zone
updated_attimestamp with time zone
gps_time_eattimestamp without time zone
updated_at_eattimestamp without time zone
source_age_hoursnumeric
reporting.v_monthly_cost_centreview

Cost-centre × month rollup. Executive grain. Excludes trips with NULL cost_centre.

ColumnTypeNullDefaultComment
month_startdate
month_labeltext
cost_centretext
active_vehiclesbigint
active_driversbigint
active_daysbigint
trip_countbigint
total_kmnumeric
driving_hoursnumeric
idle_hoursnumeric
idle_pctnumeric
km_per_vehiclenumeric
reporting.v_monthly_summaryview

Vehicle × month rollup with trend metrics (km_per_active_day, km_per_trip).

ColumnTypeNullDefaultComment
month_startdate
month_labeltext
cost_centretext
assigned_citytext
vehicle_categorytext
vehicle_numbertext
assigned_drivertext
trip_countbigint
active_daysbigint
total_kmnumeric
driving_hoursnumeric
idle_hoursnumeric
idle_pctnumeric
km_per_active_daynumeric
km_per_tripnumeric
avg_speed_kmhnumeric
peak_speed_kmhnumeric
reporting.v_trips_todayview

Today snapshot of reporting.v_trips, filtered to (NOW() AT TIME ZONE 'Africa/Nairobi')::date. Refreshes as trips land throughout the day.

ColumnTypeNullDefaultComment
trip_idbigint
imeitext
device_nametext
vehicle_numbertext
vehicle_modelstext
vehicle_categorytext
cost_centretext
assigned_citytext
assigned_drivertext
start_timetimestamp without time zone
end_timetimestamp without time zone
trip_datedate
start_hourinteger
start_dowinteger
daily_seqbigint
distance_kmnumeric(12,2)
avg_speed_kmhnumeric(7,2)
max_speed_kmhnumeric(7,2)
idle_time_sinteger
driving_time_sinteger
fuel_consumed_lnumeric(8,2)
waypoints_countinteger
start_addresstext
end_addresstext
start_geomgeometry(Point,4326)
end_geomgeometry(Point,4326)
route_geomgeometry(LineString,4326)
route_geojsonjson
is_meaningful_routeboolean
updated_attimestamp without time zone
reporting.v_weekly_cost_centreview

Cost-centre × week rollup. Excludes trips with NULL cost_centre.

ColumnTypeNullDefaultComment
week_startdate
cost_centretext
active_vehiclesbigint
active_driversbigint
active_daysbigint
trip_countbigint
total_kmnumeric
driving_hoursnumeric
idle_hoursnumeric
idle_pctnumeric
km_per_vehiclenumeric
reporting.v_weekly_summaryview

Vehicle × week rollup. Numeric only, no geometry.

ColumnTypeNullDefaultComment
week_startdate
cost_centretext
assigned_citytext
vehicle_numbertext
assigned_drivertext
trip_countbigint
active_daysbigint
total_kmnumeric
driving_hoursnumeric
idle_hoursnumeric
avg_trip_kmnumeric
reporting.fn_live_positions(…)function · plpgsql

Dashboard contract for liveposition.rahamafresh.com. Returns {summary, geojson}. NULL params = wildcard. Reads reporting.v_live_positions (already deduped). Provenance: 260521_liveposition_deployment.md §Phase 2.

argumentsp_cost_centre text DEFAULT NULL::text, p_acc_status text DEFAULT NULL::text
returnsjsonb
reporting.fn_trips_for_map(…)function · plpgsql

Dashboard contract: see 260519_trips_kepler_deployment.md §Phase 2. Args (positional): vehicle_numbers[], driver, cost_centre, assigned_city, start_date, end_date. NULL = wildcard; empty array also = wildcard. Returns {summary, geojson} where each feature carries daily_seq for client-side sequence colouring. Refuses unfiltered ranges >31 days.

argumentsp_vehicle_numbers text[] DEFAULT NULL::text[], p_driver text DEFAULT NULL::text, p_cost_centre text DEFAULT NULL::text, p_assigned_city text DEFAULT NULL::text, p_start_date date DEFAULT NULL::date, p_end_date date DEFAULT NULL::date
returnsjsonb
reporting.fn_vehicle_track(…)function · sql

Returns a GeoJSON Feature(LineString) of the vehicle's last N hours of fixes from tracksolid.position_history. Provenance: 260521_liveposition_deployment.md §Phase 3.

argumentsp_vehicle_number text, p_hours integer DEFAULT 1
returnsjsonb
reporting.normalize_plate(…)function · sql

Canonicalise Kenyan vehicle plates: trim, collapse internal whitespace, and remove the space before a single trailing letter (e.g. "KDS 453 Y" → "KDS 453Y"). Used in v_trips so plate-level grouping/joining works consistently regardless of how the plate was typed into the registry.

argumentsp text
returnstext

ops · Workshop / tickets / odometer integrations.

5 table(s) · 1 view(s) · 0 function(s) documented.

ops.cost_ratestable3 rows

Reference rates for analytics monetisation: fuel price per litre by city, labour cost per hour by role. Resolution order in views: scope_type=city > scope_type=role > scope_type=global.

ColumnTypeNullDefaultComment
rate_keytextNOT NULL
scope_typetextNOT NULLcity | role | global
scope_valuetext
metrictextNOT NULLfuel_per_litre | labour_per_hour
amountnumeric(12,2)NOT NULL
currencytextNOT NULL
effective_fromdateNOT NULLCURRENT_DATE
notestext
created_attimestamp with time zoneNOT NULLnow()
updated_attimestamp with time zoneNOT NULLnow()
ops.kpi_targetstable12 rows

Traffic-light targets per KPI per scope. Resolution order in views: cost_centre > vehicle_category > city > global.

ColumnTypeNullDefaultComment
target_idbigintNOT NULLnextval('ops.kpi_targets_target_id_seq'::regclass)
kpi_keytextNOT NULL
scope_typetextNOT NULL
scope_valuetext
target_valuenumeric(12,2)NOT NULL
amber_thresholdnumeric(12,2)
red_thresholdnumeric(12,2)
directiontextNOT NULL'higher_is_better'::texthigher_is_better -> green when value >= target. lower_is_better -> green when value <= target.
effective_fromdateNOT NULLCURRENT_DATE
notestext
created_attimestamp with time zoneNOT NULLnow()
updated_attimestamp with time zoneNOT NULLnow()
ops.odometer_readingstable0 rows

Physical odometer captures from service, fuel card, or manual entry. Powers §3.8 Odometer Divergence audit.

ColumnTypeNullDefaultComment
reading_idbigintNOT NULLnextval('ops.odometer_readings_reading_id_seq'::regclass)
imeitextNOT NULL
reading_datedateNOT NULL
reading_kmintegerNOT NULL
sourcetextservice | fuel_card | driver_manual | workshop_form
recorded_bytext
created_attimestamp with time zoneNOT NULLnow()
ops.service_logtable0 rows

Workshop service history. Powers §10 Service-Interval Forecaster.

ColumnTypeNullDefaultComment
service_idbigintNOT NULLnextval('ops.service_log_service_id_seq'::regclass)
imeitextNOT NULL
service_datedateNOT NULL
odometer_kmintegerNOT NULLPhysical odometer reading at service time (integer km).
service_typetextscheduled | repair | tyre | bodywork | inspection | other
cost_kesinteger
notestext
created_attimestamp with time zoneNOT NULLnow()
ops.ticketstable0 rows

Skeleton for ticket data sourced from the Fireside ops system. Replace or extend to match the actual feed (Zoho Desk, Freshdesk, etc).

ColumnTypeNullDefaultComment
ticket_idtextNOT NULL
assigned_imeitext
driver_nametext
customertext
job_typetext
prioritytext
statustextNOT NULL'open'::textopen | assigned | in_progress | resolved | cancelled
created_attimestamp with time zoneNOT NULL
assigned_attimestamp with time zone
closed_attimestamp with time zone
job_latdouble precision
job_lngdouble precision
job_geomgeometry(Point,4326)
ingested_attimestamp with time zoneNOT NULLnow()
ops.vw_service_forecastview

Projected next-service date per vehicle based on 30-day km rate. Service interval default 10,000 km — override at query time if needed.

ColumnTypeNullDefaultComment
imeitext
driver_nametext
vehicle_numbertext
last_service_datedate
last_service_odointeger
current_odonumeric(12,2)
km_since_servicenumeric
km_to_next_servicenumeric
km_per_day_30dnumeric
projected_service_datedate

dwh_gold · Nightly ETL aggregates.

2 table(s) · 0 view(s) · 1 function(s) documented.

dwh_gold.dim_vehiclestable0 rows

ColumnTypeNullDefaultComment
vehicle_keyintegerNOT NULLnextval('dim_vehicles_vehicle_key_seq'::regclass)
imeitext
vehicle_numbertext
is_activebooleantrue
dwh_gold.fact_daily_fleet_metricstable0 rows

ColumnTypeNullDefaultComment
daydateNOT NULL
vehicle_keyintegerNOT NULL
total_distance_kmnumeric(12,2)Total km driven that day across all trips
max_speed_kmhnumeric(7,2)
idle_hoursnumeric(5,2)
total_tripsintegerNumber of completed trips
total_drive_hoursnumeric(8,2)Total hours of active driving (engine on + moving)
total_idle_hoursnumeric(8,2)Total hours engine on but stationary
fuel_consumed_lnumeric(10,3)Total fuel consumed in litres (from webhook trip reports)
alarm_countintegerTotal alarm events triggered that day
overspeed_countintegerNumber of overspeed alarm events
day_start_timetime without time zoneTime of first trip start (Africa/Nairobi)
day_end_timetime without time zoneTime of last trip end (Africa/Nairobi)
avg_speed_kmhnumeric(7,2)Fleet average speed across all trips that day
peak_speed_kmhnumeric(7,2)Highest max_speed_kmh recorded across all trips
dwh_gold.refresh_daily_metrics(…)function · plpgsql

Populates or refreshes fact_daily_fleet_metrics for the given date. Call nightly: SELECT dwh_gold.refresh_daily_metrics(CURRENT_DATE - 1);

argumentstarget_date date
returnsvoid

public · Extension objects + pgbouncer auth helper.

1 table(s) · 3 view(s) · 1 function(s) documented.

public.spatial_ref_systable8,500 rows

ColumnTypeNullDefaultComment
sridintegerNOT NULL
auth_namecharacter varying(256)
auth_sridinteger
srtextcharacter varying(2048)
proj4textcharacter varying(2048)
public.geography_columnsview

ColumnTypeNullDefaultComment
f_table_catalogname
f_table_schemaname
f_table_namename
f_geography_columnname
coord_dimensioninteger
sridinteger
typetext
public.geometry_columnsview

ColumnTypeNullDefaultComment
f_table_catalogcharacter varying(256)
f_table_schemaname
f_table_namename
f_geometry_columnname
coord_dimensioninteger
sridinteger
typecharacter varying(30)
public.trips_viz_v1view

ColumnTypeNullDefaultComment
trip_idbigint
imeitext
vehicle_nametext
vehicle_numbertext
cost_centretext
start_timetimestamp with time zone
end_timetimestamp with time zone
distance_kmnumeric(12,2)
avg_speed_kmhnumeric(7,2)
max_speed_kmhnumeric(7,2)
vehicle_platetext
start_addresstext
end_addresstext
waypoints_countinteger
driving_time_sinteger
idle_time_sinteger
fuel_consumed_lnumeric(8,2)
trip_date_eatdate
daily_seqbigint
public.user_lookup(…)function · plpgsql

pgbouncer SCRAM auth_query — returns (username, password-hash) for connection pooling.

argumentsin_user text, OUT uname text, OUT phash text
returnsrecord

6 · Grafana dashboards

Grafana is provisioned via a baked image and reads TimescaleDB directly (read-only role grafana_ro), mostly through the tracksolid.v_* analytics views documented in §5. Two dashboards ship with the stack.

NOC Fleet Operations — Live · uid noc-fleet-live · 9 panels

SectionPanelTypeSource view / table
Total Vehiclesstattracksolid.devices
Online Nowstattracksolid.v_fleet_status
Recent (5-30 min)stattracksolid.v_fleet_status
Offlinestattracksolid.v_fleet_status
Moving Nowstattracksolid.v_fleet_status
Avg Speed (km/h)stattracksolid.v_fleet_status
Live Vehicle Locationsgeomaptracksolid.devices, tracksolid.live_positions
Vehicle Statustabletracksolid.devices, tracksolid.live_positions
Ingestion Healthtabletracksolid.v_ingestion_health

Daily Operations — Fleet & Dispatch · uid daily-ops · 21 panels

SectionPanelTypeSource view / table
Last GPS Fix (fleet)stattracksolid.live_positions
Vehicles reporting todaystattracksolid.v_fleet_today
Fleet km todaystattracksolid.v_fleet_today
Drive hours todaystattracksolid.v_fleet_today
Idle hours todaystattracksolid.v_fleet_today
Open alarms (24h)stattracksolid.alarms
In-flight SLA jobsstattracksolid.v_sla_inflight
Active Vehicles Mapgeomaptracksolid.v_active_dispatch_map
Currently Idle (engine on, speed < 2)tabletracksolid.v_currently_idle
Vehicles Not Moved Todaytabletracksolid.v_vehicles_not_moved_today
Per-Vehicle Daily Roll-uptabletracksolid.v_fleet_today
Driver Leaderboardtabletracksolid.v_driver_aggregates_daily
Fleet Distance — 7-day (by city)timeseriestracksolid.v_fleet_km_daily
Alarm Frequency — 30-day (by type)timeseriestracksolid.v_alarms_daily
Idle Cost (month-to-date)stattracksolid.v_utilisation_daily
Utilisation Heatmap (30-day)heatmaptracksolid.v_utilisation_daily
Row 7 — Field-Service SLAs (data-gated)Dispatch SLA (median mins, 24h)stattracksolid.v_sla_inflight
En-route SLA (median mins, 24h)stattracksolid.v_sla_inflight
On-site SLA (median mins, 24h)stattracksolid.v_sla_inflight
Resolution SLA (median mins, 24h)stattracksolid.v_sla_inflight
At-risk ticketstabletracksolid.v_sla_inflight

SLA panels (v_sla_inflight) and the utilisation heatmap (v_utilisation_daily) are data-gated on the ops ticket integration and nightly dwh_gold ETL respectively.

7 · Operational notes