NSPD API client: единый интегратор слоёв (foundation для G1/G2/G3/E1/#93) #94

Closed
opened 2026-05-12 05:45:37 +00:00 by lekss361 · 4 comments
lekss361 commented 2026-05-12 05:45:37 +00:00 (Migrated from github.com)

Эшелон: Gate foundation (G1/G2/G3) + on-demand foundation (#93/#51/#44)

Контекст / открытие

При исследовании НСПД через debug browser (https://nspd.gov.ru/map) найдено:

  1. Тема PKK (theme_id=1) содержит 63 готовых слоя — все нужные нам данные про ВРИ, ПЗЗ, ЗОУИТ, кадастр, инженерку
  2. Тема ARN (theme_id=665) содержит 6 layers с heatmap квартирографии по площадям (0-25, 25-40, 40-60, 60-80, 80-100, 100+ м²) — для recommend_mix
  3. REST /api/geoportal/v2/search/geoportal?query={cad} возвращает GeoJSON Polygon + полные properties за один запрос:
    • geometry (EPSG:3857)
    • permitted_use_established_by_document (ВРИ) — закрывает G2 #29
    • land_record_category_type (категория земель) — закрывает G2 #29
    • land_record_area (площадь)
    • cost_value / cost_index (кадастровая стоимость)
    • quarter_cad_number (квартал)
    • readable_address
    • ownership_type, right_type

API endpoints (полная карта)

Endpoint Назначение
GET /api/geoportal/v1/layers-theme Список тем (6 шт)
GET /api/geoportal/v1/layers-theme-tree?themeId={id} Полный каталог слоёв в теме
GET /api/geoportal/v2/search/geoportal?query={cad} Поиск по cad — GeoJSON + properties
GET /api/aeggis/v4/{layerId}/wms?...&REQUEST=GetMap WMS render тайла
GET /api/aeggis/v4/{layerId}/wms?...&REQUEST=GetFeatureInfo&INFO_FORMAT=application/json&STYLES= Feature data на точке/bbox (STYLES обязателен)
GET /api/aeggis/v4/{layerId}/wms?...&REQUEST=GetLegendGraphic&FORMAT=application/json Legend (классификация subcategory)

WFS GetCapabilities отдаёт 404 — нет прямого GetFeature для bulk download полигонов. Workaround: bbox tiling через GetFeatureInfo.

Карта слоёв — что нам нужно

TIER 1 — критичные для МКД (Gate-факторы)

LayerId Title Назначение Закрывает
36048 Земельные участки ЕГРН parcel geometry + properties E1 #51, on-demand #93
36071 Кадастровые кварталы quarter geometry cad_quarters_geom (готово)
36049 Здания ЕГРН здания cad_buildings (готово), P2 #46
36328 Сооружения ЕГРН инженерные сооружения (трубы, ТП, ЦТП) I3 #44 (engineering)
875838 Территориальные зоны ПЗЗ (Жилая / Произв / Общ-делов / СХ) G1 #28
879243 Красные линии ПКК отступы для застройки Generative B1-1 #54

TIER 2 — ЗОУИТ (G3 #30)

LayerId Title Подкатегории
37577 ЗОУИТ ОКН Территория ОКН / Охранная зона ОКН / Зона регулирования застройки
37578 ЗОУИТ энергетики, связи, транспорта subcategory=16 транспорт · 17 инженерные коммуникации · 18 связи · 19 придорожная полоса · 21 защита населения · 28 радиотех
37580 ЗОУИТ природных Водоохранная зона / Прибрежная защитная полоса / СЗО водоснабжения / Зелёная зона
37579 ЗОУИТ охраняемых объектов СЗЗ предприятий / Санитарный разрыв / Запретные зоны военных складов / Пригородная зона
37581 Иные ЗОУИТ Зона публичного сервитута / Зона резервирования земель / ОЭЗ

TIER 3 — Risk / Negative factors

LayerId Title Зачем
872202 Подтопление hard risk для застройки
872205 Затопление hard risk
872203 Заболачивание grunt risk
872210 Обвально-осыпные процессы grunt risk
872211 Абразия водные участки
872153/155/164/182 Эрозия (водная/линейная/ветровая) / Опустынивание grunt
872206 Захламление clean-up cost
872222 Гари потенциал stress

TIER 4 — Нейтральные / opportunity

LayerId Title Зачем
875845 ООПТ блокер либо premium proximity
875832/835 Береговые линии view amenity
875866 Лесничества nature proximity
37299 ЗУ на аукционе opportunities для девелопера
37294 ЗУ по схеме расположения потенциальные участки
37298 ЗУ свободные от прав потенциальные
36473 ЗУ по проекту межевания будущие
875840 Территории ОКН проверка
37236 Кадастровая стоимость (heatmap) cross-check рынку
37758 Удельный показатель КС (heatmap) cross-check

TIER 5 — ARN тема (theme_id=665)

Quartirography heatmaps:

  • 872974 / 872975 / 872976 / 872977 / 872978 / 872979 — объекты по площадям (0-25, 25-40, 40-60, 60-80, 80-100, 100+ м²)

Foundation для smart recommend_mix в районах.

TIER 6 — Administrative

  • 36945 / 36070 — кадастровые округа / районы
  • 875817 / 875819 / 875831 — субъекты / МО / нас.пункты (для multi-region scaling)

Что сделать в этом issue

1. Унифицированный клиент backend/app/services/scrapers/nspd_client.py

class NSPDClient:
    BASE = "https://nspd.gov.ru/api"
    UA = "GenDesign/1.0 (+https://gendsgn.ru)"

    async def search_by_cad(self, cad: str) -> NSPDFeature | None:
        """REST поиск: 1 запрос = geometry + ВРИ + категория + кост."""
        # GET /geoportal/v2/search/geoportal?query={cad}

    async def get_feature_info(self, layer_id: int, lon: float, lat: float, buffer_m: int = 100) -> list[dict]:
        """WMS GetFeatureInfo на точке (с микро-bbox)."""

    async def get_features_in_bbox(self, layer_id: int, bbox_3857: tuple) -> list[dict]:
        """Bulk fetch features в bbox (workaround на отсутствие WFS)."""

    async def list_layers(self, theme_id: int = 1) -> list[dict]:
        """Все слои темы (для admin UI)."""

2. Сохранение в БД — расширить схему

  • cad_parcels_geom: добавить колонки permitted_use TEXT, land_category TEXT, cost_value NUMERIC, cost_per_m2 NUMERIC, readable_address TEXT, ownership_type TEXT, right_type TEXT, land_record_reg_date DATE
  • Новые таблицы:
    • nspd_territorial_zones (layerId=875838) — ПЗЗ зоны
    • nspd_zouit (объединённая для 37577-37581) с zouit_type enum (oks/energy/nature/security/other) + subcategory int
    • nspd_red_lines (879243)
    • nspd_risk_zones (объединённая для 872xxx — подтопление/затопление/эрозия)

3. Celery tasks per layer

  • tasks.nspd_sync.sync_territorial_zones_bbox(bbox)
  • tasks.nspd_sync.sync_zouit_all_types_bbox(bbox) — 5 layers за раз
  • tasks.nspd_sync.sync_risk_zones_bbox(bbox) — 872xxx
  • Beat schedule: ежеквартально (зоны меняются редко)

4. Rate limiting + WAF handling

  • Reuse существующий nspd_lite.py rate limiter + retry logic
  • Sentry alert при WAF block

5. Foundation для:

  • #93 on-demand fetch — использует search_by_cad
  • #28 G1 ПЗЗ — sync_territorial_zones_bbox заменяет shape-импорт с data.midural.ru
  • #29 G2 ВРИ — search_by_cad возвращает permitted_use + land_category одним вызовом
  • #30 G3 ЗОУИТ — sync_zouit_all_types_bbox для 5 layers
  • #51 E1 cad_parcels — bulk через search_by_cad для каждого cad
  • #44 I3 engineering — слой 36328 Сооружения + subcategory=17 из 37578

Acceptance

  • nspd_client.py с 4 методами + типизация
  • search_by_cad('66:41:0204016:10') возвращает полную карточку участка
  • Тер.зоны (875838) подгружены для Свердл (точечный test)
  • ЗОУИТ 5 layers подгружены для test bbox
  • Rate limit + retry на WAF
  • Тесты + Sentry alerts

Owner

backend-engineer (client + tasks) + database-expert (schema migrations)

Effort

~3-4 дня

Risks / open

  • НСПД может изменить API без warning — фиксировать contract в tests
  • WAF блокирует по IP — нужен прокси-pool в будущем (cross-ref B2B-реестр #52)
  • bbox tiling для бесшовного покрытия Свердл — нужна clever chunk strategy
**Эшелон:** Gate foundation (G1/G2/G3) + on-demand foundation (#93/#51/#44) ## Контекст / открытие При исследовании НСПД через debug browser (https://nspd.gov.ru/map) найдено: 1. **Тема PKK (theme_id=1)** содержит **63 готовых слоя** — все нужные нам данные про ВРИ, ПЗЗ, ЗОУИТ, кадастр, инженерку 2. **Тема ARN (theme_id=665)** содержит 6 layers с **heatmap квартирографии по площадям** (0-25, 25-40, 40-60, 60-80, 80-100, 100+ м²) — для recommend_mix 3. **REST `/api/geoportal/v2/search/geoportal?query={cad}`** возвращает GeoJSON Polygon + полные properties за **один запрос**: - `geometry` (EPSG:3857) - `permitted_use_established_by_document` (ВРИ) — закрывает G2 #29 - `land_record_category_type` (категория земель) — закрывает G2 #29 - `land_record_area` (площадь) - `cost_value` / `cost_index` (кадастровая стоимость) - `quarter_cad_number` (квартал) - `readable_address` - `ownership_type`, `right_type` ## API endpoints (полная карта) | Endpoint | Назначение | |---|---| | `GET /api/geoportal/v1/layers-theme` | Список тем (6 шт) | | `GET /api/geoportal/v1/layers-theme-tree?themeId={id}` | Полный каталог слоёв в теме | | `GET /api/geoportal/v2/search/geoportal?query={cad}` | **Поиск по cad — GeoJSON + properties** | | `GET /api/aeggis/v4/{layerId}/wms?...&REQUEST=GetMap` | WMS render тайла | | `GET /api/aeggis/v4/{layerId}/wms?...&REQUEST=GetFeatureInfo&INFO_FORMAT=application/json&STYLES=` | Feature data на точке/bbox (STYLES обязателен) | | `GET /api/aeggis/v4/{layerId}/wms?...&REQUEST=GetLegendGraphic&FORMAT=application/json` | Legend (классификация subcategory) | **WFS GetCapabilities отдаёт 404** — нет прямого GetFeature для bulk download полигонов. Workaround: bbox tiling через GetFeatureInfo. ## Карта слоёв — что нам нужно ### TIER 1 — критичные для МКД (Gate-факторы) | LayerId | Title | Назначение | Закрывает | |---|---|---|---| | 36048 | Земельные участки ЕГРН | parcel geometry + properties | E1 #51, on-demand #93 | | 36071 | Кадастровые кварталы | quarter geometry | cad_quarters_geom (готово) | | 36049 | Здания ЕГРН | здания | cad_buildings (готово), P2 #46 | | 36328 | Сооружения ЕГРН | инженерные сооружения (трубы, ТП, ЦТП) | I3 #44 (engineering) | | **875838** | **Территориальные зоны** | **ПЗЗ** (Жилая / Произв / Общ-делов / СХ) | **G1 #28** | | 879243 | Красные линии ПКК | отступы для застройки | Generative B1-1 #54 | ### TIER 2 — ЗОУИТ (G3 #30) | LayerId | Title | Подкатегории | |---|---|---| | 37577 | ЗОУИТ ОКН | Территория ОКН / Охранная зона ОКН / Зона регулирования застройки | | **37578** | **ЗОУИТ энергетики, связи, транспорта** | subcategory=16 транспорт · **17 инженерные коммуникации** · 18 связи · 19 придорожная полоса · 21 защита населения · 28 радиотех | | 37580 | ЗОУИТ природных | **Водоохранная зона / Прибрежная защитная полоса / СЗО водоснабжения** / Зелёная зона | | 37579 | ЗОУИТ охраняемых объектов | **СЗЗ предприятий** / Санитарный разрыв / Запретные зоны военных складов / Пригородная зона | | 37581 | Иные ЗОУИТ | Зона публичного сервитута / Зона резервирования земель / ОЭЗ | ### TIER 3 — Risk / Negative factors | LayerId | Title | Зачем | |---|---|---| | 872202 | Подтопление | hard risk для застройки | | 872205 | Затопление | hard risk | | 872203 | Заболачивание | grunt risk | | 872210 | Обвально-осыпные процессы | grunt risk | | 872211 | Абразия | водные участки | | 872153/155/164/182 | Эрозия (водная/линейная/ветровая) / Опустынивание | grunt | | 872206 | Захламление | clean-up cost | | 872222 | Гари | потенциал stress | ### TIER 4 — Нейтральные / opportunity | LayerId | Title | Зачем | |---|---|---| | 875845 | ООПТ | блокер либо premium proximity | | 875832/835 | Береговые линии | view amenity | | 875866 | Лесничества | nature proximity | | 37299 | ЗУ на аукционе | **opportunities для девелопера** | | 37294 | ЗУ по схеме расположения | потенциальные участки | | 37298 | ЗУ свободные от прав | потенциальные | | 36473 | ЗУ по проекту межевания | будущие | | 875840 | Территории ОКН | проверка | | 37236 | Кадастровая стоимость (heatmap) | cross-check рынку | | 37758 | Удельный показатель КС (heatmap) | cross-check | ### TIER 5 — ARN тема (theme_id=665) Quartirography heatmaps: - 872974 / 872975 / 872976 / 872977 / 872978 / 872979 — объекты по площадям (0-25, 25-40, 40-60, 60-80, 80-100, 100+ м²) Foundation для smart recommend_mix в районах. ### TIER 6 — Administrative - 36945 / 36070 — кадастровые округа / районы - 875817 / 875819 / 875831 — субъекты / МО / нас.пункты (для multi-region scaling) ## Что сделать в этом issue ### 1. Унифицированный клиент `backend/app/services/scrapers/nspd_client.py` ```python class NSPDClient: BASE = "https://nspd.gov.ru/api" UA = "GenDesign/1.0 (+https://gendsgn.ru)" async def search_by_cad(self, cad: str) -> NSPDFeature | None: """REST поиск: 1 запрос = geometry + ВРИ + категория + кост.""" # GET /geoportal/v2/search/geoportal?query={cad} async def get_feature_info(self, layer_id: int, lon: float, lat: float, buffer_m: int = 100) -> list[dict]: """WMS GetFeatureInfo на точке (с микро-bbox).""" async def get_features_in_bbox(self, layer_id: int, bbox_3857: tuple) -> list[dict]: """Bulk fetch features в bbox (workaround на отсутствие WFS).""" async def list_layers(self, theme_id: int = 1) -> list[dict]: """Все слои темы (для admin UI).""" ``` ### 2. Сохранение в БД — расширить схему - `cad_parcels_geom`: добавить колонки `permitted_use TEXT`, `land_category TEXT`, `cost_value NUMERIC`, `cost_per_m2 NUMERIC`, `readable_address TEXT`, `ownership_type TEXT`, `right_type TEXT`, `land_record_reg_date DATE` - Новые таблицы: - `nspd_territorial_zones` (layerId=875838) — ПЗЗ зоны - `nspd_zouit` (объединённая для 37577-37581) с `zouit_type` enum (oks/energy/nature/security/other) + `subcategory` int - `nspd_red_lines` (879243) - `nspd_risk_zones` (объединённая для 872xxx — подтопление/затопление/эрозия) ### 3. Celery tasks per layer - `tasks.nspd_sync.sync_territorial_zones_bbox(bbox)` - `tasks.nspd_sync.sync_zouit_all_types_bbox(bbox)` — 5 layers за раз - `tasks.nspd_sync.sync_risk_zones_bbox(bbox)` — 872xxx - Beat schedule: ежеквартально (зоны меняются редко) ### 4. Rate limiting + WAF handling - Reuse существующий `nspd_lite.py` rate limiter + retry logic - Sentry alert при WAF block ### 5. Foundation для: - **#93** on-demand fetch — использует `search_by_cad` - **#28 G1** ПЗЗ — `sync_territorial_zones_bbox` заменяет shape-импорт с data.midural.ru - **#29 G2** ВРИ — `search_by_cad` возвращает permitted_use + land_category одним вызовом - **#30 G3** ЗОУИТ — `sync_zouit_all_types_bbox` для 5 layers - **#51 E1** cad_parcels — bulk через search_by_cad для каждого cad - **#44 I3** engineering — слой 36328 Сооружения + subcategory=17 из 37578 ## Acceptance - [ ] `nspd_client.py` с 4 методами + типизация - [ ] `search_by_cad('66:41:0204016:10')` возвращает полную карточку участка - [ ] Тер.зоны (875838) подгружены для Свердл (точечный test) - [ ] ЗОУИТ 5 layers подгружены для test bbox - [ ] Rate limit + retry на WAF - [ ] Тесты + Sentry alerts ## Owner `backend-engineer` (client + tasks) + `database-expert` (schema migrations) ## Effort ~3-4 дня ## Risks / open - НСПД может изменить API без warning — фиксировать contract в tests - WAF блокирует по IP — нужен прокси-pool в будущем (cross-ref B2B-реестр #52) - bbox tiling для бесшовного покрытия Свердл — нужна clever chunk strategy ## Links - Foundation для: #93, #28, #29, #30, #51, #44 - B2B registry cross-ref: #52
lekss361 commented 2026-05-12 11:54:12 +00:00 (Migrated from github.com)

Update 2026-05-12 — Scope refactor: REST search-by-quarter = PRIMARY pattern

После user-driven теста через debug Chrome подтверждено: REST /api/geoportal/v2/search/geoportal?query={cad_quarter} отдаёт ВСЕ объекты в кадастровом квартале одним запросом — это радикально упрощает scope этого issue.

Тест на квартале 66:41:0303161 (Крауля/Викулова, Верх-Исетский р-н ЕКБ)

117 features за 1 запрос:

  • Земельные участки ЕГРН (36368): 20
  • Здания (36369): 20 ← включая МКД с purpose="Многоквартирный дом"
  • Помещения (38489): 20 ← per-flat кадастр.стоимость
  • Машино-места (38490): 20 ← parking ratio
  • Сооружения (36370): 13 ← инженерка part 1
  • Сооружения ЕГРН (36328): 7 ← инженерка part 2
  • ЗОУИТ (37577-37581): 15 ← возвращаются (где WMS отдаёт пусто!)
  • Кадастровые кварталы (36071): 1
  • ЕНК: 1

Sample МКД (точно то, что нужно P2 #46)

{
  "cad_num": "66:41:0303161:66",
  "purpose": "Многоквартирный дом",
  "floors": "5",
  "year_built": "1971",
  "cost_value": 412246998.72,
  "cost_index": 39109.65,
  "build_record_area": 10540.8,
  "readable_address": "ул.Крауля, дом 82"
}

Новый scope для этого issue

ПЕРВИЧНЫЙ метод (был secondary):

async def search_by_quarter(self, cad_quarter: str) -> QuarterDump:
    """1 запрос = ВСЕ объекты в кадастр.квартале (до 117 features)."""
    url = f"{self.BASE}/geoportal/v2/search/geoportal"
    r = await self._client.get(url, params={"query": cad_quarter})
    return QuarterDump.from_response(r.json())  # 9 категорий

Secondary методы (для bbox-based layers):

async def get_pzz_zones_in_bbox(self, bbox_3857: tuple) -> list[dict]:
    """875838 Тер.зоны — не в search-by-quarter, только bbox."""

async def get_red_lines_in_bbox(self, bbox_3857: tuple) -> list[dict]:
    """879243 Красные линии — bbox."""

async def get_risk_zones_in_bbox(self, bbox_3857: tuple) -> list[dict]:
    """872xxx подтопление/затопление/эрозия — bbox."""

Что упрощается / закрывается одновременно

Issue Effect
#29 G2 ВРИ закрыт — permitted_use_established_by_document в parcels.options
#30 G3 ЗОУИТ упрощён — 5 layers bbox tiling больше не нужен
#44 I3 engineering upgrade — Сооружения 36370+36328 + ЗОУИТ sc=17 per-quarter
#46 P2 cad_buildings bundled — полная атрибуция в одном запросе
#51 E1 cad_parcels N раз меньше запросов
#93 on-demand cache-friendly — подгружаем весь квартал
#101 theme 99 ⏸ кандидат на close (см. отдельный коммент)

Effort revision

  • Было: 3-4 дня (WMS GetMap + GetFeatureInfo + bbox tiling парсер)
  • Стало: 1.5-2 дня (REST client + QuarterDump parser + Celery task)

Schema impact (требуется отдельная migration)

Новая data/sql/86_nspd_quarter_dumps.sql:

  • nspd_quarter_dumps (cad_quarter PK, fetched_at, total_features, raw_response JSONB)
  • nspd_buildings (cad_num PK, purpose, floors, year_built, cost_value, geom 3857 + geom_msk66 generated, raw_props)
  • Аналогично: nspd_parcels, nspd_constructions, nspd_flats, nspd_parking, nspd_zouit
  • GIST indexes на geom и geom_msk66
  • Partial index WHERE purpose = 'Многоквартирный дом' для МКД-фильтров

Production-ready проверки

  • Endpoint без ESIA / без paywall
  • Стабильно за multiple запросов
  • Полный GeoJSON Polygon + properties в одном response
  • Включает ЗОУИТ (где WMS отдаёт пусто)
  • Rate 1 req/s безопасно (12K кварталов ЕКБ = ~3.5 часа full scan)

Performance оценка

  • ЕКБ ≈ 12 000 кадастровых кварталов
  • Rate 1 req/s → ~3.5 часа full scan (Celery beat раз в квартал)
  • Per-quarter payload: 50-150 KB JSON (117 features w/ geometry)

См. NSPD_API_Map_May12 Update part 6 для полной документации pattern.

## Update 2026-05-12 — Scope refactor: REST search-by-quarter = PRIMARY pattern После user-driven теста через debug Chrome подтверждено: REST `/api/geoportal/v2/search/geoportal?query={cad_quarter}` отдаёт **ВСЕ объекты в кадастровом квартале** одним запросом — это радикально упрощает scope этого issue. ### Тест на квартале 66:41:0303161 (Крауля/Викулова, Верх-Исетский р-н ЕКБ) **117 features за 1 запрос:** - Земельные участки ЕГРН (36368): 20 - Здания (36369): 20 ← включая **МКД с purpose="Многоквартирный дом"** - Помещения (38489): 20 ← per-flat кадастр.стоимость - Машино-места (38490): 20 ← parking ratio - Сооружения (36370): 13 ← инженерка part 1 - Сооружения ЕГРН (36328): 7 ← инженерка part 2 - ЗОУИТ (37577-37581): 15 ← **возвращаются (где WMS отдаёт пусто!)** - Кадастровые кварталы (36071): 1 - ЕНК: 1 ### Sample МКД (точно то, что нужно P2 #46) ```json { "cad_num": "66:41:0303161:66", "purpose": "Многоквартирный дом", "floors": "5", "year_built": "1971", "cost_value": 412246998.72, "cost_index": 39109.65, "build_record_area": 10540.8, "readable_address": "ул.Крауля, дом 82" } ``` ### Новый scope для этого issue **ПЕРВИЧНЫЙ метод (был secondary):** ```python async def search_by_quarter(self, cad_quarter: str) -> QuarterDump: """1 запрос = ВСЕ объекты в кадастр.квартале (до 117 features).""" url = f"{self.BASE}/geoportal/v2/search/geoportal" r = await self._client.get(url, params={"query": cad_quarter}) return QuarterDump.from_response(r.json()) # 9 категорий ``` **Secondary методы (для bbox-based layers):** ```python async def get_pzz_zones_in_bbox(self, bbox_3857: tuple) -> list[dict]: """875838 Тер.зоны — не в search-by-quarter, только bbox.""" async def get_red_lines_in_bbox(self, bbox_3857: tuple) -> list[dict]: """879243 Красные линии — bbox.""" async def get_risk_zones_in_bbox(self, bbox_3857: tuple) -> list[dict]: """872xxx подтопление/затопление/эрозия — bbox.""" ``` ### Что упрощается / закрывается одновременно | Issue | Effect | |---|---| | #29 G2 ВРИ | ✅ закрыт — `permitted_use_established_by_document` в parcels.options | | #30 G3 ЗОУИТ | ✅ упрощён — 5 layers bbox tiling больше не нужен | | #44 I3 engineering | ✅ upgrade — Сооружения 36370+36328 + ЗОУИТ sc=17 per-quarter | | #46 P2 cad_buildings | ✅ bundled — полная атрибуция в одном запросе | | #51 E1 cad_parcels | ✅ N раз меньше запросов | | #93 on-demand | ✅ cache-friendly — подгружаем весь квартал | | #101 theme 99 | ⏸ кандидат на close (см. отдельный коммент) | ### Effort revision - **Было:** 3-4 дня (WMS GetMap + GetFeatureInfo + bbox tiling парсер) - **Стало:** 1.5-2 дня (REST client + QuarterDump parser + Celery task) ### Schema impact (требуется отдельная migration) Новая `data/sql/86_nspd_quarter_dumps.sql`: - `nspd_quarter_dumps` (cad_quarter PK, fetched_at, total_features, raw_response JSONB) - `nspd_buildings` (cad_num PK, purpose, floors, year_built, cost_value, geom 3857 + geom_msk66 generated, raw_props) - Аналогично: nspd_parcels, nspd_constructions, nspd_flats, nspd_parking, nspd_zouit - GIST indexes на geom и geom_msk66 - Partial index `WHERE purpose = 'Многоквартирный дом'` для МКД-фильтров ### Production-ready проверки - ✅ Endpoint без ESIA / без paywall - ✅ Стабильно за multiple запросов - ✅ Полный GeoJSON Polygon + properties в одном response - ✅ Включает ЗОУИТ (где WMS отдаёт пусто) - ✅ Rate 1 req/s безопасно (12K кварталов ЕКБ = ~3.5 часа full scan) ### Performance оценка - ЕКБ ≈ 12 000 кадастровых кварталов - Rate 1 req/s → ~3.5 часа full scan (Celery beat раз в квартал) - Per-quarter payload: 50-150 KB JSON (117 features w/ geometry) См. [[NSPD_API_Map_May12]] Update part 6 для полной документации pattern.
Owner

Working on this in sub-PRs. PR 1 (TIER 3 risk zones) open at #217. Roadmap: PR2 (TIER 4 opportunity + red lines), PR3 (denorm entity tables), PR4 (TIER 5 ARN).

Working on this in sub-PRs. **PR 1 (TIER 3 risk zones)** open at #217. Roadmap: PR2 (TIER 4 opportunity + red lines), PR3 (denorm entity tables), PR4 (TIER 5 ARN).
Owner

Roadmap progress (2026-05-16)

  • PR1 — TIER 3 risk zones (#217) merged + deployed. 11 layers (flooding/landslide/burns/erosion). _get_risk_zones + NspdRiskZonesBlock (severity badges).
  • PR2 — TIER 4 opportunity (auction/scheme/free/future/oopt) + red lines (#220) merged + deployed. Denorm cols has_auction_parcels, opportunity_count. _get_red_lines использует ST_Length(ST_Intersection(planar)::geography) (после code-reviewer fix — изначально был bug с ST_Area на LINESTRING).
  • PR3 — denorm nspd_parcels + nspd_buildings (#222 — open, awaiting bot review). Foundation для downstream features (МКД neighbors, parcel attrs).
  • PR4 — TIER 5 ARN квартирография heatmap (~450 LOC) — pending.

Total прогресс: 2/4 merged + deployed, 1/4 in review, 1/4 pending.

## Roadmap progress (2026-05-16) - ✅ **PR1** — TIER 3 risk zones (#217) merged + deployed. 11 layers (flooding/landslide/burns/erosion). `_get_risk_zones` + `NspdRiskZonesBlock` (severity badges). - ✅ **PR2** — TIER 4 opportunity (auction/scheme/free/future/oopt) + red lines (#220) merged + deployed. Denorm cols `has_auction_parcels`, `opportunity_count`. `_get_red_lines` использует `ST_Length(ST_Intersection(planar)::geography)` (после code-reviewer fix — изначально был bug с `ST_Area` на LINESTRING). - ⏳ **PR3** — denorm `nspd_parcels` + `nspd_buildings` (#222 — open, awaiting bot review). Foundation для downstream features (МКД neighbors, parcel attrs). - ⏳ **PR4** — TIER 5 ARN квартирография heatmap (~450 LOC) — pending. Total прогресс: 2/4 merged + deployed, 1/4 in review, 1/4 pending.
Collaborator

DRIFT — реализовано (ground-truth 2026-06-13), трекер отставал.

NSPDClient полностью реализован — nspd_client.py (43KB): search_by_cad, get_feature_info, get_features_in_bbox(_grid), search_by_quarter, list_layers, LAYERS map. Foundation готов (commits #1077/#1080/#247). Closed as implemented.

**DRIFT — реализовано (ground-truth 2026-06-13), трекер отставал.** NSPDClient полностью реализован — `nspd_client.py` (43KB): search_by_cad, get_feature_info, get_features_in_bbox(_grid), search_by_quarter, list_layers, LAYERS map. Foundation готов (commits #1077/#1080/#247). Closed as implemented.
Sign in to join this conversation.
No project
No assignees
3 participants
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#94
No description provided.