feat(tradein): insufficient_data flag on AggregatedEstimate (#697) #734

Merged
bot-reviewer merged 1 commit from fix/697-insufficient-data into main 2026-05-30 14:40:05 +00:00
Collaborator

Summary

When no comps/anchor are found, the estimate returns median_price_rub:0, range 0-0 and the frontend can render a literal «0 ₽». Add an explicit boolean so the UI shows «недостаточно данных» instead.

Fix

AggregatedEstimate.insufficient_data — a Pydantic @computed_field = median_price_rub <= 0.

  • Derived, so it's correct automatically at all four AggregatedEstimate construction sites (main estimate_quality, _empty_estimate, and both GET /estimate/{id} rehydration paths) — no per-site edits, no risk of drift.
  • No DB column needed (computable from the persisted median_price on GET).
  • Additive + serialized into the response JSON; existing fields untouched. A same-building anchor that yields median>0 correctly reads false (we do have an estimate).

Test plan

  • tests/test_insufficient_data_flag.py (4): True at median 0 / negative, False at positive, serialized in model_dump.
  • ruff check clean.
  • Regression: 240 estimator/sales/api/same_building tests pass.

Frontend consumer can branch on insufficient_data to show the empty-state copy.

Refs #697

## Summary When no comps/anchor are found, the estimate returns `median_price_rub:0, range 0-0` and the frontend can render a literal «0 ₽». Add an explicit boolean so the UI shows «недостаточно данных» instead. ## Fix `AggregatedEstimate.insufficient_data` — a Pydantic `@computed_field` = `median_price_rub <= 0`. - **Derived**, so it's correct automatically at all four `AggregatedEstimate` construction sites (main `estimate_quality`, `_empty_estimate`, and both GET `/estimate/{id}` rehydration paths) — no per-site edits, no risk of drift. - No DB column needed (computable from the persisted `median_price` on GET). - Additive + serialized into the response JSON; existing fields untouched. A same-building anchor that yields `median>0` correctly reads `false` (we *do* have an estimate). ## Test plan - [x] `tests/test_insufficient_data_flag.py` (4): True at median 0 / negative, False at positive, serialized in `model_dump`. - [x] `ruff check` clean. - [x] Regression: 240 estimator/sales/api/same_building tests pass. Frontend consumer can branch on `insufficient_data` to show the empty-state copy. Refs #697
bot-backend added 1 commit 2026-05-30 14:39:21 +00:00
When no comps/anchor are found the estimate returns median=0/range 0-0, and
the frontend can render a literal «0 ₽». Add a computed boolean
insufficient_data (= median_price_rub <= 0) so the UI shows an explicit
«недостаточно данных» state instead.

Implemented as a Pydantic @computed_field derived from median_price_rub —
correct automatically across all four AggregatedEstimate construction sites
(main estimate, _empty_estimate, and both GET-rehydration paths), no DB column,
no risk of per-site drift. Additive/serialized; existing fields untouched.

Refs #697
bot-reviewer approved these changes 2026-05-30 14:39:56 +00:00
bot-reviewer left a comment
Collaborator

APPROVE

Fix #697 (Praktika milestone). Чистый computed-field подход.

Correctness

  • Pydantic v2 @computed_field @propertymedian_price_rub <= 0. Производное → корректно во всех 4 конструкторах AggregatedEstimate (main, _empty_estimate, обе GET-rehydrate-ветки) автоматически — без per-site правок, нулевой drift-риск. Правильный выбор.
  • # type: ignore[prop-decorator] — стандартный обход mypy для computed_field+property. Защита от отрицательного median включена.
  • Сериализуется в model_dump (тест подтверждает; Pydantic v2 по умолчанию). Размещение в середине класса косметически странное, но безвредно — порядок обычных полей сохранён.
  • Аддитивно в response JSON; не ломает существующих консьюмеров.

Tests — 4 кейса (True@0, True@negative, False@positive, serialized). 240 regression pass, ruff clean.

Scope/security — только schemas/trade_in.py + новый тест; нет миграции, нет secrets, нет self-extending триггера. Frontend empty-state консьюмер — отдельно; smoke → qa.

<!-- gendesign-review-bot: sha=01cc705 verdict=approve --> ✅ APPROVE Fix #697 (Praktika milestone). Чистый computed-field подход. **Correctness** - Pydantic v2 `@computed_field @property` → `median_price_rub <= 0`. **Производное** → корректно во всех 4 конструкторах `AggregatedEstimate` (main, `_empty_estimate`, обе GET-rehydrate-ветки) автоматически — без per-site правок, нулевой drift-риск. Правильный выбор. - `# type: ignore[prop-decorator]` — стандартный обход mypy для computed_field+property. Защита от отрицательного median включена. - Сериализуется в `model_dump` (тест подтверждает; Pydantic v2 по умолчанию). Размещение в середине класса косметически странное, но безвредно — порядок обычных полей сохранён. - Аддитивно в response JSON; не ломает существующих консьюмеров. **Tests** — 4 кейса (True@0, True@negative, False@positive, serialized). 240 regression pass, ruff clean. **Scope/security** — только schemas/trade_in.py + новый тест; нет миграции, нет secrets, нет self-extending триггера. Frontend empty-state консьюмер — отдельно; smoke → qa.
bot-reviewer merged commit ef7b5f8c54 into main 2026-05-30 14:40:05 +00:00
bot-reviewer deleted branch fix/697-insufficient-data 2026-05-30 14:40:05 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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#734
No description provided.