feat(tradein): #2043 BE-1 (cv/source_counts/created_at + history/cache-KPI) + #2044 BE-2 (radius_m query-params) #2140

Merged
lekss361 merged 2 commits from feat/tradein-v2-be1-be2-contract into main 2026-07-02 13:59:09 +00:00
Collaborator

Summary

Завершают data-contract нового UI /trade-in/v2. Additive, скраперы не тронуты — значения уже считаются, их надо просто отдать.

#2043 BE-1 — cv / source_counts / created_at + /history.sources_used + cache-KPI

  • AggregatedEstimate += cv (float|None), source_counts (dict[str,int]), created_at.
  • estimator: helpers _cv_from_ppm2 / _source_counts; cv прокинут через PricingResult — anchor-путь берёт CV комплов (anchor["cv"]), radius-путь — CV радиусной ₽/м²-выборки. source_counts по ПОЛНОЙ выборке (metadata_lots) до top-N отсечки.
  • POST /estimate возвращает все три; GET /estimate/{id} пересчитывает cv/source_counts из сохранённых analogs (best-effort) + created_at из колонки.
  • /history: += sources_used → разлочивает колонку «ИСТОЧНИКОВ N/7».
  • /cache-stats: += avg_median_price (по median_price>0) + repeat_address_pct (доля неуникальных адресов). Честный best-effort по persisted-оценкам.

#2044 BE-2 — optional radius_m

  • schema radius_m + estimate_quality уже в main (e23dabe4); здесь остаток: GET /estimate/{id}/house-analytics и /sell-time-sensitivity принимают radius_m (int|None) query-param. None → байт-идентичная авто-логика (300 м при <8 записях); задан → явный радиус, клампится [100,5000].

Test plan

  • ruff check app/ — clean
  • pytest — 2733 passed (1 pre-existing unrelated fail: test_search_api::test_search_cache_hit, падает и на base main)
  • new units: _cv_from_ppm2 / _source_counts / _price_from_inputs cv (radius+anchor) / radius_m bounds+None-preserves-default
  • прод-verify (реальная оценка 701795d8 / Белинского 86) — post-merge, главная сессия

Closes #2043
Closes #2044

## Summary Завершают data-contract нового UI `/trade-in/v2`. Additive, скраперы не тронуты — значения уже считаются, их надо просто отдать. ### #2043 BE-1 — cv / source_counts / created_at + /history.sources_used + cache-KPI - `AggregatedEstimate` += `cv` (float|None), `source_counts` (dict[str,int]), `created_at`. - estimator: helpers `_cv_from_ppm2` / `_source_counts`; `cv` прокинут через `PricingResult` — anchor-путь берёт CV комплов (`anchor["cv"]`), radius-путь — CV радиусной ₽/м²-выборки. `source_counts` по ПОЛНОЙ выборке (`metadata_lots`) до top-N отсечки. - `POST /estimate` возвращает все три; `GET /estimate/{id}` пересчитывает `cv`/`source_counts` из сохранённых analogs (best-effort) + `created_at` из колонки. - `/history`: += `sources_used` → разлочивает колонку «ИСТОЧНИКОВ N/7». - `/cache-stats`: += `avg_median_price` (по median_price>0) + `repeat_address_pct` (доля неуникальных адресов). Честный best-effort по persisted-оценкам. ### #2044 BE-2 — optional radius_m - schema `radius_m` + `estimate_quality` уже в main (`e23dabe4`); здесь остаток: `GET /estimate/{id}/house-analytics` и `/sell-time-sensitivity` принимают `radius_m` (int|None) query-param. None → байт-идентичная авто-логика (300 м при <8 записях); задан → явный радиус, клампится [100,5000]. ## Test plan - [x] `ruff check app/` — clean - [x] `pytest` — 2733 passed (1 pre-existing unrelated fail: `test_search_api::test_search_cache_hit`, падает и на base main) - [x] new units: `_cv_from_ppm2` / `_source_counts` / `_price_from_inputs` cv (radius+anchor) / `radius_m` bounds+None-preserves-default - [ ] прод-verify (реальная оценка `701795d8` / Белинского 86) — post-merge, главная сессия Closes #2043 Closes #2044
bot-backend added 2 commits 2026-07-02 13:52:17 +00:00
Данные уже считаются в estimator — отдаём наружу для /trade-in/v2 (снимает
approximate-флаги CV / счётчиков источников / даты отчёта / «ИСТОЧНИКОВ N/7»).

- AggregatedEstimate += cv (float|None), source_counts (dict[str,int]), created_at.
- estimator: _cv_from_ppm2 / _source_counts helpers. cv прокинут через
  PricingResult — anchor-путь берёт CV комплов (anchor["cv"]), radius-путь — CV
  радиусной ₽/м²-выборки. source_counts считается по ПОЛНОЙ выборке (metadata_lots)
  до top-N отсечки. created_at = момент создания.
- POST /estimate возвращает все три; GET /estimate/{id} пересчитывает cv/
  source_counts из сохранённых analogs (best-effort) + created_at из колонки.
- /history: += sources_used (jsonb) в проекции → колонка «ИСТОЧНИКОВ N/7».
- /cache-stats: += avg_median_price (по median_price>0) + repeat_address_pct
  (доля строк с неуникальным address). Честный best-effort по persisted-оценкам.

Refs #2043
feat(tradein/api): #2044 BE-2 — optional radius_m on house-analytics + sell-time-sensitivity
All checks were successful
CI / changes (pull_request) Successful in 11s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
3bf2c1a48a
radius_m (schema + estimate_quality comp-search) уже в main (e23dabe4). Здесь —
остаток: два derived-роута принимают radius_m как optional query-param.

- GET /estimate/{id}/house-analytics и /sell-time-sensitivity: += radius_m
  (int|None). None → байт-идентичная авто-логика (расширение до 300 м только при
  <8 in-house записей). Задан → явный радиус расширения выборки домов, клампится
  в [100,5000], возвращается в radius_m ответа.

Refs #2044
lekss361 merged commit 5f661bd0b7 into main 2026-07-02 13:59:09 +00:00
lekss361 deleted branch feat/tradein-v2-be1-be2-contract 2026-07-02 13:59:09 +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#2140
No description provided.