feat(parcels): connection-points endpoint (Forgejo #115 Phase 1 backend) #190

Merged
lekss361 merged 5 commits from feat/115-connection-points-backend into main 2026-05-16 05:58:28 +00:00
Showing only changes of commit 0cf0ab3358 - Show all commits

View file

@ -19,6 +19,7 @@ from datetime import UTC, datetime, timedelta
from typing import Any from typing import Any
from sqlalchemy import text from sqlalchemy import text
from sqlalchemy.exc import OperationalError, ProgrammingError
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -505,7 +506,9 @@ def _get_parcel_wkt(db: Session, cad_num: str) -> str | None:
if row is not None and row[0] is not None: if row is not None and row[0] is not None:
return str(row[0]) return str(row[0])
# Fallback: кварталы (более крупный объект — менее точно, но лучше чем ничего) # Fallback: кварталы (более крупный объект — менее точно, но лучше чем ничего).
# cad_quarters_geom хранит 3-сегментные ключи (66:41:0204016), не 4-сегментные.
quarter_key = derive_quarter_cad(cad_num)
row = db.execute( row = db.execute(
text( text(
""" """
@ -515,7 +518,7 @@ def _get_parcel_wkt(db: Session, cad_num: str) -> str | None:
LIMIT 1 LIMIT 1
""" """
), ),
{"c": cad_num}, {"c": quarter_key},
).first() ).first()
if row is not None and row[0] is not None: if row is not None and row[0] is not None:
return str(row[0]) return str(row[0])
@ -573,7 +576,7 @@ def _get_engineering_structures_by_boundary(
), ),
{"q": quarter, "wkt": parcel_wkt, "radius_m": radius_m}, {"q": quarter, "wkt": parcel_wkt, "radius_m": radius_m},
).fetchall() ).fetchall()
except Exception as e: except (OperationalError, ProgrammingError) as e:
logger.warning( logger.warning(
"engineering_structures query failed for quarter=%s: %s", "engineering_structures query failed for quarter=%s: %s",
quarter, quarter,
@ -592,7 +595,7 @@ def _get_engineering_structures_by_boundary(
if geom_raw: if geom_raw:
try: try:
geom_dict = json.loads(geom_raw) geom_dict = json.loads(geom_raw)
except Exception: except (ValueError, json.JSONDecodeError):
geom_dict = {} geom_dict = {}
result.append( result.append(
@ -641,11 +644,12 @@ def _get_zouit_engineering_overlaps(
), ),
ST_GeomFromText(:wkt, 4326) ST_GeomFromText(:wkt, 4326)
) )
LIMIT 100
""" """
), ),
{"q": quarter, "wkt": parcel_wkt}, {"q": quarter, "wkt": parcel_wkt},
).fetchall() ).fetchall()
except Exception as e: except (OperationalError, ProgrammingError) as e:
logger.warning( logger.warning(
"zouit_engineering query failed for quarter=%s: %s", "zouit_engineering query failed for quarter=%s: %s",
quarter, quarter,
@ -662,7 +666,7 @@ def _get_zouit_engineering_overlaps(
if geom_raw: if geom_raw:
try: try:
geom_dict = json.loads(geom_raw) geom_dict = json.loads(geom_raw)
except Exception: except (ValueError, json.JSONDecodeError):
geom_dict = {} geom_dict = {}
subcategory_raw = props.get("subcategory") subcategory_raw = props.get("subcategory")