Co-authored-by: lekss361 <lekss361@gendsgn.local> Co-committed-by: lekss361 <lekss361@gendsgn.local>
86 lines
5.4 KiB
PL/PgSQL
86 lines
5.4 KiB
PL/PgSQL
-- 138_ekb_ppt_tep.sql
|
||
-- #1085 (Site Finder v2 / GG-форсайт #1067) — ТЭП из ППТ/ПМТ-пояснительных записок.
|
||
--
|
||
-- Что/зачем: структурированный контент пояснительных записок ППТ/ПМТ (PDF).
|
||
-- Три логических таблицы документа:
|
||
-- Табл.11 — баланс территории по зонам (га + %);
|
||
-- Табл.12 — основные ТЭП (площади, этажность, плотность, инфраструктура);
|
||
-- Табл.13 — очередность строительства (объект/зона/срок/финансирование).
|
||
--
|
||
-- Линковка к геометрии: doc_ref сопоставляется с planning_projects.source_key /
|
||
-- doc_full_name (данные ППТ/ПМТ уже в БД через WFS, #1085). Прямой FK не ставим
|
||
-- из-за best-effort nature ссылок (одна пояснительная → несколько границ и наоборот).
|
||
--
|
||
-- Grain: одна строка = один PDF-документ пояснительной записки.
|
||
-- UNIQUE(doc_ref) — не допускает дублей при повторном ingest.
|
||
--
|
||
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN).
|
||
-- Idempotent: CREATE TABLE/INDEX IF NOT EXISTS + guarded DO-блок для UNIQUE.
|
||
-- Без INSERT (данные приходят из ekb_ppt_tep_sync Celery-воркера).
|
||
|
||
BEGIN;
|
||
|
||
-- ── 1. Таблица ekb_ppt_tep ────────────────────────────────────────────────────
|
||
CREATE TABLE IF NOT EXISTS ekb_ppt_tep (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
doc_ref TEXT NOT NULL, -- ид/ссылка документа ППТ (для join к planning_projects)
|
||
project_type TEXT NOT NULL, -- 'ppt' | 'pmt'
|
||
zone_balance JSONB, -- Табл.11: баланс территории по зонам
|
||
tep JSONB, -- Табл.12: основные ТЭП
|
||
phasing JSONB, -- Табл.13: очередность строительства
|
||
raw_tables JSONB, -- сырые таблицы для отладки/re-parse
|
||
source_pdf TEXT, -- URL или путь к исходному PDF
|
||
fetched_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||
);
|
||
|
||
COMMENT ON TABLE ekb_ppt_tep IS
|
||
'ТЭП из пояснительных записок ППТ/ПМТ (#1085, GG-форсайт #1067). '
|
||
'1 строка = 1 PDF-документ. '
|
||
'Три JSONB-поля: zone_balance (Табл.11), tep (Табл.12), phasing (Табл.13). '
|
||
'Линковка к геометрии: doc_ref → planning_projects.source_key.';
|
||
|
||
COMMENT ON COLUMN ekb_ppt_tep.doc_ref IS
|
||
'Идентификатор/ссылка документа ППТ. Для сопоставления с '
|
||
'planning_projects.source_key или doc_full_name.';
|
||
COMMENT ON COLUMN ekb_ppt_tep.project_type IS
|
||
'''ppt'' — проект планировки территории; ''pmt'' — проект межевания территории.';
|
||
COMMENT ON COLUMN ekb_ppt_tep.zone_balance IS
|
||
'Баланс территории по зонам (Табл.11): [{no, zone_name, existing_ha, project_ha, ...}]. '
|
||
'Пустой массив [] если таблица не найдена в PDF.';
|
||
COMMENT ON COLUMN ekb_ppt_tep.tep IS
|
||
'Основные ТЭП (Табл.12): [{no, indicator, unit, current, target}]. '
|
||
'Пустой массив [] если таблица не найдена.';
|
||
COMMENT ON COLUMN ekb_ppt_tep.phasing IS
|
||
'Очередность строительства (Табл.13): [{phase, composition, zone, area_ha, '
|
||
'funding, program}]. Пустой массив [] если таблица не найдена.';
|
||
COMMENT ON COLUMN ekb_ppt_tep.raw_tables IS
|
||
'Сырые таблицы из pdfplumber для отладки: [{page, table_index, rows: [[...]]}]. ';
|
||
|
||
-- ── 2. UNIQUE(doc_ref) — дедуп-ключ для UPSERT воркера ──────────────────────
|
||
-- Guard по pg_constraint → idempotent re-apply (прецедент: м.132, 136, 137).
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (
|
||
SELECT 1 FROM pg_constraint WHERE conname = 'uq_ekb_ppt_tep_doc_ref'
|
||
) THEN
|
||
ALTER TABLE ekb_ppt_tep
|
||
ADD CONSTRAINT uq_ekb_ppt_tep_doc_ref UNIQUE (doc_ref);
|
||
END IF;
|
||
END
|
||
$$;
|
||
|
||
-- ── 3. Индексы ────────────────────────────────────────────────────────────────
|
||
-- Фильтр по типу проекта (ppt/pmt).
|
||
CREATE INDEX IF NOT EXISTS idx_ekb_ppt_tep_project_type
|
||
ON ekb_ppt_tep (project_type);
|
||
|
||
-- Свежесть / ORDER BY fetched_at для мониторинга.
|
||
CREATE INDEX IF NOT EXISTS idx_ekb_ppt_tep_fetched_at
|
||
ON ekb_ppt_tep (fetched_at DESC);
|
||
|
||
-- GIN-индекс на zone_balance для поиска по зонам (follow-up: @> queries).
|
||
CREATE INDEX IF NOT EXISTS idx_ekb_ppt_tep_zone_balance_gin
|
||
ON ekb_ppt_tep USING GIN (zone_balance)
|
||
WHERE zone_balance IS NOT NULL;
|
||
|
||
COMMIT;
|