gendesign/backend/app/services/site_finder/planning_lookup.py
bot-backend c93d6cbde1
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Successful in 2m15s
Deploy / build-worker (push) Successful in 3m14s
Deploy / deploy (push) Successful in 1m28s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 10s
fix(ptica): шесть lookup'ов /analyze глотали ошибку БД без SAVEPOINT (#2464) (#2951)
2026-08-20 07:38:23 +00:00

62 lines
3.1 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.

"""ППТ/ПМТ planning-overlay lookup для analyze_parcel (#1085 analyze-wiring).
Читает ``planning_projects`` (м.134, наполняется planning_harvest #1085) и отдаёт проекты
планировки/межевания, пересекающие участок: что/где утверждено к застройке (future-supply).
Комплементарно ИРД-overlay (``ird_overlay_lookup``): тот — ограничения участка, этот — граддоки.
Graceful: если таблица ``planning_projects`` ещё не задеплоена (pre-migration) или БД-ошибка —
возвращает пустой список (analyze не падает). Wiring в analyze — за тем же флагом, что ИРД (D9b).
"""
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__)
# ППТ/ПМТ overlap по участку: ST_Intersects через GIST idx_planning_projects_geom. geom уже 4326
# (harvest стор WFS geoloc как 4326). Участок — WKT в 4326. CAST psycopg v3.
_PLANNING_OVERLAP_SQL = text(
"""
SELECT project_type, doc_status_name, full_name, project_name, dmd_actual_year
FROM planning_projects
WHERE ST_Intersects(geom, ST_GeomFromText(CAST(:parcel_wkt AS text), 4326))
ORDER BY project_type, dmd_actual_year DESC NULLS LAST
"""
)
def parcel_planning_overlaps(db: Session, parcel_wkt: str | None) -> list[dict[str, Any]]:
"""ППТ/ПМТ, пересекающие участок.
Args:
db: сессия.
parcel_wkt: геометрия участка в WKT (EPSG:4326). None → пустой список.
Returns:
list[{project_type, doc_status_name, full_name, project_name, dmd_actual_year}].
Пусто при отсутствии участка/таблицы/пересечений (analyze не падает).
"""
if not parcel_wkt:
return []
try:
# #2464: SAVEPOINT перед проглатыванием ошибки. Сессия ОБЩАЯ с analyze_parcel
# (build_ird_analyze_block зовёт шесть таких lookup'ов подряд в одном словаре),
# и на Postgres упавший запрос оставляет транзакцию в aborted-состоянии —
# падают все следующие, включая запись прогона. Образец рядом:
# ppt_tep_lookup.py делает ровно так же.
with db.begin_nested():
rows = db.execute(_PLANNING_OVERLAP_SQL, {"parcel_wkt": parcel_wkt}).mappings().all()
except (OperationalError, ProgrammingError) as exc:
# Таблица ещё не задеплоена / БД-ошибка — graceful degrade.
logger.warning("parcel_planning_overlaps: planning_projects недоступна, skip: %s", exc)
return []
return [dict(r) for r in rows]
__all__ = ["parcel_planning_overlaps"]