143 lines
9.6 KiB
PL/PgSQL
143 lines
9.6 KiB
PL/PgSQL
-- 180_connection_capacity.sql
|
||
-- Forgejo #2119 Phase A — «точки подключения СО СВОБОДНОЙ МОЩНОСТЬЮ» для ПТИЦА §3.
|
||
--
|
||
-- Три таблицы верифицированных источников свободной мощности (электро + вода):
|
||
-- power_supply_centers — центры питания (ЦП: ПС 35/110 кВ) из Россети WFS +
|
||
-- резервы свободной мощности по ЦП (rosseti-ural.ru xlsx).
|
||
-- power_tp_rp_reserves — резервы ТП/РП напряжением ниже 35 кВ (10k+ строк,
|
||
-- в основном БЕЗ координат — Phase B геокод).
|
||
-- water_supply_reserves — резервы ЦСВ/ЦСК Водоканала ЕКБ (docx, city-level).
|
||
--
|
||
-- Источники гео-блокируют non-RU IP → загрузчики РАБОТАЮТ НА ПРОДЕ (Celery/manual
|
||
-- docker exec). Код не должен предполагать локальный сетевой доступ.
|
||
--
|
||
-- Refresh: weekly via tasks.connection_capacity_sync (WFS + reserves + water).
|
||
-- Порядок применения: миграция ПЕРЕД деплоем кода (schema-first, sql.md).
|
||
|
||
BEGIN;
|
||
|
||
-- ── power_supply_centers ─────────────────────────────────────────────────────
|
||
-- ЦП = центр питания (ПС 35/110 кВ). geom из Россети WFS (координаты округлены
|
||
-- ~100 м — для §3 «есть ли точка рядом» этого достаточно). Резервы свободной
|
||
-- мощности (installed/current/reserve) допихиваются из xlsx-раскрытия по
|
||
-- sc_name_norm-матчу. sc_name_norm — нормализованное имя для сопоставления
|
||
-- (lower, «ПС»/voltage-префикс срезан, ё→е, тире/пробелы схлопнуты).
|
||
CREATE TABLE IF NOT EXISTS power_supply_centers (
|
||
id SERIAL PRIMARY KEY,
|
||
source TEXT NOT NULL, -- 'rosseti_wfs'
|
||
external_id TEXT, -- feature id или stable hash
|
||
sc_name TEXT NOT NULL, -- исходное имя ЦП
|
||
sc_name_norm TEXT NOT NULL, -- нормализованное для матча
|
||
dzo_name TEXT, -- ДЗО (напр. «Россети Урал»)
|
||
org_name TEXT,
|
||
branch_name TEXT, -- филиал (br_name)
|
||
voltage_class TEXT, -- напр. '110/35/10'
|
||
load_index TEXT, -- 'open'|'limited'|'closed'|NULL
|
||
installed_capacity_mva NUMERIC, -- установленная, МВА
|
||
current_load_mva NUMERIC, -- текущая нагрузка, МВА
|
||
reserve_mva NUMERIC, -- свободная мощность, МВА
|
||
reserve_asof DATE, -- дата актуальности резерва
|
||
capacity_source TEXT, -- 'cp_35_110'|'tp_rp_sub35'|NULL
|
||
municipality TEXT,
|
||
place_city TEXT, -- sc_placecity
|
||
geom GEOMETRY(POINT, 4326),
|
||
raw JSONB, -- сырая WFS-фича целиком
|
||
fetched_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
||
UNIQUE (source, external_id)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS gist_power_supply_centers_geom
|
||
ON power_supply_centers USING GIST (geom);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_power_supply_centers_name_norm
|
||
ON power_supply_centers (sc_name_norm);
|
||
|
||
COMMENT ON TABLE power_supply_centers IS
|
||
'Центры питания (ЦП, ПС 35/110 кВ) Россети + резервы свободной мощности по ЦП. '
|
||
'Source: Россети WFS (geom) + rosseti-ural.ru xlsx (reserve). '
|
||
'Refresh: weekly via tasks.connection_capacity_sync. Forgejo #2119 Phase A.';
|
||
|
||
COMMENT ON COLUMN power_supply_centers.sc_name_norm IS
|
||
'Нормализованное имя ЦП для матча с xlsx-резервом (lower, «ПС»/voltage-префикс '
|
||
'срезан, ё→е, тире/пробелы схлопнуты).';
|
||
|
||
COMMENT ON COLUMN power_supply_centers.geom IS
|
||
'Координаты Россети WFS округлены ~100 м — для §3 «есть ли ЦП рядом» достаточно.';
|
||
|
||
-- ── power_tp_rp_reserves ─────────────────────────────────────────────────────
|
||
-- Резервы ТП/РП напряжением ниже 35 кВ (10 741 строк в верифицированном xlsx).
|
||
-- В основном БЕЗ координат — geocode_status='pending', гео придёт в Phase B.
|
||
-- UNIQUE(name_norm, municipality, voltage_kv) — одно и то же имя ТП может
|
||
-- встречаться в разных МО / на разном напряжении.
|
||
CREATE TABLE IF NOT EXISTS power_tp_rp_reserves (
|
||
id SERIAL PRIMARY KEY,
|
||
name TEXT NOT NULL, -- напр. «ТП-721»
|
||
name_norm TEXT NOT NULL, -- нормализованное для матча
|
||
res_unit TEXT, -- РЭС
|
||
municipality TEXT,
|
||
settlement TEXT,
|
||
voltage_kv TEXT, -- класс напряжения, кВ
|
||
installed_capacity_mva NUMERIC, -- установленная, МВА
|
||
current_load_mva NUMERIC, -- текущая нагрузка, МВА
|
||
reserve_mva NUMERIC, -- свободная мощность, МВА
|
||
reserve_asof DATE,
|
||
geom GEOMETRY(POINT, 4326), -- NULL до Phase B геокода
|
||
geocode_status TEXT DEFAULT 'pending',
|
||
raw JSONB,
|
||
fetched_at TIMESTAMPTZ DEFAULT NOW(),
|
||
|
||
-- NULLS NOT DISTINCT: municipality/voltage_kv бывают NULL (пустые ячейки xlsx);
|
||
-- без этого ON CONFLICT не матчится и weekly-прогон плодит дубли
|
||
-- (те же грабли, что 140_domrf_documents_unique_nulls_not_distinct.sql).
|
||
UNIQUE NULLS NOT DISTINCT (name_norm, municipality, voltage_kv)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS gist_power_tp_rp_reserves_geom
|
||
ON power_tp_rp_reserves USING GIST (geom);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_power_tp_rp_reserves_name_norm
|
||
ON power_tp_rp_reserves (name_norm);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_power_tp_rp_reserves_geocode_status
|
||
ON power_tp_rp_reserves (geocode_status);
|
||
|
||
COMMENT ON TABLE power_tp_rp_reserves IS
|
||
'Резервы свободной мощности ТП/РП <35 кВ (rosseti-ural.ru xlsx, ~10.7k строк). '
|
||
'geom NULL до Phase B геокода (geocode_status). Forgejo #2119 Phase A.';
|
||
|
||
-- ── water_supply_reserves ────────────────────────────────────────────────────
|
||
-- Резервы ЦСВ (центр. система водоснабжения) / ЦСК (водоотведения) Водоканала
|
||
-- ЕКБ (docx-раскрытие). Городской уровень (без geom) — фронт показывает ЦСВ
|
||
-- «ЗФС, ГСВ» как атрибут города. reserve может быть ОТРИЦАТЕЛЬНЫМ (дефицит) —
|
||
-- знак сохраняем. UNIQUE(system_kind, system_name, period).
|
||
CREATE TABLE IF NOT EXISTS water_supply_reserves (
|
||
id SERIAL PRIMARY KEY,
|
||
system_kind TEXT NOT NULL, -- 'water'|'sewerage'
|
||
system_name TEXT NOT NULL, -- ЦСВ/ЦСК, напр. «ЗФС, ГСВ»
|
||
reserve_thousand_m3_day NUMERIC, -- резерв, тыс. м³/сут (может быть <0)
|
||
connections_requested INT, -- заявок на подключение
|
||
connections_refused INT, -- отказов
|
||
note TEXT,
|
||
period TEXT, -- напр. '2026-Q1'
|
||
source_url TEXT,
|
||
fetched_at TIMESTAMPTZ DEFAULT NOW(),
|
||
|
||
-- NULLS NOT DISTINCT: period может быть NULL при неудачном infer_period.
|
||
UNIQUE NULLS NOT DISTINCT (system_kind, system_name, period)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_water_supply_reserves_period
|
||
ON water_supply_reserves (period);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_water_supply_reserves_kind
|
||
ON water_supply_reserves (system_kind);
|
||
|
||
COMMENT ON TABLE water_supply_reserves IS
|
||
'Резервы ЦСВ/ЦСК Водоканала ЕКБ (docx-раскрытие, city-level, без geom). '
|
||
'reserve_thousand_m3_day может быть отрицательным (дефицит). Forgejo #2119 Phase A.';
|
||
|
||
COMMENT ON COLUMN water_supply_reserves.reserve_thousand_m3_day IS
|
||
'Свободная мощность ЦСВ/ЦСК, тыс. м³/сут. Отрицательное значение = дефицит.';
|
||
|
||
COMMIT;
|