gendesign/backend/tests/services/test_ird_analyze.py
lekss361 53e76738b4
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-worker (push) Successful in 2m26s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m22s
Deploy / deploy (push) Successful in 1m14s
feat(sf): wire ППТ/ПМТ planning_projects в analyze ird-блок (#1105)
planning_lookup.py (parcel_planning_overlaps, ST_Intersects через GIST idx_planning_projects_geom) + ird_analyze.py ключ planning_projects (DB-only). ППТ/ПМТ overlap участка в analyze ird-блоке. За флагом enable_ird_analyze (OFF), parcels.py не тронут. Зеркалит ird_overlay_lookup. Зависит от #1104 (м.134). 7 тестов.

Refs #1085.
Co-authored-by: lekss361 <lekss361@gendsgn.local>
Co-committed-by: lekss361 <lekss361@gendsgn.local>
2026-06-06 20:50:34 +00:00

118 lines
4.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.

"""Тесты build_ird_analyze_block (#1067 D9b analyze-wiring).
DB/сеть не дёргаются: мокаем parcel_ird_overlaps + get_or_fetch_zone_regulation (module-level)
и передаём fake EKBGeoportalClient. Проверяем сборку блока, split opportunity_*, graceful-деградацию
каждого источника и skip geoportal при отсутствии centroid.
"""
from __future__ import annotations
from typing import Any
from app.services.site_finder import ird_analyze
class _Feat:
def __init__(self, properties: dict[str, Any]) -> None:
self.properties = properties
class _FakeClient:
def __init__(self, *, fz: list[_Feat], krt: list[_Feat], boom: bool = False) -> None:
self._fz = fz
self._krt = krt
self._boom = boom
self.calls: list[tuple[str, float, float]] = []
def features_at_point(self, layer: str, lon: float, lat: float) -> list[_Feat]:
self.calls.append((layer, lon, lat))
if self._boom:
raise RuntimeError("geoportal down")
return self._fz if layer == "functional_zone" else self._krt
_OVERLAY = {
"ird_overlaps": [
{"layer_kind": "zouit_okn", "reg_numb_border": "66:41-6.1"},
{"layer_kind": "opportunity_auction", "reg_numb_border": "66:41:1:10"},
{"layer_kind": "opportunity_krt", "reg_numb_border": None},
],
"ird_by_kind": {"zouit_okn": 1, "opportunity_auction": 1, "opportunity_krt": 1},
}
_PLANNING = [{"project_type": "ppt", "doc_status_name": "действующий", "full_name": "ПАГЕ №1"}]
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))
def test_full_block_assembly(monkeypatch: Any) -> None:
"""Все источники → overlaps + split opportunity + функц.зона + КРТ + регламент."""
_patch_overlay(monkeypatch, _OVERLAY)
monkeypatch.setattr(
ird_analyze,
"get_or_fetch_zone_regulation",
lambda db, lon, lat, client=None: {"zone_index": "Ц-1"},
)
client = _FakeClient(fz=[_Feat({"name": "Ж-зона"})], krt=[_Feat({"num_oks_krt": "КРТ-7"})])
block = ird_analyze.build_ird_analyze_block(object(), "POINT(60 56)", 60.6, 56.8, client=client)
assert len(block["ird_overlaps"]) == 3
assert block["ird_by_kind"]["opportunity_auction"] == 1
assert [o["layer_kind"] for o in block["opportunity_overlaps"]] == [
"opportunity_auction",
"opportunity_krt",
]
assert block["functional_zone"] == {"name": "Ж-зона"}
assert block["krt"] == [{"num_oks_krt": "КРТ-7"}]
assert block["zone_regulation"] == {"zone_index": "Ц-1"}
assert block["planning_projects"] == _PLANNING
def test_geoportal_failure_is_graceful(monkeypatch: Any) -> None:
"""Сбой геопортала → функц.зона None, КРТ [], регламент None; overlaps уцелели."""
_patch_overlay(monkeypatch, _OVERLAY)
def _boom(*a: Any, **kw: Any) -> Any:
raise RuntimeError("zone reg down")
monkeypatch.setattr(ird_analyze, "get_or_fetch_zone_regulation", _boom)
client = _FakeClient(fz=[], krt=[], boom=True)
block = ird_analyze.build_ird_analyze_block(object(), "POINT(60 56)", 60.6, 56.8, client=client)
assert len(block["ird_overlaps"]) == 3 # DB-overlay не задет
assert block["functional_zone"] is None
assert block["krt"] == []
assert block["zone_regulation"] is None
def test_no_centroid_skips_geoportal(monkeypatch: Any) -> None:
"""lon/lat None → только DB-overlay, geoportal не зовётся (client.calls пуст)."""
_patch_overlay(monkeypatch, _OVERLAY)
client = _FakeClient(fz=[_Feat({"x": 1})], krt=[])
block = ird_analyze.build_ird_analyze_block(object(), "POINT(60 56)", None, None, client=client)
assert client.calls == []
assert block["functional_zone"] is None
assert block["krt"] == []
assert block["zone_regulation"] is None
assert len(block["ird_overlaps"]) == 3
def test_empty_overlay(monkeypatch: Any) -> None:
"""Пустой overlay → пустые списки, без KeyError."""
_patch_overlay(monkeypatch, {"ird_overlaps": [], "ird_by_kind": {}})
client = _FakeClient(fz=[], krt=[])
monkeypatch.setattr(ird_analyze, "get_or_fetch_zone_regulation", lambda *a, **kw: None)
block = ird_analyze.build_ird_analyze_block(object(), None, None, None, client=client)
assert block["ird_overlaps"] == []
assert block["opportunity_overlaps"] == []
assert block["ird_by_kind"] == {}