-- 181_gas_grs_capacity.sql -- Forgejo #2119 Phase B1 — газовая вертикаль «свободная мощность ГРС» для ПТИЦА §3. -- -- Одна таблица gas_grs_capacity: свободная мощность ГРС (газораспределительная -- станция) из раскрытия «Газпром трансгаз Екатеринбург» (ГТЕ): -- https://ekaterinburg-tr.gazprom.ru/about/informatsiya-o-tekhnicheskoj-vozmo/ -- — инлайн HTML-таблица «Информация о технической возможности…». -- -- Источник ГЕО-БЛОКИРУЕТ non-RU IP → загрузчик РАБОТАЕТ НА ПРОДЕ (Celery / manual -- docker exec) — как rosseti-/vodokanal-лоадеры (180). Код не должен предполагать -- локальный сетевой доступ. -- -- У ГРС бывает несколько выходов («выход 1/2/3») — тогда одна ГРС = N строк с -- разным output_name; output_name IS NULL = вся ГРС целиком (одна строка). -- grs_name_norm — нормализованное имя для матча (lower, ё→е, пробелы/дефисы -- схлопнуты; префиксы «ГРС»/«АРП» СОХРАНЯЮТСЯ, т.к. различают станции). -- -- Refresh: weekly via tasks.connection_capacity_sync.sync_gas_grs_capacity. -- Порядок применения: миграция ПЕРЕД деплоем кода (schema-first, sql.md). BEGIN; -- ── gas_grs_capacity ───────────────────────────────────────────────────────── -- geom NULL до Фазы C (геокод ГРС). raw jsonb — сырые ячейки строки целиком -- (неизвестные/будущие колонки таблицы ГТЕ не теряются, а падают в raw). CREATE TABLE IF NOT EXISTS gas_grs_capacity ( id SERIAL PRIMARY KEY, grs_name TEXT NOT NULL, -- исходное имя ГРС grs_name_norm TEXT NOT NULL, -- нормализованное для матча output_name TEXT, -- «выход 1/2/3»; NULL = вся ГРС region TEXT, -- область (Свердловская и др.) design_capacity_th_m3_h NUMERIC, -- проектная, тыс. м³/ч current_load_th_m3_h NUMERIC, -- текущая загрузка, тыс. м³/ч free_capacity_th_m3_h NUMERIC, -- свободная мощность, тыс. м³/ч free_capacity_pct NUMERIC, -- свободная, % upgrade_due TEXT, -- срок расшивки (как в источнике) asof DATE, -- дата актуальности данных geom GEOMETRY(POINT, 4326), -- NULL до Фазы C геокода raw JSONB, -- сырая строка таблицы целиком fetched_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- NULLS NOT DISTINCT: output_name nullable (у ГРС без разбивки по выходам — -- одна строка с output_name IS NULL). Без этого ON CONFLICT не матчит строку -- с NULL-выходом → weekly-прогон плодит дубли (те же грабли, что #140 / -- 180_connection_capacity.sql power_tp_rp_reserves). UNIQUE NULLS NOT DISTINCT (grs_name_norm, output_name) ); CREATE INDEX IF NOT EXISTS idx_gas_grs_capacity_name_norm ON gas_grs_capacity (grs_name_norm); CREATE INDEX IF NOT EXISTS gist_gas_grs_capacity_geom ON gas_grs_capacity USING GIST (geom); COMMENT ON TABLE gas_grs_capacity IS 'Свободная мощность ГРС (газораспределительных станций) из раскрытия «Газпром ' 'трансгаз Екатеринбург». Один output_name на строку («выход 1/2/3»; NULL = вся ' 'ГРС). geom NULL до Фазы C геокода. Refresh: weekly via ' 'tasks.connection_capacity_sync.sync_gas_grs_capacity. Forgejo #2119 Phase B1.'; COMMENT ON COLUMN gas_grs_capacity.grs_name_norm IS 'Нормализованное имя ГРС для матча/дедупа (lower, ё→е, пробелы/дефисы схлопнуты; ' 'префиксы «ГРС»/«АРП» СОХРАНЯЮТСЯ — различают станции).'; COMMENT ON COLUMN gas_grs_capacity.output_name IS 'Выход ГРС («выход 1/2/3»). NULL = вся ГРС целиком (нет разбивки по выходам).'; COMMENT ON COLUMN gas_grs_capacity.free_capacity_th_m3_h IS 'Свободная (резервная) мощность ГРС, тыс. м³/ч. Может быть 0 при полной загрузке.'; COMMENT ON COLUMN gas_grs_capacity.upgrade_due IS 'Срок расшивки (планового увеличения пропускной способности), как в источнике ' '(свободный текст: год / «после 2027» / пусто).'; COMMIT;