feat(site-finder): резервы мощности для ТП — электро+вода на карте §3 (#2119 Фаза A) #2120

Merged
bot-backend merged 1 commit from feat/connection-capacity-phase-a into main 2026-07-02 08:36:52 +00:00
Collaborator

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

Первая партия наполнения карты точками подключения с характеристиками из верифицированных research'ем источников: электричество (Россети: центры питания со свободной мощностью для ТП) + вода/канализация (Водоканал: резервы систем, включая городской дефицит −168,5 тыс. м³/сут).

Backend

  • Миграция data/sql/180_connection_capacity.sql: power_supply_centers (точки ПС 35-220кВ + резерв МВА), power_tp_rp_reserves (10.7k ТП/РП 6-10кВ — резервы; геокод в Фазе B), water_supply_reserves. UNIQUE NULLS NOT DISTINCT на nullable-ключах (грабли #140 — поймано deep-review).
  • Лоадеры (все источники гео-блокируют не-RU IP → RUN-ON-PROD, Celery вт 04:00/04:30 + ручной docker exec):
    • rosseti_wfs_loader — открытый WFS портал-тп.рф (punycode-хост): ~488 ПС Свердл. обл. с координатами, индекс загрузки (открыт/ограничен/закрыт), voltage из имени;
    • rosseti_reserve_loader — xlsx-раскрытие ПП№24: ЦП 35-110кВ (данные со строки 8, матч к WFS-точкам по общему нормализатору имён) + ТП/РП <35кВ (со строки 9; кВА-санити >2.5 МВА для ТП → ÷1000, РП не трогаем);
    • vodokanal_reserve_loader — DOCX-раскрытие ПП№6 (stdlib-парсер, vMerge forward-fill, отрицательные резервы со знаком).
  • Endpoint GET /api/v1/parcels/{cad}/connection-capacity (radius_m 100-10000, деф. 3000): ПС в радиусе + summary (ближайшая с резервом, счёт по статусам) + вода за последний период per-system_kind (водоотведение может отставать на квартал — deep-review low-фикс).

Frontend (§3 «Сети и точки подключения»)

  • Карточка «Ресурсные резервы»: ближайший ЦП (напряжение · резерв МВА · статус-бейдж) + вода/канализация (городская система выделена; отрицательный резерв → красный «дефицит» + примечание из раскрытия) + caveat про ТУ.
  • Слой «Центры питания (резерв)» на карте: маркеры с цветом по индексу загрузки (зелёный/янтарный/красный), белая обводка (отличимы от НСПД-точек), попап: напряжение / установленная / загрузка / резерв для ТП / статус / дата среза / дисклеймер ±100 м. Легенда под картой.
  • Числа через toFiniteNumber (урок #2114: Decimal→строка).

Проверки

  • Backend: 39 тестов (нормализатор, кВА-санити, DOCX vMerge, xlsx row-offsets на синтетике, endpoint 404/422) + ruff чист + psycopg3-guard чист.
  • Frontend: tsc/eslint/prettier чисты, SiteMap smoke 2/2 (MiniMap не сломан — новый prop опционален).
  • api-types.ts офлайн-регенерация: +131/−0 строго аддитивно.
  • Deep-review: ⚠️ MINOR → все 3 замечания исправлены в этом же коммите (NULLS NOT DISTINCT ×2, per-kind MAX(period), settlement-комментарий).

После merge

  1. Deploy применит миграцию 180 автоматически (schema-first, deploy.yml).
  2. Запустить лоадеры на проде (docker exec → Celery tasks sync_power_supply_centers, sync_water_reserves) — до этого карточка честно показывает «Данные о резервах ПС загружаются».
  3. Прод-верификация: скриншот §3 с маркерами ЦП + попап с резервом МВА + карточка с водным дефицитом.
## Что (issue #2119, Фаза A) Первая партия наполнения карты **точками подключения с характеристиками** из верифицированных research'ем источников: **электричество** (Россети: центры питания со свободной мощностью для ТП) + **вода/канализация** (Водоканал: резервы систем, включая городской дефицит −168,5 тыс. м³/сут). ## Backend - **Миграция `data/sql/180_connection_capacity.sql`**: `power_supply_centers` (точки ПС 35-220кВ + резерв МВА), `power_tp_rp_reserves` (10.7k ТП/РП 6-10кВ — резервы; геокод в Фазе B), `water_supply_reserves`. `UNIQUE NULLS NOT DISTINCT` на nullable-ключах (грабли #140 — поймано deep-review). - **Лоадеры** (все источники гео-блокируют не-RU IP → RUN-ON-PROD, Celery вт 04:00/04:30 + ручной docker exec): - `rosseti_wfs_loader` — открытый WFS портал-тп.рф (punycode-хост): ~488 ПС Свердл. обл. с координатами, индекс загрузки (открыт/ограничен/закрыт), voltage из имени; - `rosseti_reserve_loader` — xlsx-раскрытие ПП№24: ЦП 35-110кВ (данные со строки 8, матч к WFS-точкам по общему нормализатору имён) + ТП/РП <35кВ (со строки 9; кВА-санити >2.5 МВА для ТП → ÷1000, РП не трогаем); - `vodokanal_reserve_loader` — DOCX-раскрытие ПП№6 (stdlib-парсер, vMerge forward-fill, отрицательные резервы со знаком). - **Endpoint** `GET /api/v1/parcels/{cad}/connection-capacity` (radius_m 100-10000, деф. 3000): ПС в радиусе + summary (ближайшая с резервом, счёт по статусам) + вода за последний период **per-system_kind** (водоотведение может отставать на квартал — deep-review low-фикс). ## Frontend (§3 «Сети и точки подключения») - Карточка **«Ресурсные резервы»**: ближайший ЦП (напряжение · резерв МВА · статус-бейдж) + вода/канализация (городская система выделена; отрицательный резерв → красный «дефицит» + примечание из раскрытия) + caveat про ТУ. - Слой **«Центры питания (резерв)»** на карте: маркеры с цветом по индексу загрузки (зелёный/янтарный/красный), белая обводка (отличимы от НСПД-точек), попап: напряжение / установленная / загрузка / **резерв для ТП** / статус / дата среза / дисклеймер ±100 м. Легенда под картой. - Числа через `toFiniteNumber` (урок #2114: Decimal→строка). ## Проверки - Backend: **39 тестов** (нормализатор, кВА-санити, DOCX vMerge, xlsx row-offsets на синтетике, endpoint 404/422) + ruff чист + psycopg3-guard чист. - Frontend: tsc/eslint/prettier чисты, SiteMap smoke 2/2 (MiniMap не сломан — новый prop опционален). - api-types.ts офлайн-регенерация: **+131/−0 строго аддитивно**. - **Deep-review: ⚠️ MINOR** → все 3 замечания исправлены в этом же коммите (NULLS NOT DISTINCT ×2, per-kind MAX(period), settlement-комментарий). ## После merge 1. Deploy применит миграцию 180 автоматически (schema-first, deploy.yml). 2. **Запустить лоадеры на проде** (docker exec → Celery tasks `sync_power_supply_centers`, `sync_water_reserves`) — до этого карточка честно показывает «Данные о резервах ПС загружаются». 3. Прод-верификация: скриншот §3 с маркерами ЦП + попап с резервом МВА + карточка с водным дефицитом.
bot-backend added 1 commit 2026-07-02 07:46:33 +00:00
feat(site-finder): резервы мощности для ТП — электро+вода на карте §3 (#2119 Фаза A)
All checks were successful
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Successful in 1m17s
CI / openapi-codegen-check (pull_request) Successful in 2m6s
CI / backend-tests (pull_request) Successful in 14m28s
e285cbe33a
Наполнение карты точками подключения с ХАРАКТЕРИСТИКАМИ (свободная мощность)
из верифицированных источников (research #2119). Все источники гео-блокируют
не-RU IP — лоадеры выполняются на проде (Celery weekly + ручной docker exec).

Backend:
- Миграция 180: power_supply_centers (ПС 35-220кВ, точки + резерв МВА),
  power_tp_rp_reserves (10.7k ТП/РП 6-10кВ, геокод — Фаза B),
  water_supply_reserves (ЦСВ/ЦСК Водоканала). UNIQUE NULLS NOT DISTINCT на
  nullable-ключах (грабли #140).
- rosseti_wfs_loader: открытый WFS портал-тп.рф (punycode) → 488 ПС Свердл обл,
  индекс загрузки 256184/6/8 → open/limited/closed, voltage из имени.
- rosseti_reserve_loader: раскрытие ПП№24 (xlsx) — ЦП 35-110кВ (строка 8+)
  матчится к WFS-точкам по нормализованному имени; ТП/РП <35кВ (строка 9+),
  кВА-санити (>2.5 МВА для ТП → ÷1000), «н/д»→NULL, SAVEPOINT per-row.
- vodokanal_reserve_loader: DOCX-раскрытие ПП№6 (stdlib parse, vMerge
  forward-fill), отрицательные резервы (город: дефицит) сохраняются со знаком.
- Endpoint GET /{cad}/connection-capacity: ПС в радиусе (ST_DWithin geography)
  + summary + вода за последний период per-system_kind. Celery: вт 04:00/04:30.

Frontend (§3):
- Карточка «Ресурсные резервы»: ближайший ЦП с резервом МВА + статус-бейдж;
  вода/канализация с красным «дефицит» при отрицательном резерве + примечание.
- Слой «Центры питания (резерв)» на карте: цвет по индексу загрузки
  (зелёный/янтарь/красный), попап с напряжением/мощностью/загрузкой/резервом,
  легенда под картой. Числа через toFiniteNumber (Decimal→str coercion).

api-types.ts перегенерён офлайн (+131/-0, аддитивно). 39 тестов зелёные.
Deep-review: ⚠️ MINOR → все 3 замечания исправлены (NULLS NOT DISTINCT,
per-kind MAX(period), settlement-комментарий).
bot-backend merged commit 4758ea5e2b into main 2026-07-02 08:36:52 +00:00
bot-backend deleted branch feat/connection-capacity-phase-a 2026-07-02 08:36:52 +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#2120
No description provided.