parent
f5aa7ed191
commit
d3aa396ceb
3 changed files with 55 additions and 1 deletions
|
|
@ -2994,7 +2994,7 @@ def analyze_parcel(
|
|||
if settings.enable_ird_analyze:
|
||||
try:
|
||||
result_payload["ird"] = build_ird_analyze_block(
|
||||
db, geom_wkt, centroid_lon, centroid_lat
|
||||
db, geom_wkt, centroid_lon, centroid_lat, cad_num
|
||||
)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ from sqlalchemy.orm import Session
|
|||
from app.services.scrapers.ekb_geoportal_client import EKBGeoportalClient
|
||||
from app.services.site_finder.ird_overlay_lookup import parcel_ird_overlaps
|
||||
from app.services.site_finder.planning_lookup import parcel_planning_overlaps
|
||||
from app.services.site_finder.reservation_lookup import parcel_reservations
|
||||
from app.services.site_finder.zone_regulation import get_or_fetch_zone_regulation
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -75,6 +76,7 @@ def build_ird_analyze_block(
|
|||
geom_wkt: str | None,
|
||||
lon: float | None,
|
||||
lat: float | None,
|
||||
cad_num: str | None = None,
|
||||
*,
|
||||
client: EKBGeoportalClient | None = None,
|
||||
) -> dict[str, Any]:
|
||||
|
|
@ -84,6 +86,8 @@ def build_ird_analyze_block(
|
|||
db: сессия.
|
||||
geom_wkt: геометрия участка WKT (EPSG:4326) для DB-overlay ``ird_overlays``.
|
||||
lon/lat: centroid участка (EPSG:4326) для geoportal-резолва функц.зоны/КРТ/регламента.
|
||||
cad_num: кадастровый номер ЗУ для lookup изъятия/резервирования (м.136 land_reservation).
|
||||
None → reservations=[].
|
||||
client: переиспользуемый EKBGeoportalClient (для тестов/одного TLS-пула). По умолчанию
|
||||
создаётся с укороченным timeout.
|
||||
|
||||
|
|
@ -91,6 +95,7 @@ def build_ird_analyze_block(
|
|||
dict: ``ird_overlaps``/``ird_by_kind`` (DB-overlay, incl opportunity_*),
|
||||
``opportunity_overlaps`` (подмножество layer_kind='opportunity_*'),
|
||||
``planning_projects`` (ППТ/ПМТ overlap, DB, м.134 #1085),
|
||||
``reservations`` (list, изъятие/резервирование из land_reservation по cad_num, #1091/#1062),
|
||||
``functional_zone`` (генплан, dict|None), ``krt`` (list), ``zone_regulation`` (dict|None).
|
||||
Любой источник деградирует независимо — блок всегда well-formed.
|
||||
"""
|
||||
|
|
@ -102,6 +107,7 @@ def build_ird_analyze_block(
|
|||
"ird_by_kind": overlay.get("ird_by_kind", {}),
|
||||
"opportunity_overlaps": opportunity,
|
||||
"planning_projects": parcel_planning_overlaps(db, geom_wkt),
|
||||
"reservations": parcel_reservations(db, cad_num),
|
||||
"functional_zone": None,
|
||||
"krt": [],
|
||||
"zone_regulation": None,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ _PLANNING = [{"project_type": "ppt", "doc_status_name": "действующий"
|
|||
def _patch_overlay(monkeypatch: Any, overlay: dict[str, Any]) -> None:
|
||||
monkeypatch.setattr(ird_analyze, "parcel_ird_overlaps", lambda db, wkt: overlay)
|
||||
monkeypatch.setattr(ird_analyze, "parcel_planning_overlaps", lambda db, wkt: list(_PLANNING))
|
||||
monkeypatch.setattr(ird_analyze, "parcel_reservations", lambda db, cad_num: [])
|
||||
|
||||
|
||||
def test_full_block_assembly(monkeypatch: Any) -> None:
|
||||
|
|
@ -191,3 +192,50 @@ def test_session_not_shared_between_threads(monkeypatch: Any) -> None:
|
|||
assert (
|
||||
zone_reg_thread[0] is main_thread
|
||||
), "zone_regulation должен исполняться в основном потоке, а не в фоновом (Session safety)"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Reservation tests (#1091, #1062)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
_RESERVATION_ROW = {
|
||||
"reservation_kind": "изъятие",
|
||||
"basis_act": "Постановление Правительства",
|
||||
"act_number": "12-ПП",
|
||||
"act_date": "2024-03-01",
|
||||
"purpose": "дорожное строительство",
|
||||
"doc_url": "https://example.com/doc.pdf",
|
||||
}
|
||||
|
||||
|
||||
def test_reservations_wired_to_block(monkeypatch: Any) -> None:
|
||||
"""cad_num передан → parcel_reservations возвращает запись → ключ reservations в block."""
|
||||
_patch_overlay(monkeypatch, _OVERLAY)
|
||||
monkeypatch.setattr(
|
||||
ird_analyze,
|
||||
"parcel_reservations",
|
||||
lambda db, cad_num: [_RESERVATION_ROW] if cad_num == "66:41:0101001:123" else [],
|
||||
)
|
||||
monkeypatch.setattr(ird_analyze, "get_or_fetch_zone_regulation", lambda *a, **kw: None)
|
||||
client = _FakeClient(fz=[], krt=[])
|
||||
|
||||
block = ird_analyze.build_ird_analyze_block(
|
||||
object(), "POINT(60 56)", None, None, "66:41:0101001:123", client=client
|
||||
)
|
||||
|
||||
assert "reservations" in block
|
||||
assert len(block["reservations"]) == 1
|
||||
assert block["reservations"][0]["reservation_kind"] == "изъятие"
|
||||
|
||||
|
||||
def test_reservations_none_cad_num_returns_empty(monkeypatch: Any) -> None:
|
||||
"""cad_num=None → reservations == [] (parcel_reservations graceful, ключ присутствует)."""
|
||||
_patch_overlay(monkeypatch, {"ird_overlaps": [], "ird_by_kind": {}})
|
||||
monkeypatch.setattr(ird_analyze, "get_or_fetch_zone_regulation", lambda *a, **kw: None)
|
||||
client = _FakeClient(fz=[], krt=[])
|
||||
|
||||
block = ird_analyze.build_ird_analyze_block(object(), None, None, None, None, client=client)
|
||||
|
||||
assert "reservations" in block
|
||||
assert block["reservations"] == []
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue