fix(market-metrics): resolve admin→micros for _price_sensitivity (#1211) #1259
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#1259
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/price-sensitivity-micro-districts"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #1211 (P2 silent correctness).
_price_sensitivityпередавал сырое admin-имя в_elasticity_coef, который фильтрует микро-вокабуляр → регрессия всегда FALLBACK.Bug
compute_market_metrics:364правильно резолвит admin → micros (resolve_objective_districts) для stock/sales. Но_price_sensitivity:523— НЕ резолвит, передаёт сырое 'Кировский' в_elasticity_coef, фильтрующийobjective_corpus_room_month.district = :dnгде district — микро ('Втузгородок', 'ЖБИ', ground-truth вdistrict_resolver+131_district_vocab_map.sql).Эффект: для 7 из 8 admin-районов регрессия получает 0 точек →
n=0<30→ всегда FALLBACK. §9.2 district-level эластичность молча не считалась в /analyze. Только 'Академический' совпадал в обоих вокабулярах случайно.Fix (Вариант 1 из issue)
_elasticity_coefрасширен: новый kwargdistricts: list[str] | None = None. None → legacycrm.district = :dn(back-compat для других caller'ов вanalytics_queries). Список →crm.district = ANY(CAST(:districts AS text[])). Пустой → EKB-wide._price_sensitivity: зовётresolve_objective_districts(db, district), передаётdistricts=micros if micros else [].psycopg v3
CAST(:districts AS text[])(rule изbackend.md).Test plan
TestPriceSensitivityDistrictResolution: admin→micros в SQL bind, None→EKB-wide, regression preserved post-resolve, graceful на exception.pytest tests/services/site_finder/test_market_metrics.py→ 76 passed.pytest -k "elasticity or sensitivity"→ 156 passed, 1 skipped.ruff check+ psycopg v3 grep → clean.price_sensitivity_source='regression'(не'fallback').Closes #1211
_price_sensitivity передавал сырое admin-имя ('Кировский') в _elasticity_coef, который фильтрует objective_corpus_room_month.district по МИКРО-вокабуляру (Втузгородок, ЖБИ, …) → регрессия получала 0 точек → всегда FALLBACK_ELASTICITY. §9.2 district-level эластичность молча НЕ считалась в /analyze-пути (только 'Академический' совпадал в обоих вокабулярах случайно). Fix: вызываем resolve_objective_districts() в _price_sensitivity и передаём список микро через новый kwarg districts=[…] в _elasticity_coef. Резолвер None ('не определён' / нет чистых алиасов) → пустой список → EKB-wide регрессия. _elasticity_coef расширен с back-compat: districts=None → legacy путь по district_name (другой caller в analytics_queries — отдельный bug class, вне scope). 5 новых юнит-тестов TestPriceSensitivityDistrictResolution: admin→micros в SQL bind, None→EKB-wide, regression preserved post-resolve, graceful. 76/76 market_metrics + 156/156 elasticity/sensitivity тестов зелёные. ruff + psycopg v3 grep clean. Closes #1211