fix(tradein/estimate): отдавать фактический радиус подбора, а не выбор пользователя #2835
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
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#2835
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2632-actual-radius"
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?
Постановка подтвердилась ЧАСТИЧНО
Пункты 1-3 исходного #2632 закрыты в #2643:
search_radius_mв схеме, круг v2 по нему, disclosure. Но на СОХРАНЁННОЙ оценке поле пустое — колонки под него нет,GET /estimate/{id}его не восстанавливал. Фронт падал на превью-радиус 1 км, то есть исходный дефект («картинка убедительнее текста») жив ровно там, где по оценке ходят чаще всего: shared-link,?id=, перезагрузка страницы.Живой прод, 2026-08-11, оценка
4c20518f(Советская 51), запрос изнутри контейнера:Три утверждения об одном радиусе на одном экране: круг 1 км, подпись 5 км, текст 2 км.
Замер расхождения (прод,
tradein_estimates)Изменения
DEFAULT_RADIUS_M. Нет расстояний → остаётсяnull(фронт падает на выбор пользователя, как раньше). Миграция не нужна. Приём не новый: v2SourcesMapуже рисует круг поmax(distance_m).radius_relaxation_label/radius_from_relaxations), иначе строка и парсер разъедутся.confidence_explanationназывает фактический радиус. Было прибито «расширили радиус до 2 км» — константа старого 1км→2км fallback'а, хотя каскад #oblast-F уходит до 3/5 км. Метка называла вход, а не результат — тот же дефект, что чинили в #2811.requested_radius_m(с чего начали) рядом сsearch_radius_m(чем кончили). На GETrequested_radius_mостаётсяnull:radius_mне персистится, и подставить дефолт значило бы выдать догадку за выбор пользователя.Фронт не трогал — v2 уже читает
search_radius_mи рисует круг по нему, микрокопия причины уже есть: «Аналогов в радиусе 1 км не хватило — поиск расширен до 5 км». Правка бэкенда оживляет её на реоткрытой оценке.Test plan
tests/test_estimator_search_radius_2632.py(9 тестов) — красный на origin/main:AssertionError: объяснение называет не тот радиус: '... (расширили радиус до 2 км из-за нехватки данных).'AssertionError: сохранённая оценка отдала search_radius_m=None, а relaxations говорят ['радиус расширен до 5000 м'], самый дальний аналог 4381 мruff check+ruff-format(pre-commit, pinned v0.7.4) — чистоИзвестные границы (не в этом PR)
radius_mне персистится). Расширения там нет по контракту #2044, но круг рисуется по превью 1 км. Нужна колонка → отдельная задача для database-expert.MapCard.tsx:139рисует круг с жёстко зашитымradius: 2000. Однострочная правка наestimate.search_radius_m ?? 2000— оставил frontend-engineer.Refs #2632
Сохранённая оценка отдавала search_radius_m=null, и карта рисовала круг по превью-радиусу 1 км. Прод 2026-08-11 (оценка 4c20518f, Советская 51): relaxations = ["радиус расширен до 5000 м"], все 10 показанных аналогов вне круга, самый дальний — 4381 м. По всей базе: у 62 из 388 оценок с расстояниями (16%) есть аналог дальше километра, p90 максимума 1572 м, максимум 4381 м. - GET /estimate/{id} восстанавливает фактический радиус из того, что реально персистится: подпись каскада «радиус расширен до N м» (точное значение, то же, что вернул POST), иначе — размах сохранённых аналогов, но не ниже DEFAULT_RADIUS_M. Нет расстояний — остаётся null, фронт падает на выбор пользователя, как раньше. Колонки/миграции не требуется. - Подпись каскада и её разбор — один helper (radius_relaxation_label / radius_from_relaxations), иначе строка и парсер разъедутся. - confidence_explanation называет ФАКТИЧЕСКИЙ радиус: было прибито «расширили радиус до 2 км» (константа старого 1км→2км fallback'а) даже когда каскад #oblast-F уходил до 5 км — метка называла не результат (ср. #2811). - Ответ несёт обе величины: requested_radius_m (с чего начали) рядом с search_radius_m (чем кончили). На GET requested_radius_m остаётся null — radius_m не персистится, подставлять дефолт значило бы выдать догадку за выбор пользователя. Refs #2632