-- migrate:up -- -- Tracksolid's device_name field is a free-form admin tag. In this fleet it -- follows the convention "{driver name} - {plate}[_cam]" for ~90% of devices: -- "John Mbugua - KDW 573B_cam" → driver "John Mbugua" -- "Parked - KMGK 596V" → no driver (placeholder tag) -- "JC400P-92732" → no driver (device serial) -- -- Extract a best-effort driver name so the popup can show it pre-emptively, -- ahead of the proper driver-roster work in P3 (PRD F3.10-F3.13). When the -- HR-synced roster lands, this helper becomes redundant and gets removed. CREATE OR REPLACE FUNCTION serve._driver_name(device_name text) RETURNS text LANGUAGE sql IMMUTABLE AS $$ SELECT CASE WHEN m IS NULL THEN NULL WHEN lower(m[1]) IN ('parked', 'unassigned', 'spare', 'available') THEN NULL WHEN m[1] ~ '^[0-9_]+$' THEN NULL ELSE m[1] END FROM (SELECT regexp_match(COALESCE(device_name, ''), '^(.+?) - .+$') AS m) p $$; DROP FUNCTION IF EXISTS serve.fn_live_view(jsonb); CREATE OR REPLACE FUNCTION serve.fn_live_view(filters jsonb) RETURNS jsonb LANGUAGE plpgsql STABLE AS $$ DECLARE fresh_window interval := COALESCE((filters->>'fresh_window')::interval, interval '24 hours'); offline_after interval := COALESCE((filters->>'offline_after')::interval, interval '5 minutes'); move_speed_kmh numeric := COALESCE((filters->>'move_speed_kmh')::numeric, 5); p_cost_centre text := filters->>'cost_centre'; p_assigned_city text := filters->>'assigned_city'; p_vehicle_numbers text[] := CASE WHEN filters ? 'vehicle_numbers' THEN ARRAY(SELECT jsonb_array_elements_text(filters->'vehicle_numbers')) ELSE NULL END; result jsonb; BEGIN WITH candidates AS ( SELECT lp.imei, lp.occurred_at, lp.geom, lp.speed_kmh, lp.direction_deg, lp.mc_type, lp.current_mileage_km, lp.gps_signal, lp.satellites, lp.device_name, lp.pos_type, d.device_type, d.activation_at, v.vehicle_id, v.plate, v.cost_centre, v.assigned_city FROM state.live_positions lp JOIN domain.devices d ON d.imei = lp.imei JOIN domain.vehicles v ON v.vehicle_id = d.vehicle_id WHERE d.lifecycle = 'active' AND (p_cost_centre IS NULL OR v.cost_centre = p_cost_centre) AND (p_assigned_city IS NULL OR v.assigned_city = p_assigned_city) AND (p_vehicle_numbers IS NULL OR v.plate = ANY (p_vehicle_numbers)) ), ranked AS ( SELECT c.*, ROW_NUMBER() OVER ( PARTITION BY c.vehicle_id ORDER BY CASE c.device_type WHEN 'tracker' THEN 0 ELSE 1 END, CASE WHEN c.occurred_at > now() - fresh_window THEN 0 ELSE 1 END, c.occurred_at DESC, c.activation_at DESC NULLS LAST ) AS rn FROM candidates c ), deduped AS (SELECT * FROM ranked WHERE rn = 1), enriched AS ( SELECT d.*, CASE WHEN d.occurred_at <= now() - offline_after THEN 'offline' WHEN d.speed_kmh IS NOT NULL AND d.speed_kmh > move_speed_kmh THEN 'moving' ELSE 'parked' END AS operational_state, serve._cost_centre_color(d.cost_centre) AS cost_centre_color, EXTRACT(EPOCH FROM (now() - d.occurred_at))::int AS age_sec, round(ST_Y(d.geom)::numeric, 4) AS lat_rounded, round(ST_X(d.geom)::numeric, 4) AS lng_rounded FROM deduped d ), with_addr AS ( SELECT e.*, g.address, g.address_short FROM enriched e LEFT JOIN state.geocoded_positions g ON g.lat_rounded = e.lat_rounded AND g.lng_rounded = e.lng_rounded ), summary AS ( SELECT jsonb_build_object( 'total_active', count(*), 'moving', count(*) FILTER (WHERE operational_state = 'moving'), 'parked', count(*) FILTER (WHERE operational_state = 'parked'), 'offline', count(*) FILTER (WHERE operational_state = 'offline'), 'below_freshness_slo', count(*) FILTER ( WHERE occurred_at <= now() - interval '90 seconds' ), 'as_of', to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"') ) AS s FROM with_addr ), features AS ( SELECT COALESCE(jsonb_agg( jsonb_build_object( 'type', 'Feature', 'geometry', ST_AsGeoJSON(e.geom)::jsonb, 'properties', jsonb_build_object( 'vehicle_id', e.vehicle_id, 'plate', e.plate, 'plate_short', serve._label_short(e.device_name, e.plate), 'driver_name', serve._driver_name(e.device_name), 'imei', e.imei, 'device_type', e.device_type, 'device_name', e.device_name, 'mc_type', e.mc_type, 'pos_type', e.pos_type, 'cost_centre', e.cost_centre, 'cost_centre_color', e.cost_centre_color, 'assigned_city', e.assigned_city, 'address', e.address, 'address_short', e.address_short, 'occurred_at', to_char(e.occurred_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"'), 'age_sec', e.age_sec, 'speed_kmh', e.speed_kmh, 'heading_deg', e.direction_deg, 'gps_signal', e.gps_signal, 'satellites', e.satellites, 'current_mileage_km', e.current_mileage_km, 'operational_state', e.operational_state, 'style_class', 'vehicle-' || e.operational_state, 'marker_color', CASE WHEN e.operational_state = 'moving' THEN e.cost_centre_color ELSE '#9ca3af' END, 'show_arrow', (e.operational_state = 'moving' AND e.direction_deg IS NOT NULL) ) ) ), '[]'::jsonb) AS feats FROM with_addr e ), slo_block AS ( SELECT COALESCE(jsonb_object_agg( metric, jsonb_build_object('threshold', threshold, 'current', current_value, 'status', status) ), '{}'::jsonb) AS ss FROM slo.v_current_status ) SELECT jsonb_build_object( 'summary', (SELECT s FROM summary), 'geojson', jsonb_build_object('type', 'FeatureCollection', 'features', (SELECT feats FROM features)), 'slo_status', (SELECT ss FROM slo_block) ) INTO result; RETURN result; END; $$; -- migrate:down DROP FUNCTION IF EXISTS serve.fn_live_view(jsonb); DROP FUNCTION IF EXISTS serve._driver_name(text);