feat(workbench): add runtime GIS and sample integrations

This commit is contained in:
2026-09-22 10:44:31 +08:00
parent a3b4e75317
commit 7ab9b36a5e
62 changed files with 6685 additions and 51 deletions
+122
View File
@@ -0,0 +1,122 @@
DO $$
DECLARE
layer RECORD;
BEGIN
FOR layer IN
SELECT *
FROM (VALUES
('fx_20200423_drain_valves', 'fx_20200423_drain_valves', 'Point'),
('fx_20200423_service_connections', 'fx_20200423_service_connections', 'Point'),
('fx_20200423_flow_meters', 'fx_20200423_flow_meters', 'Point'),
('fx_20200423_hydrants', 'fx_20200423_hydrants', 'Point'),
('fx_20200423_customer_meters', 'fx_20200423_customer_meters', 'Point'),
('fx_20200423_pipes', 'fx_20200423_pipes', 'LineString'),
('fx_20200423_valves', 'fx_20200423_valves', 'Point'),
('fx_20200423_non_residential_meters', 'fx_20200423_non_residential_meters', 'Point'),
('fx_20200811_dn100_pipes', 'fx_20200811_dn100_pipes', 'LineString')
) AS configured(view_name, layer_key, geometry_type)
LOOP
IF to_regclass(format('gis.%I', layer.view_name)) IS NULL THEN
EXECUTE format(
$view$
CREATE MATERIALIZED VIEW gis.%I AS
SELECT
feature.source_fid::text AS id,
feature.source_fid,
feature.source_object_id,
feature.source_diameter AS diameter,
CASE
WHEN GeometryType(feature.geom) IN ('LINESTRING', 'MULTILINESTRING')
THEN ST_Length(feature.geom)
ELSE NULL
END AS length,
dataset.dataset_key,
dataset.title AS dataset_title,
dataset.source_date,
source_layer.layer_key AS source_layer_key,
source_layer.display_name AS source_layer_name,
source_layer.feature_kind,
ST_Transform(feature.geom, 3857)::geometry(%s, 3857) AS geom
FROM source_gis.features AS feature
JOIN source_gis.layers AS source_layer
ON source_layer.layer_key = feature.layer_key
JOIN source_gis.datasets AS dataset
ON dataset.dataset_key = source_layer.dataset_key
WHERE feature.layer_key = %L
AND feature.geom IS NOT NULL
WITH DATA
$view$,
layer.view_name,
layer.geometry_type,
layer.layer_key
);
END IF;
EXECUTE format(
'CREATE UNIQUE INDEX IF NOT EXISTS %I ON gis.%I (id)',
'ux_' || layer.view_name || '_id',
layer.view_name
);
EXECUTE format(
'CREATE INDEX IF NOT EXISTS %I ON gis.%I USING GIST (geom)',
'ix_' || layer.view_name || '_geom',
layer.view_name
);
END LOOP;
END
$$;
DROP VIEW IF EXISTS gis.water_quality_monitoring_points;
CREATE VIEW gis.water_quality_monitoring_points AS
WITH latest_result AS (
SELECT
run.run_id,
run.name AS source_analysis,
run.created_at,
result.payload
FROM analysis.runs AS run
JOIN LATERAL (
SELECT stored.payload
FROM analysis.results AS stored
WHERE stored.run_id = run.run_id
AND stored.result_type = 'sensor_placement'
ORDER BY stored.created_at DESC, stored.result_id DESC
LIMIT 1
) AS result ON true
WHERE run.run_type = 'sensor_placement'
AND run.status = 'completed'
AND result.payload->>'sensor_type' = 'water_quality'
AND jsonb_typeof(result.payload->'sensor_locations') = 'array'
ORDER BY run.created_at DESC, run.run_id DESC
LIMIT 1
), ranked_locations AS (
SELECT
latest.run_id,
latest.source_analysis,
latest.created_at,
latest.payload,
location.node_id,
location.rank
FROM latest_result AS latest
CROSS JOIN LATERAL jsonb_array_elements_text(
latest.payload->'sensor_locations'
) WITH ORDINALITY AS location(node_id, rank)
)
SELECT
ranked.node_id AS id,
ranked.node_id,
ranked.rank::integer AS monitoring_point_no,
ranked.run_id,
ranked.source_analysis,
ranked.created_at,
ranked.payload->>'method' AS selection_method,
(ranked.payload->>'minimum_diameter')::integer AS minimum_diameter,
junction.elevation,
junction.geom
FROM ranked_locations AS ranked
JOIN gis.junctions AS junction
ON junction.id = ranked.node_id;
COMMENT ON VIEW gis.water_quality_monitoring_points IS
'Current water-quality monitoring points selected by the sensitivity service.';