fix(tradein): sync n_analogs to anchor count when anchor drives headline (#695)
QA-fail after #738: that PR de-contradicted the explanation STRING, but n_analogs stayed = radius count (listings_clean) while the same-building anchor (#691/#694) replaced the headline + analogs list with the house comps. So every UI counter («Аналогов N», «Показано N из M», «по N аналогам», histogram) still read the radius number — producing «Показано 5 из 4» on the Олимп penthouse (radius=4, anchor=5). #738's Малышева case passed only because radius==anchor (14=14) — mimicry, not a fix. Fix: when anchor_tier is not None, set n_analogs = anchor['n'] (the comp count the estimate is actually built on, = the displayed analogs capped at 10). All counters now agree. Per #698, for the anchor path that IS the «full count found». Radius path unchanged. Refs #695
This commit is contained in:
parent
2b3eb0b23d
commit
d688d24a12
2 changed files with 28 additions and 0 deletions
|
|
@ -1818,6 +1818,14 @@ async def estimate_quality(
|
|||
f"Оценка построена по {anchor['n']} аналогам из {tier_label}"
|
||||
f"{' (топ-уровень в доме)' if anchor['used_uplift'] else ''}."
|
||||
) + repair_note
|
||||
# #695 (QA fixup): когда якорь подменяет headline и список аналогов на
|
||||
# комплы дома, n_analogs ДОЛЖЕН считаться по anchor-популяции, а не по
|
||||
# радиусу (listings_clean). Иначе все UI-счётчики («Аналогов N»,
|
||||
# «Показано N из M», «по N аналогам», гистограмма) расходятся: radius=4 vs
|
||||
# anchor=5 → артефакт «Показано 5 из 4». anchor['n'] = число комплов, на
|
||||
# которых построена оценка (= показываемый analogs, capped 10). Для anchor-
|
||||
# пути это и есть «полное число найденных» по контракту n_analogs (#698).
|
||||
n_analogs = anchor["n"]
|
||||
|
||||
# ── #651: IMV / Yandex BLEND (killer accuracy fix) — SECONDARY, Tier D only ──
|
||||
# Радиусная медиана системно занижает премиум/видовые квартиры (нет class/
|
||||
|
|
|
|||
|
|
@ -947,3 +947,23 @@ def test_explanation_radius_path_keeps_base_text() -> None:
|
|||
exp = est.confidence_explanation or ""
|
||||
assert "Найдено" in exp
|
||||
assert "Оценка построена по" not in exp # якорной фразы нет на чистом радиусе
|
||||
|
||||
|
||||
# ── #695 QA fixup: n_analogs синхронизируется с anchor-популяцией (radius≠anchor) ──
|
||||
|
||||
|
||||
def test_anchor_n_analogs_syncs_to_anchor_count() -> None:
|
||||
"""#695 QA-fail: anchor подменяет headline+список на комплы дома, но n_analogs
|
||||
раньше оставался радиусным → «Показано 5 из 4». radius=5 ≠ anchor=3 намеренно;
|
||||
n_analogs ДОЛЖЕН стать 3 (anchor), согласуясь с «по 3 аналогам» в explanation."""
|
||||
radius = [_make_listing(price_per_m2=200_000.0) for _ in range(5)]
|
||||
est = _run_estimate(anchor_comps=_SB_COMPS_PREMIUM, anchor_tier="A", radius_analogs=radius)
|
||||
assert est.n_analogs == 3 # = len(_SB_COMPS_PREMIUM), НЕ 5 (радиус)
|
||||
assert "по 3 аналогам" in (est.confidence_explanation or "")
|
||||
|
||||
|
||||
def test_radius_path_n_analogs_unchanged() -> None:
|
||||
"""#695 контроль: без якоря n_analogs = радиусный счёт (поведение не меняется)."""
|
||||
radius = [_make_listing(price_per_m2=200_000.0) for _ in range(5)]
|
||||
est = _run_estimate(anchor_comps=[], anchor_tier=None, radius_analogs=radius)
|
||||
assert est.n_analogs == 5
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue