-- 17_fleetops_fuel_view.sql -- FleetOps fuel roll-up source: reporting.v_fuel_daily. -- -- Backs GET /analytics/fuel in dashboard_api_rev.py (the FleetOps SPA). It pairs -- ACTUAL fuel (trips.fuel_consumed_l, from the /pushtripreport webhook) with an -- ESTIMATED figure (distance_km * devices.fuel_100km / 100) so the SPA can show -- both and flag the gap. -- -- Why a view (not a direct join in the API): it encapsulates the -- reporting.v_trips -> tracksolid.devices join so the read-only staging role only -- needs SELECT on this one reporting.* object, not on tracksolid.devices. It reuses -- the same per-trip grain + is_meaningful_route filter as the other reporting -- summaries (migration 11), and the same imei key v_trips already exposes. -- -- Data state (2026-06-10): devices.fuel_100km is NULL fleet-wide and the /pushoil -- + /pushobd webhooks are unregistered, so estimated_fuel_l is NULL today and -- actual_fuel_l is sparse. The view is correct now and fills in as data lands — -- the API surfaces availability flags rather than faking numbers. Fuel-cost -- monetisation is intentionally absent: ops.cost_rates was purged 2026-06-05 -- (migration 12). -- -- CREATE OR REPLACE + guarded grant -> safe to re-apply. SET search_path = reporting, tracksolid, public; CREATE OR REPLACE VIEW reporting.v_fuel_daily AS SELECT t.trip_date, t.vehicle_number, t.cost_centre, t.assigned_city, t.assigned_driver, t.imei, t.distance_km, t.fuel_consumed_l AS actual_fuel_l, CASE WHEN d.fuel_100km IS NOT NULL AND t.distance_km IS NOT NULL THEN round(t.distance_km * d.fuel_100km / 100.0, 3) ELSE NULL::numeric END AS estimated_fuel_l FROM reporting.v_trips t LEFT JOIN tracksolid.devices d ON d.imei = t.imei WHERE t.is_meaningful_route; COMMENT ON VIEW reporting.v_fuel_daily IS 'Per-trip fuel: actual (trips.fuel_consumed_l) vs estimated (distance_km * devices.fuel_100km/100). ' 'Source for dashboard_api GET /analytics/fuel. Encapsulates the v_trips->devices join so the ' 'read-only staging role needs SELECT only on this view. fuel_100km is NULL fleet-wide as of 2026-06-10.'; -- ── grants (guarded: roles may not exist on a fresh DB) ─────────────────────── DO $grants$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ro') THEN GRANT USAGE ON SCHEMA reporting TO grafana_ro; GRANT SELECT ON reporting.v_fuel_daily TO grafana_ro; END IF; END $grants$;