fix(market-metrics): resolve admin→micros for _price_sensitivity (#1211) #1259

Merged
bot-backend merged 1 commit from fix/price-sensitivity-micro-districts into main 2026-06-13 06:02:30 +00:00
Collaborator

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 расширен: новый kwarg districts: list[str] | None = None. None → legacy crm.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

  • 5 новых юнит-тестов TestPriceSensitivityDistrictResolution: admin→micros в SQL bind, None→EKB-wide, regression preserved post-resolve, graceful на exception.
  • pytest tests/services/site_finder/test_market_metrics.py76 passed.
  • pytest -k "elasticity or sensitivity"156 passed, 1 skipped.
  • ruff check + psycopg v3 grep → clean.
  • Post-deploy: smoke на 'Кировский' → price_sensitivity_source='regression' (не 'fallback').

Closes #1211

## 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` расширен**: новый kwarg `districts: list[str] | None = None`. None → legacy `crm.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 - [x] 5 новых юнит-тестов `TestPriceSensitivityDistrictResolution`: admin→micros в SQL bind, None→EKB-wide, regression preserved post-resolve, graceful на exception. - [x] `pytest tests/services/site_finder/test_market_metrics.py` → **76 passed**. - [x] `pytest -k "elasticity or sensitivity"` → **156 passed, 1 skipped**. - [x] `ruff check` + psycopg v3 grep → clean. - [ ] Post-deploy: smoke на 'Кировский' → `price_sensitivity_source='regression'` (не `'fallback'`). Closes #1211
bot-backend added 1 commit 2026-06-13 05:52:47 +00:00
fix(market-metrics): resolve admin→micros for _price_sensitivity (#1211)
All checks were successful
CI / changes (push) Successful in 8s
CI / frontend-tests (push) Has been skipped
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (push) Successful in 6m35s
CI / backend-tests (pull_request) Successful in 6m38s
811800f2c6
_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
bot-backend merged commit 4c2f19ace0 into main 2026-06-13 06:02:30 +00:00
bot-backend deleted branch fix/price-sensitivity-micro-districts 2026-06-13 06:02:30 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1259
No description provided.