fix(site-finder): NO_ENGINEERING_NEARBY is a warning, not a verdict blocker (#1617)
Some checks failed
CI / changes (push) Successful in 9s
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (push) Has been skipped
CI / backend-tests (pull_request) Has been cancelled
CI / openapi-codegen-check (push) Failing after 1m40s
CI / frontend-tests (pull_request) Has been cancelled
CI / openapi-codegen-check (pull_request) Has been cancelled
CI / backend-tests (push) Failing after 8m47s
Some checks failed
CI / changes (push) Successful in 9s
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (push) Has been skipped
CI / backend-tests (pull_request) Has been cancelled
CI / openapi-codegen-check (push) Failing after 1m40s
CI / frontend-tests (pull_request) Has been cancelled
CI / openapi-codegen-check (pull_request) Has been cancelled
CI / backend-tests (push) Failing after 8m47s
Introduce INFORMATIONAL_WARNING_CODES frozenset; verdict assembly now only downgrades to «С ограничениями» when verdict-relevant warnings exist. NO_ENGINEERING_NEARBY still appears in warnings[] for display but a clean residential parcel (Ж-zone, no ЗОУИТ) correctly receives verdict_label=«Можно».
This commit is contained in:
parent
9a0ca9336f
commit
ac19ef4823
2 changed files with 46 additions and 4 deletions
|
|
@ -63,6 +63,11 @@ WARNING_TYPE_ZONE_KEYWORDS: tuple[str, ...] = ("сзз", "санитарно-з
|
|||
# Engineering nearby search radius (метры) — совпадает с quarter_dump_lookup.py
|
||||
ENGINEERING_NEARBY_THRESHOLD_M = 200
|
||||
|
||||
# Warning codes that are purely informational — they appear in warnings[] for the user
|
||||
# but do NOT downgrade the final verdict from «Можно» to «С ограничениями» (#1617).
|
||||
# A clean residential parcel with only these warnings still gets verdict_label="Можно".
|
||||
INFORMATIONAL_WARNING_CODES: frozenset[str] = frozenset({"NO_ENGINEERING_NEARBY"})
|
||||
|
||||
|
||||
# ── TypedDicts ────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -308,12 +313,17 @@ def compute_gate_verdict(
|
|||
)
|
||||
)
|
||||
|
||||
# Final verdict
|
||||
# Final verdict.
|
||||
# Informational warnings (e.g. NO_ENGINEERING_NEARBY) appear in warnings[] for display
|
||||
# but do NOT by themselves downgrade a clean parcel to «С ограничениями» (#1617).
|
||||
verdict_relevant_warnings = [
|
||||
w for w in warnings if w["code"] not in INFORMATIONAL_WARNING_CODES
|
||||
]
|
||||
can_build: bool | Literal["unknown"]
|
||||
if blockers:
|
||||
can_build = False
|
||||
label = "Нельзя"
|
||||
elif warnings:
|
||||
elif verdict_relevant_warnings:
|
||||
can_build = True
|
||||
label = "С ограничениями"
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -88,14 +88,46 @@ def test_zouit_non_blocker_subcategory_is_warning():
|
|||
|
||||
|
||||
def test_no_engineering_warning_not_blocker():
|
||||
"""Отсутствие инженерных сетей в 200м — предупреждение, не блокер."""
|
||||
"""NO_ENGINEERING_NEARBY — информационное предупреждение, не блокер и не даунгрейдит вердикт.
|
||||
|
||||
Чистый жилой участок (Ж-зона, нет ЗОУИТ) без сетей в 200м должен оставаться «Можно»
|
||||
— отсутствие сетей не является юридическим запретом на МКД (#1617).
|
||||
"""
|
||||
nspd_zoning = {"zone_code": "Ж-2", "zone_name": "Жилая"}
|
||||
verdict = compute_gate_verdict(nspd_zoning, [], [], {"available": True})
|
||||
assert verdict["can_build_mkd"] is True # warnings не блокируют
|
||||
assert verdict["can_build_mkd"] is True
|
||||
assert verdict["verdict_label"] == "Можно" # не «С ограничениями» (#1617)
|
||||
assert any(w["code"] == "NO_ENGINEERING_NEARBY" for w in verdict["warnings"])
|
||||
assert verdict["blockers"] == []
|
||||
|
||||
|
||||
def test_no_engineering_plus_real_warning_still_downgrades():
|
||||
"""NO_ENGINEERING_NEARBY совместно с реальным предупреждением (ЗОУИТ) → «С ограничениями».
|
||||
|
||||
Реальный ЗОУИТ-warning должен продолжать даунгрейдить вердикт;
|
||||
NO_ENGINEERING_NEARBY при этом тоже присутствует в warnings[] (#1617).
|
||||
"""
|
||||
nspd_zoning = {"zone_code": "Ж-2", "zone_name": "Жилая"}
|
||||
overlaps = [{"subcategory": 5, "name": "Придорожная полоса", "layer": "12345"}]
|
||||
# нет инженерных сетей рядом — пустой список
|
||||
verdict = compute_gate_verdict(nspd_zoning, overlaps, [], {"available": True})
|
||||
assert verdict["can_build_mkd"] is True
|
||||
assert verdict["verdict_label"] == "С ограничениями"
|
||||
assert any(w["code"] == "ZOUIT_SUB5" for w in verdict["warnings"])
|
||||
assert any(w["code"] == "NO_ENGINEERING_NEARBY" for w in verdict["warnings"])
|
||||
assert verdict["blockers"] == []
|
||||
|
||||
|
||||
def test_no_engineering_real_blocker_still_rejects():
|
||||
"""Реальный блокер (охранная зона ЛЭП) при отсутствии сетей → «Нельзя» (#1617)."""
|
||||
nspd_zoning = {"zone_code": "Ж-3", "zone_name": "Жилая"}
|
||||
overlaps = [{"subcategory": 17, "name": "ЛЭП 110кВ", "layer": "37578"}]
|
||||
verdict = compute_gate_verdict(nspd_zoning, overlaps, [], {"available": True})
|
||||
assert verdict["can_build_mkd"] is False
|
||||
assert verdict["verdict_label"] == "Нельзя"
|
||||
assert any(b["code"] == "ZOUIT_OVERLAP_SUB17" for b in verdict["blockers"])
|
||||
|
||||
|
||||
def test_stale_dump_marks_source_partial():
|
||||
"""stale=True → source='nspd_dump_partial'."""
|
||||
nspd_zoning = {"zone_code": "Ж-1", "zone_name": "Жилая"}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue