fix(tradein/estimate): оживлять мёртвые сохранённые оценки при открытии #2826

Merged
lekss361 merged 1 commit from fix/tradein-revive-dead-estimates into main 2026-08-11 04:15:41 +00:00

1 commit

Author SHA1 Message Date
bot-backend
3e809321e9 fix(tradein/estimate): оживлять мёртвые сохранённые оценки при открытии
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Successful in 4m31s
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
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
CI Trade-In / frontend-checks (pull_request) Successful in 1m20s
Заказчик прислал в поддержку ссылку на сохранённую оценку и увидел
«НЕДОСТАТОЧНО ДАННЫХ». Запись создана до фиксов #2823/#2825 и лежит в БД
мёртвой (median_price=0) со старым текстом объяснения, хотя новый расчёт
по тем же входным данным даёт 4 031 157 ₽. Таких строк 117 из 1071.

- GET оценки: если строка мертва (median_price <= 0/NULL) — пересчёт из
  сохранённых входных данных с записью результата в ТУ ЖЕ строку, id и
  ссылка не меняются. Строку с реальной ценой не трогаем никогда — это
  сохранённый документ клиента.
- Защита от шторма и гонки: атомарный UPDATE с проверкой «всё ещё мертва»
  и «давно не пробовали» прямо в БД (revival_attempted_at, окно 10 мин),
  без TOCTOU между параллельными GET. Временная строка, которую создаёт
  estimate_quality, удаляется, avito_imv_evaluations перепривязан до
  удаления — иначе каскад снёс бы только что записанный кэш.
- Любая ошибка пересчёта → отдаём сохранённую строку и logger.exception,
  GET не падает.
- relaxations / reliability теперь персистятся (миграция 255_*, idempotent)
  — раньше при возврате к сохранённой оценке пропадал красный дисклеймер,
  хотя цена построена на расширенной выборке. PDF читает их так же.
- Радиус в UI: добавлены 3000 и 5000 м (бэкенд принимал до 5000) плюс
  подсказка, что «Авто» расширяет поиск, а явный радиус ограничивает —
  заказчик выбрал «мах 2000», тем самым отрезав шаги каскада на 3 и 5 км.
2026-08-11 07:08:25 +03:00