72 lines
4.5 KiB
PL/PgSQL
72 lines
4.5 KiB
PL/PgSQL
-- 139_ekb_genplan_functional_zone.sql
|
||
-- #1058 / #1067 (Site Finder v2, «GG-форсайт») — функциональные зоны генплана ЕКБ-2045.
|
||
--
|
||
-- Источник: ГИСОГД-СО WFS (gisogd66.midural.ru), слой
|
||
-- agate_ekbgo:agate_ekbgo_geo_urban_10_functional_zone_<hash>.
|
||
-- Harvest-воркер: tasks/genplan_zones_sync.py (Celery beat «genplan-zones-sync-weekly»).
|
||
-- Read-side: app/services/site_finder/functional_zone_lookup.py → parcel_functional_zones().
|
||
-- Analyze-врезка: follow-up после merge #1131 (чтобы не конфликтить с ird-analyze PR).
|
||
--
|
||
-- Grain: одна строка = одна зона (Polygon/MultiPolygon). Дедуп-ключ — globalid (UUID из ГИСОГД).
|
||
--
|
||
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN). Idempotent:
|
||
-- CREATE TABLE/INDEX IF NOT EXISTS + guarded DO-блок для UNIQUE (зеркаль м.132, м.125).
|
||
-- НИКАКИХ строк здесь не вставляется — данные приходят из harvest-воркера.
|
||
|
||
BEGIN;
|
||
|
||
-- ── 1. Таблица ekb_genplan_functional_zone ────────────────────────────────────
|
||
CREATE TABLE IF NOT EXISTS ekb_genplan_functional_zone (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
globalid TEXT NOT NULL, -- UUID из ГИСОГД (дедуп-ключ, UNIQUE ниже)
|
||
zone_type TEXT, -- читаемый тип зоны (full_name / urban10_classid_v)
|
||
zone_class_code TEXT, -- числовой код класса (urban10_classid)
|
||
status TEXT, -- «Существующий» / «Планируемый» (urban10_status_v)
|
||
area_ha NUMERIC, -- площадь, га (urban10_area)
|
||
doc_ref TEXT, -- ссылка на документ генплана (info_set_key_ref)
|
||
geom geometry(Geometry, 4326) NOT NULL, -- Polygon/MultiPolygon, EPSG:4326
|
||
raw_props JSONB, -- полный properties фичи (forward-compat / debug)
|
||
fetched_at timestamptz NOT NULL DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE ekb_genplan_functional_zone IS
|
||
'Функциональные зоны генплана ЕКБ-2045 (#1058, GG-форсайт). '
|
||
'Источник: ГИСОГД-СО WFS (gisogd66.midural.ru). '
|
||
'UPSERT harvest-воркером tasks/genplan_zones_sync.py по globalid. '
|
||
'analyze читает overlap участка через ST_Intersects(geom). Пустая = 0 overlap.';
|
||
|
||
COMMENT ON COLUMN ekb_genplan_functional_zone.globalid IS
|
||
'UUID объекта из ГИСОГД-СО (urban10_globalid); дедуп-ключ UPSERT';
|
||
COMMENT ON COLUMN ekb_genplan_functional_zone.zone_type IS
|
||
'Читаемый тип зоны: full_name или urban10_classid_v («Жилые зоны» и т.д.)';
|
||
COMMENT ON COLUMN ekb_genplan_functional_zone.zone_class_code IS
|
||
'Числовой код класса зоны (urban10_classid)';
|
||
|
||
-- ── 2. UNIQUE по globalid (дедуп для UPSERT) ─────────────────────────────────
|
||
-- Guard через pg_constraint — idempotent re-apply (зеркаль м.132 / м.125 / м.110).
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (
|
||
SELECT 1 FROM pg_constraint WHERE conname = 'uq_ekb_genplan_functional_zone_globalid'
|
||
) THEN
|
||
ALTER TABLE ekb_genplan_functional_zone
|
||
ADD CONSTRAINT uq_ekb_genplan_functional_zone_globalid
|
||
UNIQUE (globalid);
|
||
END IF;
|
||
END
|
||
$$;
|
||
|
||
-- ── 3. Индексы ────────────────────────────────────────────────────────────────
|
||
-- Read-path: ST_Intersects(parcel.geom, zone.geom) через GIST.
|
||
CREATE INDEX IF NOT EXISTS idx_ekb_genplan_fz_geom
|
||
ON ekb_genplan_functional_zone USING GIST (geom);
|
||
|
||
-- Фильтрация по типу зоны (выборка «все жилые» / «все производственные»).
|
||
CREATE INDEX IF NOT EXISTS idx_ekb_genplan_fz_zone_type
|
||
ON ekb_genplan_functional_zone (zone_type);
|
||
|
||
-- Фильтрация по статусу (существующие vs планируемые).
|
||
CREATE INDEX IF NOT EXISTS idx_ekb_genplan_fz_status
|
||
ON ekb_genplan_functional_zone (status) WHERE status IS NOT NULL;
|
||
|
||
COMMIT;
|