feat(analytics): add v_driver_clock_daily/today views for tardiness monitoring
Two read-only views in the tracksolid schema feeding n8n's working-hours checks: per-IMEI per-Nairobi-day reporting/closing times, start/end locations + Nominatim addresses, and trip-count/km/drive-hours context. No policy embedded; cost-centre filtering and tardiness thresholds live in n8n. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
f94d14864f
commit
737ca67712
1 changed files with 111 additions and 0 deletions
111
10_driver_clock_views.sql
Normal file
111
10_driver_clock_views.sql
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
-- 10_driver_clock_views.sql
|
||||
-- Driver clock-in / clock-out views for n8n tardiness + working-hours monitoring.
|
||||
--
|
||||
-- Two views, both keyed by IMEI per local Africa/Nairobi date:
|
||||
-- • v_driver_clock_daily — historical, one row per IMEI per day with activity
|
||||
-- • v_driver_clock_today — thin pass-through filtered to today (EAT)
|
||||
--
|
||||
-- The view exposes raw times, locations, and addresses; n8n owns tardiness
|
||||
-- thresholds and cost-centre filtering. Closing time is the latest end_time
|
||||
-- of any trip whose start_time falls on the local Nairobi date — kept lossless
|
||||
-- so n8n can detect midnight crossings via reporting_ts/closing_ts.
|
||||
--
|
||||
-- Reuses:
|
||||
-- • tracksolid.trips.distance_km (renamed in migration 04)
|
||||
-- • tracksolid.trips.driving_time_s (referenced in migration 05)
|
||||
-- • tracksolid.trips.start_geom/end_geom (migration 02 §3.06)
|
||||
-- • tracksolid.trips.start_address/end_address (migration 09 — Nominatim)
|
||||
--
|
||||
-- Pattern follows 07_analytics_views.sql: regular views (not materialised),
|
||||
-- COMMENT ON VIEW with provenance, GRANT SELECT TO grafana_ro.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- v_driver_clock_daily
|
||||
-- One row per IMEI per local Africa/Nairobi date with at least one trip.
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
CREATE OR REPLACE VIEW tracksolid.v_driver_clock_daily AS
|
||||
WITH daily_agg AS (
|
||||
SELECT
|
||||
t.imei,
|
||||
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS report_date,
|
||||
MIN(t.start_time) AS reporting_ts,
|
||||
MAX(t.end_time) AS closing_ts,
|
||||
COUNT(*) AS trips_count,
|
||||
SUM(t.distance_km) AS total_km,
|
||||
SUM(t.driving_time_s)::numeric / 3600 AS drive_hours
|
||||
FROM tracksolid.trips t
|
||||
GROUP BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date
|
||||
),
|
||||
start_row AS (
|
||||
SELECT DISTINCT ON (t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date)
|
||||
t.imei,
|
||||
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS report_date,
|
||||
ST_Y(t.start_geom::geometry) AS start_lat,
|
||||
ST_X(t.start_geom::geometry) AS start_lng,
|
||||
t.start_address AS start_address
|
||||
FROM tracksolid.trips t
|
||||
ORDER BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date, t.start_time ASC
|
||||
),
|
||||
end_row AS (
|
||||
SELECT DISTINCT ON (t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date)
|
||||
t.imei,
|
||||
(t.start_time AT TIME ZONE 'Africa/Nairobi')::date AS report_date,
|
||||
ST_Y(t.end_geom::geometry) AS end_lat,
|
||||
ST_X(t.end_geom::geometry) AS end_lng,
|
||||
t.end_address AS end_address
|
||||
FROM tracksolid.trips t
|
||||
ORDER BY t.imei, (t.start_time AT TIME ZONE 'Africa/Nairobi')::date, t.end_time DESC NULLS LAST
|
||||
)
|
||||
SELECT
|
||||
a.imei,
|
||||
d.driver_name,
|
||||
d.vehicle_number,
|
||||
d.cost_centre,
|
||||
COALESCE(d.assigned_city, d.city, 'unassigned') AS assigned_city,
|
||||
a.report_date,
|
||||
(a.reporting_ts AT TIME ZONE 'Africa/Nairobi')::time AS reporting_time,
|
||||
(a.closing_ts AT TIME ZONE 'Africa/Nairobi')::time AS closing_time,
|
||||
a.reporting_ts,
|
||||
a.closing_ts,
|
||||
s.start_lat,
|
||||
s.start_lng,
|
||||
s.start_address,
|
||||
e.end_lat,
|
||||
e.end_lng,
|
||||
e.end_address,
|
||||
a.trips_count,
|
||||
a.total_km,
|
||||
a.drive_hours
|
||||
FROM daily_agg a
|
||||
LEFT JOIN start_row s ON s.imei = a.imei AND s.report_date = a.report_date
|
||||
LEFT JOIN end_row e ON e.imei = a.imei AND e.report_date = a.report_date
|
||||
LEFT JOIN tracksolid.devices d ON d.imei = a.imei;
|
||||
|
||||
COMMENT ON VIEW tracksolid.v_driver_clock_daily IS
|
||||
'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).';
|
||||
|
||||
GRANT SELECT ON tracksolid.v_driver_clock_daily TO grafana_ro;
|
||||
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- v_driver_clock_today
|
||||
-- Pass-through filter: today's row from v_driver_clock_daily.
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
CREATE OR REPLACE VIEW tracksolid.v_driver_clock_today AS
|
||||
SELECT *
|
||||
FROM tracksolid.v_driver_clock_daily
|
||||
WHERE report_date = (NOW() AT TIME ZONE 'Africa/Nairobi')::date;
|
||||
|
||||
COMMENT ON VIEW tracksolid.v_driver_clock_today IS
|
||||
'Today snapshot of v_driver_clock_daily, filtered to (NOW() AT TIME ZONE '
|
||||
'''Africa/Nairobi'')::date. Refreshes as trips land throughout the day.';
|
||||
|
||||
GRANT SELECT ON tracksolid.v_driver_clock_today TO grafana_ro;
|
||||
|
||||
COMMIT;
|
||||
Loading…
Reference in a new issue