Remove stale NOTE 2026-05-24 + add tier field на AnalogLot.
- schemas/trade_in.py: AnalogLot добавлено поле `tier: str | None`
('T0_per_house' / 'T1_per_street' — для rosreestr deals)
- services/estimator.py:
* _deal_to_analog: compute tier via kadastr_num heuristic
('66:41:0204016:10' → T0; '66:41:...:0' OR NULL → T1)
* estimate_quality docstring: replaced устаревший NOTE с corrected
explanation что importer (PR-A 2026-05-24) уже фильтрует doc_type='ДКП'
и deals идут в actual_deals output
* _fetch_deals SQL: include kadastr_num в SELECT (для tier classify)
Observation: open dataset Росреестра (current state) имеет
kadastr_num=NULL для всех 49,791 ДКП-сделок → все классифицируются
как T1_per_street. Поле зарезервировано на случай будущего ЕГРН
direct feed.
Tests: ruff clean, services/ pytest 19/19 pass.
Closes#564 Phase 3.
AggregatedEstimate не нёс параметры целевой квартиры (площадь, этаж,
комнаты, год, тип дома). HeroSummary брал их из формы-инпута — у
свежей оценки работало, но при открытии оценки по ссылке (?id=, из
Истории) формы нет → «Сводка» показывала «ЭТАЖ 0/0, Площадь 0 м²».
Параметры теперь проходят сквозь весь стек:
- AggregatedEstimate + TS-тип получили area_m2/rooms/floor/
total_floors/year_built/house_type/repair_state/has_balcony;
- estimate_quality заполняет их из payload, get_estimate — из строки
trade_in_estimates (колонки там уже есть);
- HeroSummary читает из estimate с откатом на input.
Заодно в TS-тип добавлен пропущенный est_days_on_market.
Доп. поля для трейд-ин менеджера: тип собственности, ипотека/
обременение, имя и телефон клиента. На расчёт оценки не влияют —
сохраняются в trade_in_estimates вместе с записью.
- data/sql/008_crm_fields.sql — 4 колонки в trade_in_estimates.
- TradeInEstimateInput + estimator INSERT — приём и сохранение.
- EstimateForm — секция «CRM — для менеджера» (4 поля).
Closes#395
Фото квартиры прикрепляются к оценке, хранятся в Postgres (bytea) —
без отдельного файлового тома, уезжают вместе с бэкапом БД.
- data/sql/007_estimate_photos.sql — таблица estimate_photos
(FK на trade_in_estimates, ON DELETE CASCADE).
- POST /estimate/{id}/photos — multipart-загрузка (image/*, ≤10 МБ,
≤12 фото на оценку).
- GET /estimate/{id}/photos — список метаданных.
- GET /estimate/{id}/photos/{photo_id} — отдать содержимое.
- python-multipart добавлен в зависимости (FastAPI UploadFile).
Фронтенд (file-drop в форме) — отдельным PR.