gendesign/data/sql/187_gisogd_permits.sql
bot-backend 282c92747e
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 2m40s
Deploy / build-worker (push) Successful in 3m27s
Deploy / build-frontend (push) Successful in 4m0s
Deploy / deploy (push) Successful in 1m41s
feat(scrapers): реестр РНС/РВЭ ГИСОГД-СО из открытого API — миграция + лоадер (#2367 PR-1) (#2370)
2026-07-04 03:26:07 +00:00

99 lines
7.5 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.

-- 187_gisogd_permits.sql
-- Forgejo #2367 PR-1 (Schema) — реестр разрешений на строительство (РНС) и ввод
-- в эксплуатацию (РВЭ) Свердловской области из ОТКРЫТОГО API ГИСОГД-СО.
--
-- Одна таблица gisogd_permits: карточки документов раздела 13 («Сведения о
-- документах в деле о земельном участке») региональной ГИС органов гос. власти
-- Свердловской области (gisogd66.midural.ru). Открытый JSON-API без авторизации.
--
-- Источник (карточки/списки) отдаёт данные без гео-блокировки (bare curl 200), но
-- код лоадера всё равно держим устойчивым к отсутствию полей (spatialUnit / geometry
-- у части документов отсутствуют — hasGeometry=false).
--
-- Две схемы источника:
-- agate_ekbgo — ЕКБ, самая свежая выгрузка;
-- agate_sverdregion — регион-агрегат, отстаёт ~неделю.
-- Один документ может встретиться в ОБЕИХ схемах → бизнес-ключ = (doc_group, doc_num);
-- при конфликте предпочитаем запись с более поздним date_reg (лоадер, PR-2).
--
-- doc_group:
-- 'RS' — Разрешение на строительство (группа источника DocRS);
-- 'RV' — Разрешение на ввод в эксплуатацию (группа источника DocRV).
--
-- cad_nums — распарсенный spatialUnit (может быть НЕСКОЛЬКО кадастровых номеров
-- через запятую, может отсутствовать → пустой массив). geom — из infosetGeoJson
-- (GeoJSON Polygon WGS84 lon/lat, лоадер приводит к MultiPolygon), NULL когда
-- hasGeometry=false. source_schema/source_key фиксируют, откуда прилетела запись
-- (для инкрементальной сверки по (source_schema, source_key, date_reg)).
--
-- Порядок применения: миграция ПЕРЕД деплоем кода (schema-first, sql.md).
-- Таблица НОВАЯ → deploy.yml гоняет всё в одной транзакции; CREATE INDEX
-- CONCURRENTLY здесь не нужен (и запрещён внутри транзакции).
BEGIN;
-- ── gisogd_permits ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS gisogd_permits (
id BIGSERIAL PRIMARY KEY,
doc_group TEXT NOT NULL, -- 'RS' (РНС) | 'RV' (РВЭ) — см. CHECK
doc_num TEXT NOT NULL, -- № документа, напр. «66-45-08-2026» (strip'нут)
doc_name TEXT, -- name карточки, напр. «Разрешение на строительство № … от …»
date_doc DATE, -- dateDoc — дата выдачи документа
date_reg DATE, -- dateReg — дата регистрации в реестре (для conflict-резолва)
approved_organization TEXT, -- approvedOrganization — выдавший орган
source_schema TEXT NOT NULL, -- 'agate_ekbgo' | 'agate_sverdregion'
source_key TEXT NOT NULL, -- key карточки в схеме источника (для инкрементальной сверки)
cad_nums TEXT[] NOT NULL DEFAULT '{}', -- распарсенный spatialUnit ('{}' если нет)
geom GEOMETRY(MultiPolygon, 4326), -- из infosetGeoJson; NULL если hasGeometry=false
fetched_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Только 'RS'/'RV' допустимы (защита от опечаток в лоадере).
CONSTRAINT chk_gisogd_permits_doc_group CHECK (doc_group IN ('RS', 'RV')),
-- Бизнес-ключ: один документ (группа + номер) хранится ОДНОЙ строкой, даже если
-- прилетел из обеих схем. Лоадер UPSERT-ит по нему, предпочитая поздний date_reg.
UNIQUE (doc_group, doc_num)
);
-- Пространственный индекс — §-запросы «РНС/РВЭ рядом с участком».
CREATE INDEX IF NOT EXISTS gist_gisogd_permits_geom
ON gisogd_permits USING GIST (geom);
-- GIN по массиву кадастровых номеров — матч «разрешение на этом участке».
CREATE INDEX IF NOT EXISTS gin_gisogd_permits_cad_nums
ON gisogd_permits USING GIN (cad_nums);
-- Дата документа — фильтры/сортировки по свежести разрешений.
CREATE INDEX IF NOT EXISTS idx_gisogd_permits_date_doc
ON gisogd_permits (date_doc DESC);
COMMENT ON TABLE gisogd_permits IS
'Реестр разрешений на строительство (РНС) и ввод в эксплуатацию (РВЭ) '
'Свердловской области из открытого API ГИСОГД-СО (gisogd66.midural.ru, раздел 13). '
'Бизнес-ключ (doc_group, doc_num); при конфликте двух схем источника '
'(agate_ekbgo / agate_sverdregion) предпочитается поздний date_reg. Refresh: weekly '
'/ on-demand. Forgejo #2367.';
COMMENT ON COLUMN gisogd_permits.doc_group IS
'''RS'' = разрешение на строительство (группа источника DocRS), '
'''RV'' = разрешение на ввод в эксплуатацию (группа источника DocRV).';
COMMENT ON COLUMN gisogd_permits.cad_nums IS
'Распарсенный spatialUnit карточки: список кадастровых номеров (несколько через '
'запятую в источнике). Пустой массив ''{}'' когда spatialUnit отсутствует или все '
'значения не прошли валидацию формата кадастрового номера.';
COMMENT ON COLUMN gisogd_permits.geom IS
'MultiPolygon (WGS84) из infosetGeoJson карточки (Polygon приведён к MultiPolygon '
'лоадером). NULL когда hasGeometry=false / infosetGeoJson отсутствует.';
COMMENT ON COLUMN gisogd_permits.source_schema IS
'Схема источника, из которой прилетела запись: ''agate_ekbgo'' (ЕКБ, свежая) или '
'''agate_sverdregion'' (регион-агрегат, отстаёт ~неделю).';
COMMENT ON COLUMN gisogd_permits.source_key IS
'key карточки в схеме источника. Вместе с (source_schema, date_reg) используется '
'лоадером для инкрементальной сверки: карточки тянутся только для новых/изменённых.';
COMMIT;