gendesign/backend/app/services/site_finder/functional_zone_lookup.py
lekss361 189ecc81f8
All checks were successful
Deploy / build-backend (push) Successful in 1m18s
Deploy / build-frontend (push) Has been skipped
Deploy / changes (push) Successful in 5s
Deploy / build-worker (push) Successful in 2m28s
Deploy / deploy (push) Successful in 1m17s
feat(sf): ingest функц.зон генплана ЕКБ-2045 из ГИСОГД-СО WFS → ekb_genplan_functional_zone (#1137)
Co-authored-by: lekss361 <lekss361@gendsgn.local>
Co-committed-by: lekss361 <lekss361@gendsgn.local>
2026-06-07 12:03:39 +00:00

68 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Lookup функциональных зон генплана ЕКБ-2045 для analyze_parcel (#1058).
Читает ``ekb_genplan_functional_zone`` (м.139) и отдаёт зоны, пересекающие участок.
Graceful: таблица ещё не задеплоена / ошибка БД / пустой wkt → возвращает [].
Analyze-врезка (вшивание в build_ird_analyze_block / analyze_parcel) — отдельный
follow-up после merge #1131, чтобы не конфликтить с ird-analyze PR.
Зеркалит ird_overlay_lookup.py (стиль, graceful handling, CAST psycopg v3).
"""
from __future__ import annotations
import logging
from typing import Any
from sqlalchemy import text
from sqlalchemy.exc import OperationalError, ProgrammingError
from sqlalchemy.orm import Session
logger = logging.getLogger(__name__)
# Spatial overlap участка: ST_Intersects через GIST idx_ekb_genplan_fz_geom.
# Участок передаётся как WKT в 4326. CAST psycopg v3 (НИКОГДА :x::type).
_ZONE_OVERLAP_SQL = text(
"""
SELECT zone_type, status, area_ha, zone_class_code
FROM ekb_genplan_functional_zone
WHERE ST_Intersects(geom, ST_GeomFromText(CAST(:parcel_wkt AS text), 4326))
ORDER BY zone_type, status
"""
)
def parcel_functional_zones(db: Session, parcel_wkt: str | None) -> list[dict[str, Any]]:
"""Функциональные зоны генплана, пересекающие участок.
Args:
db: SQLAlchemy-сессия.
parcel_wkt: геометрия участка в WKT (EPSG:4326). None → пустой результат.
Returns:
Список dict: [{zone_type, status, area_ha, zone_class_code}].
Пусто при: нет wkt / таблица не задеплоена / нет пересечений / ошибка БД.
"""
if not parcel_wkt:
return []
try:
rows = db.execute(_ZONE_OVERLAP_SQL, {"parcel_wkt": parcel_wkt}).mappings().all()
except (OperationalError, ProgrammingError) as exc:
# Таблица ещё не задеплоена или ошибка БД — graceful degrade (analyze не падает).
logger.warning(
"parcel_functional_zones: ekb_genplan_functional_zone недоступна, skip: %s", exc
)
return []
return [
{
"zone_type": r["zone_type"],
"status": r["status"],
"area_ha": float(r["area_ha"]) if r["area_ha"] is not None else None,
"zone_class_code": r["zone_class_code"],
}
for r in rows
]
__all__ = ["parcel_functional_zones"]