feat(site-finder): ЕЭСК-резервы городских ПС/ТП + тепло из ФГИС ФАС (#2119 B2) #2165

Merged
bot-backend merged 1 commit from feat/eesk-heat-reserves into main 2026-07-02 16:44:58 +00:00
Collaborator

Что (issue #2119, Фаза B2)

Два больших пробела закрыты: городские ПС получают числовые резервы (вместо «по запросу в ЕЭСК») и в карточке §3 появляется четвёртый ресурс — тепло.

Backend

  • Миграция 182: power_supply_centers +reserve_unit ('МВА'/'МВт') +district (адм. район ЕКБ); heat_system_reserves (UNIQUE NULLS NOT DISTINCT).
  • eesk_reserve_loader (RUN-ON-PROD): хаб раскрытия eesk.ru (147 файлов, серии с 2012) → свежайшие xlsx по (год, квартал) из текста ссылки:
    • ПС 35-220 кВ (структура снята с живого Q2-2026): 76 городских ПС с районами, % загрузки (доля→%), свободной мощностью МВт → UPDATE наших 70 WFS-точек ЕЭСК (скоуп dzo ILIKE %ЕЭСК%; «ФСК ЕЭС» не матчится — проверено ревью);
    • ТП/РП <35 кВ: ~2014 городских ТП с резервами МВт → power_tp_rp_reserves.
    • ⚠️ Допущение: % загрузки в источнике — доля (0..1); смена формата на целые проценты даст тихий ×100 (задокументировано).
  • eias_heat_loader (RUN-ON-PROD): ФГИС ФАС ri.eias.ru (в CA-бандл добавлен GlobalSign-интермедиат — сервер не шлёт цепочку, та же болезнь что у Газпрома): карточки ЕТК/Екатеринбургэнерго → публикации свежайшего квартала → TemplatePrinter base64-ZIP → tpl XLSX → defensive-парс («СТ №N» + правейшее число) → heat_system_reserves (живой пример: СТ №54 → 3,26 Гкал/ч).
  • Celery вт 05:30/06:00; endpoint: power_points +reserve_unit/district, новый heat-блок (per-org MAX(period), graceful до миграции); схемы аддитивны, api-types +29/−0.

Frontend

  • Блок «ТЕПЛО» в карточке резервов (между газом и водой): «{орг} · СТ №N: резерв X Гкал/ч» с бейджами, свёртка >5 систем, суммарная строка, источник «Раскрытие ФАС».
  • Попап ПС: «Район: …» + единица резерва из reserve_unit (только на строке резерва: у ЕЭСК установленная — МВА, свободная — МВт, разные единицы источника).
  • B1-хвост: «(выход №N)» теперь вырезается из середины имени ГРС.

Проверки

  • 64 теста зелёные (классификация серий, разделители, доля→%, ЕЭСК-скоуп, base64/zip-guards, defensive-парс, heat-агрегация, unit/district passthrough, B1-фикс); ruff/psycopg3-guard чисты; tsc/eslint/prettier чисты.
  • Deep-review: APPROVE (1 medium — допущение доли, задокументировано; PG16 ALTER metadata-only — без lock storm).
  • Собрано 4 узкими воркерами по новому канону delegation.md; все структуры сняты с живых источников ДО написания парсеров.

После merge

Deploy (182 schema-first) → прогоны sync_eesk_reserves + sync_heat_reserves (docker exec) → верификация счётчиков (matched>0 из 70 ПС, parsed>0 систем) → скриншот карточки.

## Что (issue #2119, Фаза B2) Два больших пробела закрыты: **городские ПС получают числовые резервы** (вместо «по запросу в ЕЭСК») и в карточке §3 появляется **четвёртый ресурс — тепло**. ## Backend - **Миграция 182**: `power_supply_centers` +`reserve_unit` ('МВА'/'МВт') +`district` (адм. район ЕКБ); `heat_system_reserves` (UNIQUE NULLS NOT DISTINCT). - **`eesk_reserve_loader`** (RUN-ON-PROD): хаб раскрытия eesk.ru (147 файлов, серии с 2012) → свежайшие xlsx по (год, квартал) из текста ссылки: - **ПС 35-220 кВ** (структура снята с живого Q2-2026): 76 городских ПС с районами, % загрузки (доля→%), **свободной мощностью МВт** → UPDATE наших 70 WFS-точек ЕЭСК (скоуп dzo ILIKE %ЕЭСК%; «ФСК ЕЭС» не матчится — проверено ревью); - **ТП/РП <35 кВ**: ~2014 городских ТП с резервами МВт → `power_tp_rp_reserves`. - ⚠️ Допущение: % загрузки в источнике — доля (0..1); смена формата на целые проценты даст тихий ×100 (задокументировано). - **`eias_heat_loader`** (RUN-ON-PROD): ФГИС ФАС ri.eias.ru (в CA-бандл добавлен **GlobalSign-интермедиат** — сервер не шлёт цепочку, та же болезнь что у Газпрома): карточки ЕТК/Екатеринбургэнерго → публикации свежайшего квартала → TemplatePrinter **base64-ZIP → tpl XLSX** → defensive-парс («СТ №N» + правейшее число) → `heat_system_reserves` (живой пример: СТ №54 → 3,26 Гкал/ч). - Celery вт 05:30/06:00; endpoint: `power_points` +reserve_unit/district, новый **heat-блок** (per-org MAX(period), graceful до миграции); схемы аддитивны, api-types **+29/−0**. ## Frontend - Блок **«ТЕПЛО»** в карточке резервов (между газом и водой): «{орг} · СТ №N: резерв X Гкал/ч» с бейджами, свёртка >5 систем, суммарная строка, источник «Раскрытие ФАС». - Попап ПС: **«Район: …»** + единица резерва из reserve_unit (**только** на строке резерва: у ЕЭСК установленная — МВА, свободная — МВт, разные единицы источника). - B1-хвост: «(выход №N)» теперь вырезается из середины имени ГРС. ## Проверки - **64 теста** зелёные (классификация серий, разделители, доля→%, ЕЭСК-скоуп, base64/zip-guards, defensive-парс, heat-агрегация, unit/district passthrough, B1-фикс); ruff/psycopg3-guard чисты; tsc/eslint/prettier чисты. - **Deep-review: ✅ APPROVE** (1 medium — допущение доли, задокументировано; PG16 ALTER metadata-only — без lock storm). - Собрано 4 узкими воркерами по новому канону delegation.md; все структуры сняты с живых источников ДО написания парсеров. ## После merge Deploy (182 schema-first) → прогоны `sync_eesk_reserves` + `sync_heat_reserves` (docker exec) → верификация счётчиков (matched>0 из 70 ПС, parsed>0 систем) → скриншот карточки.
bot-backend added 1 commit 2026-07-02 16:27:28 +00:00
feat(site-finder): ЕЭСК-резервы городских ПС/ТП + тепло из ФГИС ФАС (#2119 B2)
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Successful in 1m10s
CI / openapi-codegen-check (pull_request) Successful in 2m0s
CI / backend-tests (pull_request) Successful in 14m36s
372856c4cc
Городские числа вместо «по запросу» + четвёртый ресурс (тепло) в карточке §3.

- Миграция 182: power_supply_centers +reserve_unit ('МВА'/'МВт') +district;
  heat_system_reserves (UNIQUE NULLS NOT DISTINCT).
- eesk_reserve_loader (RUN-ON-PROD): хаб раскрытия eesk.ru → свежайшие xlsx по
  (год, квартал) из текста ссылки; ПС 35-220 (структура снята: r7+, доля
  0.41→41.0, свободная МВт) → UPDATE 70 городских ПС (только dzo ЕЭСК;
  «ФСК ЕЭС» не матчится — проверено ревью); ТП/РП ниже 35 (r4+, ~2014 строк
  города) → power_tp_rp_reserves. ДОПУЩЕНИЕ: % загрузки в источнике — доля
  (0..1); если ЕЭСК перейдёт на целые проценты, load_pct тихо ×100.
- eias_heat_loader (RUN-ON-PROD, SSL: в CA-бандл добавлен GlobalSign-интермедиат
  — ri.eias.ru не шлёт цепочку): карточка орг (ЕТК 30814352, Екатеринбургэнерго
  26479450) → публикации свежайшего квартала → TemplatePrinter base64-ZIP → tpl
  XLSX → defensive-парс «СТ №N»+правейшее число → heat_system_reserves.
- Celery вт 05:30/06:00; endpoint: power_points +reserve_unit/district,
  heat-блок (per-org MAX(period), graceful); схемы аддитивны, api-types +29/-0.
- Фронт: блок «ТЕПЛО» (бейджи резерв/исчерпана, свёртка >5, суммарно Гкал/ч);
  попап ПС: район + unit ТОЛЬКО на строке резерва (у ЕЭСК installed МВА,
  резерв МВт — разные единицы источника).
- B1-хвост: «(выход №N)» матчится в середине имени ГРС.

64+ тестов зелёные; deep-review  APPROVE.
bot-backend merged commit e501dedf78 into main 2026-07-02 16:44:58 +00:00
bot-backend deleted branch feat/eesk-heat-reserves 2026-07-02 16:44:58 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2165
No description provided.