-- 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;