gendesign/data/sql/136_land_reservation.sql
lekss361 59f2628e0b
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m41s
Deploy / build-worker (push) Successful in 3m25s
Deploy / deploy (push) Successful in 1m25s
feat(sf): ПАГЕ-парсер изъятия/резервирования → land_reservation (#1118)
Co-authored-by: lekss361 <lekss361@gendsgn.local>
Co-committed-by: lekss361 <lekss361@gendsgn.local>
2026-06-07 10:15:03 +00:00

79 lines
5.8 KiB
PL/PgSQL
Raw 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.

-- 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;