gendesign/backend/app/services/site_finder/pat_lookup.py
bot-backend 9736192359
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-backend (push) Successful in 1m25s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Successful in 2m26s
Deploy / deploy (push) Successful in 1m11s
feat(sf): подзоны ПАТ Кольцово → pat_subzones (#1150)
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-06-07 14:43:07 +00:00

65 lines
2.4 KiB
Python

"""ПАТ-lookup для site-finder analyze (#1065 / #1067).
Читает pat_subzones и возвращает подзоны ПАТ, пересекающие переданный участок.
Graceful: если таблица ещё не задеплоена или БД недоступна — возвращает пустой список.
Wiring в analyze_parcel — follow-up (не в этом PR).
"""
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__)
# ST_Intersects к pat_subzones, GIST idx_pat_subzones_geom.
# Исключаем subzone_no=0 (aggregate_outline) — клиент получает конкретные подзоны 1..6.
_PAT_INTERSECTS_SQL = text(
"""
SELECT subzone_no, name, restriction, aerodrome
FROM pat_subzones
WHERE subzone_no > 0
AND ST_Intersects(geom, ST_GeomFromText(CAST(:parcel_wkt AS text), 4326))
ORDER BY subzone_no
"""
)
def parcel_pat_subzones(db: Session, parcel_wkt: str | None) -> list[dict[str, Any]]:
"""Подзоны ПАТ, пересекающие участок.
Args:
db: SQLAlchemy-сессия.
parcel_wkt: геометрия участка WKT (EPSG:4326). None → пустой результат.
Returns:
Список dict [{subzone_no, name, restriction, aerodrome}] отсортированный
по subzone_no. Пустой список при отсутствии пересечений, ошибке БД
или недеплоенной таблице.
"""
if not parcel_wkt:
return []
try:
rows = db.execute(_PAT_INTERSECTS_SQL, {"parcel_wkt": parcel_wkt}).mappings().all()
except (OperationalError, ProgrammingError) as exc:
# Таблица ещё не задеплоена / структура изменилась — graceful degrade.
logger.warning("parcel_pat_subzones: pat_subzones недоступна, skip: %s", exc)
return []
return [
{
"subzone_no": r["subzone_no"],
"name": r["name"],
"restriction": r["restriction"],
"aerodrome": r["aerodrome"],
}
for r in rows
]
__all__ = ["parcel_pat_subzones"]