gendesign/data/sql/134_planning_projects.sql
lekss361 9e4348629b
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m36s
Deploy / build-worker (push) Successful in 2m20s
Deploy / deploy (push) Successful in 1m14s
feat(sf): ППТ/ПМТ WFS ingest → planning_projects (future-supply, #1104)
Миграция 134_planning_projects.sql + planning_harvest.py: ингест утверждённых ППТ/ПМТ ЕКБ из геопортал-WFS (один BBOX-запрос на слой, geom уже 4326 → SetSRID без Transform) → planning_projects (project_type/source_key UNIQUE, doc_status/год). SAVEPOINT per-row, beat monthly (1-е 06:00). Зависит от TLS-фикса #1103. Документ-центричная таблица отдельно от ird_overlays. 3 теста. ТЭП/PDF — follow-up.

Refs #1085.
Co-authored-by: lekss361 <lekss361@gendsgn.local>
Co-committed-by: lekss361 <lekss361@gendsgn.local>
2026-06-06 20:25:23 +00:00

78 lines
6.1 KiB
PL/PgSQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 134_planning_projects.sql
-- #1085 (Site Finder v2 / future-supply «GG-форсайт») — store ППТ/ПМТ ЕКБ (геометрия + реквизиты).
--
-- Future-supply: что/где утверждено к застройке. Источник — ЕКБ-геопортал GeoServer WFS
-- (ekb_geoportal_client.py, #1083): слои portal_geo_dmd_prj_plan (ППТ — проекты планировки) и
-- portal_geo_dmd_prj_mej (ПМТ — проекты межевания). Каждая фича — утверждённый документ
-- планировки с геометрией охвата + doc_status/год (live-verified 2026-06-06, vault research/
-- EKB_Geoportal_WFS_Construction_Intel_Jun06).
--
-- ОТДЕЛЬНАЯ таблица (не ird_overlays м.132): ird_overlays — НСПД-ограничения участка (per-feature
-- ЗОУИТ/ПЗЗ/ОКН + reg_numb_border + category/subcategory), а тут документ-центричная модель
-- геопортала (doc_status / dmd_actual_year / project_name / full_name) из другого источника (WFS,
-- уже EPSG:4326). Смешивать схемы — натяжка; держим раздельно, analyze читает overlap отдельно.
--
-- Что отдаёт WFS-фича (DescribeFeatureType + live): key (стабильный id портала), full_name
-- (документ-описание), doc_full_name/doc_status/doc_status_name (статус утверждения),
-- dmd_actual_year (год актуальности), project_name, geoloc (геометрия 4326).
--
-- Зерно (grain): одна строка = одна WFS-фича (один документ планировки) в слое. Дедуп-ключ —
-- (project_type, source_key): source_key = портальный `key`; project_type 'ppt'|'pmt'.
-- re-harvest UPSERT-ит (latest wins): документы стабильны, обновление = свежий fetched_at.
--
-- ТЭП/очередность из PDF пояснительных записок (pdfplumber) — отдельный проход (#1085 follow-up);
-- колонки tep/staging добавятся ALTER-ом позже (тут только WFS-слой: геометрия + статус).
--
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN). Idempotent:
-- CREATE TABLE/INDEX IF NOT EXISTS + guarded DO для UNIQUE (прецедент м.125/132/133).
BEGIN;
-- ── 1. Таблица planning_projects ───────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS planning_projects (
id BIGSERIAL PRIMARY KEY,
project_type TEXT NOT NULL, -- 'ppt' (проект планировки) | 'pmt' (проект межевания)
source_key BIGINT NOT NULL, -- стабильный `key` фичи геопортала (дедуп внутри типа)
full_name TEXT, -- описание документа (ПАГЕ № / «Об утверждении ...»)
doc_full_name TEXT, -- doc_full_name WFS
doc_status TEXT, -- doc_status (код/строка статуса утверждения)
doc_status_name TEXT, -- читаемый статус ('действующий'/'утверждён'/...)
project_name TEXT, -- project_name WFS
dmd_actual_year INTEGER, -- год актуальности документа (dmd_actual_year)
geom geometry(Geometry, 4326) NOT NULL, -- охват документа (WFS geoloc, уже 4326)
raw_props JSONB, -- полный properties фичи (forward-compat / ТЭП-резолв)
fetched_at timestamptz NOT NULL DEFAULT now(), -- когда harvest снял (freshness)
CONSTRAINT planning_projects_type_chk CHECK (project_type IN ('ppt', 'pmt')),
CONSTRAINT planning_projects_source_key_chk CHECK (source_key > 0)
);
COMMENT ON TABLE planning_projects IS
'ППТ/ПМТ ЕКБ (#1085, future-supply GG-форсайт): утверждённые проекты планировки/межевания из '
'ЕКБ-геопортала WFS (portal_geo_dmd_prj_plan/_mej). 1 строка = 1 WFS-фича (документ). UPSERT '
'harvest-воркером по uq_planning_projects (project_type, source_key). analyze читает overlap '
'участка через ST_Intersects(geom). ТЭП/очередность из PDF — отдельный проход (follow-up).';
COMMENT ON COLUMN planning_projects.source_key IS 'Стабильный `key` фичи ЕКБ-геопортала — дедуп-ключ внутри project_type';
COMMENT ON COLUMN planning_projects.doc_status_name IS 'Читаемый статус утверждения документа планировки (действующий/утверждён/...)';
-- ── 2. Дедуп/UPSERT-ключ (project_type, source_key) ────────────────────────────
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'uq_planning_projects'
) THEN
ALTER TABLE planning_projects
ADD CONSTRAINT uq_planning_projects
UNIQUE (project_type, source_key);
END IF;
END
$$;
-- ── 3. Индексы ─────────────────────────────────────────────────────────────────
-- Главный read-path: spatial overlap участка (analyze: ST_Intersects(parcel.geom, pp.geom)).
CREATE INDEX IF NOT EXISTS idx_planning_projects_geom
ON planning_projects USING GIST (geom);
-- Фильтр по типу проекта (выборка «все ППТ» / «все ПМТ»).
CREATE INDEX IF NOT EXISTS idx_planning_projects_type
ON planning_projects (project_type);
COMMIT;