79 lines
5.8 KiB
PL/PgSQL
79 lines
5.8 KiB
PL/PgSQL
-- 136_land_reservation.sql
|
||
-- #1091 / #1062 (ИРД-5, «GG-форсайт» #1067) — хранилище ЗУ под изъятие/резервирование.
|
||
--
|
||
-- Геометрии зон изъятия/резервирования НЕТ ни в одном spatial-источнике (НСПД/геопортал/ГИСОГД
|
||
-- проверены пусто, vault research 2026-06). Перечень ЗУ существует ТОЛЬКО текстом в постановлениях
|
||
-- (PDF, pravo.gov66.ru / ПАГЕ). Геометрию получаем join'ом кад-номера к cad_parcels.geom — это
|
||
-- покрывает read-side analyse без хранения геометрии здесь.
|
||
--
|
||
-- Что/зачем: per-parcel флаг «в действующем постановлении №X об изъятии/резервировании» + ссылка
|
||
-- на документ. Парсер текста постановлений (page_reservation_parser.py) извлекает кад-номера и
|
||
-- метаданные акта; ingest-task пишет сюда; reservation_lookup.py читает для analyze.
|
||
--
|
||
-- Grain: одна строка = один кад-номер в одном акте (cad_num, act_number — дедуп-ключ).
|
||
-- Источник: pravo.gov66.ru PDF-постановления (seed: 509-ПП Правительства СО, ул. Татищева ЕКБ).
|
||
--
|
||
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN). Idempotent
|
||
-- (ре-apply дважды чисто): CREATE TABLE/INDEX IF NOT EXISTS + guarded DO-блок для UNIQUE
|
||
-- (constraint нельзя добавить дважды → guard по pg_constraint, прецедент м.132).
|
||
-- НИКАКИХ строк здесь не вставляется (данные приходят из reservation_ingest task).
|
||
|
||
BEGIN;
|
||
|
||
-- ── 1. Таблица land_reservation ───────────────────────────────────────────────
|
||
CREATE TABLE IF NOT EXISTS land_reservation (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
cad_num TEXT NOT NULL, -- кадастровый номер ЗУ (66:41:XXXXXXX:NN)
|
||
reservation_kind TEXT NOT NULL, -- 'изъятие' | 'резервирование'
|
||
basis_act TEXT NOT NULL, -- «Постановление Правительства СО № 509-ПП»
|
||
act_number TEXT, -- «509-ПП» (None если не распарсилось)
|
||
act_date DATE, -- дата акта (NULL если не распарсилось)
|
||
purpose TEXT, -- цель (реконструкция ул. Татищева, ...)
|
||
doc_url TEXT, -- ссылка на PDF/страницу
|
||
source TEXT NOT NULL DEFAULT 'page_pdf', -- источник: page_pdf | ...
|
||
is_active BOOLEAN NOT NULL DEFAULT true, -- актуальное постановление
|
||
raw_excerpt TEXT, -- ±120 символов вокруг первого кад-номера
|
||
fetched_at timestamptz NOT NULL DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE land_reservation IS
|
||
'ЗУ под изъятие/резервирование (#1091/#1062, GG-форсайт #1067). 1 строка = 1 кад-номер '
|
||
'в 1 постановлении. Геометрия не хранится — join к cad_parcels.geom на read-side. '
|
||
'Парсер page_reservation_parser.py извлекает кад-номера из PDF-постановлений; '
|
||
'reservation_lookup.py читает для analyze.';
|
||
|
||
COMMENT ON COLUMN land_reservation.cad_num IS 'Кадастровый номер ЗУ вида 66:41:XXXXXXX:NN';
|
||
COMMENT ON COLUMN land_reservation.reservation_kind IS 'изъятие | резервирование';
|
||
COMMENT ON COLUMN land_reservation.basis_act IS 'Читаемое описание акта-основания';
|
||
COMMENT ON COLUMN land_reservation.act_number IS 'Номер постановления (509-ПП, NNN-ПА и т.п.)';
|
||
COMMENT ON COLUMN land_reservation.raw_excerpt IS '±120 симв. вокруг первого кад-номера; debug/верификация';
|
||
|
||
-- ── 2. Дедуп/UPSERT-ключ (cad_num, act_number) ───────────────────────────────
|
||
-- Guard по pg_constraint → idempotent re-apply (constraint нельзя добавить дважды).
|
||
-- Прецедент: м.132 (uq_ird_overlays_feature).
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (
|
||
SELECT 1 FROM pg_constraint WHERE conname = 'uq_land_reservation_cad_act'
|
||
) THEN
|
||
ALTER TABLE land_reservation
|
||
ADD CONSTRAINT uq_land_reservation_cad_act
|
||
UNIQUE (cad_num, act_number);
|
||
END IF;
|
||
END
|
||
$$;
|
||
|
||
-- ── 3. Индексы ────────────────────────────────────────────────────────────────
|
||
-- Основной read-path: lookup по кад-номеру (reservation_lookup.py → analyze).
|
||
CREATE INDEX IF NOT EXISTS idx_land_reservation_cad_num
|
||
ON land_reservation (cad_num);
|
||
|
||
-- Фильтр активных постановлений (is_active=true — рабочий подмножество).
|
||
CREATE INDEX IF NOT EXISTS idx_land_reservation_active
|
||
ON land_reservation (cad_num) WHERE is_active;
|
||
|
||
-- Lookup по номеру акта (cross-ref / ручные проверки).
|
||
CREATE INDEX IF NOT EXISTS idx_land_reservation_act_number
|
||
ON land_reservation (act_number) WHERE act_number IS NOT NULL;
|
||
|
||
COMMIT;
|