-- 182_eesk_heat_reserves.sql -- Forgejo #2119 Phase B2 — АО «ЕЭСК» (Екатеринбургская электросетевая компания): -- (а) резерв мощности по ЦП ПС 35-220 кВ → апдейт power_supply_centers (МВт); -- (б) резерв ТП/РП напряжением ниже 35 кВ → UPSERT power_tp_rp_reserves; -- (в) heat_system_reserves — задел под теплоснабжение (Gcal/ч), city-level. -- -- Источник: eesk.ru «Наличие объёма свободной для технологического присоединения -- мощности» — статический HTML-хаб со ссылками на xlsx (обычный SSL, БЕЗ гео-блока, -- но лоадер всё равно RUN-ON-PROD рядом с rosseti/gas/vodokanal). -- -- ЕЭСК резервы у ЦП измеряются в МВт (не МВА как у Россетей) → добавляем -- reserve_unit на power_supply_centers (default 'МВА' для старых строк Россетей, -- лоадер ЕЭСК проставляет 'МВт'). district — адм. район ЕКБ из xlsx ЕЭСК. -- -- Refresh: weekly via tasks.connection_capacity_sync (отдельный воркер). -- Порядок применения: миграция ПЕРЕД деплоем кода (schema-first, sql.md). BEGIN; -- ── power_supply_centers: единица резерва + адм. район ──────────────────────── -- reserve_unit: у Россетей резерв в МВА, у ЕЭСК ПС 35-220 — в МВт. default 'МВА' -- сохраняет семантику существующих строк (заполнены Россетями), лоадер ЕЭСК -- явно проставляет 'МВт'. district — административный район Екатеринбурга (колонка -- B файла ЕЭСК); у Россети-строк остаётся NULL. ALTER TABLE power_supply_centers ADD COLUMN IF NOT EXISTS reserve_unit TEXT DEFAULT 'МВА'; ALTER TABLE power_supply_centers ADD COLUMN IF NOT EXISTS district TEXT; COMMENT ON COLUMN power_supply_centers.reserve_unit IS 'Единица reserve_mva/installed_capacity_mva: ''МВА'' (Россети, default) или ' '''МВт'' (ЕЭСК ПС 35-220, capacity_source=''eesk_35_220''). Forgejo #2119 B2.'; COMMENT ON COLUMN power_supply_centers.district IS 'Административный район Екатеринбурга (из xlsx ЕЭСК ПС 35-220). NULL у ' 'Россети-строк. Forgejo #2119 Phase B2.'; -- ── heat_system_reserves ────────────────────────────────────────────────────── -- Резервы тепловой мощности систем теплоснабжения (Gcal/ч), city-level, без geom. -- sphere зафиксирована 'heat' (задел под другие сферы раскрытия одной таблицей). -- reserve_gcal_h может быть отрицательным (дефицит) — знак сохраняем. raw jsonb — -- сырая строка источника целиком (будущие колонки не теряются). CREATE TABLE IF NOT EXISTS heat_system_reserves ( id SERIAL PRIMARY KEY, org TEXT NOT NULL, -- организация-держатель (АО «ЕЭСК» и др.) sphere TEXT NOT NULL DEFAULT 'heat', system_name TEXT NOT NULL, -- имя системы теплоснабжения reserve_gcal_h NUMERIC, -- свободная мощность, Гкал/ч (может быть <0) applications_note TEXT, -- примечание о заявках на подключение period TEXT, -- напр. '2026-Q2' source_guid TEXT, -- хэш/идентификатор исходного файла raw JSONB, -- сырая строка источника целиком fetched_at TIMESTAMPTZ DEFAULT NOW(), -- NULLS NOT DISTINCT: period может быть NULL при неудачном разборе даты -- (те же грабли, что #140 / 180_connection_capacity.sql water_supply_reserves). UNIQUE NULLS NOT DISTINCT (org, sphere, system_name, period) ); CREATE INDEX IF NOT EXISTS idx_heat_system_reserves_period ON heat_system_reserves (period); CREATE INDEX IF NOT EXISTS idx_heat_system_reserves_sphere ON heat_system_reserves (sphere); COMMENT ON TABLE heat_system_reserves IS 'Резервы тепловой мощности систем теплоснабжения (Гкал/ч, city-level, без geom). ' 'reserve_gcal_h может быть отрицательным (дефицит). Forgejo #2119 Phase B2.'; COMMENT ON COLUMN heat_system_reserves.reserve_gcal_h IS 'Свободная (резервная) тепловая мощность, Гкал/ч. Отрицательное = дефицит.'; COMMIT;