d688d24a12
fix(tradein): sync n_analogs to anchor count when anchor drives headline ( #695 )
...
QA-fail after #738 : that PR de-contradicted the explanation STRING, but
n_analogs stayed = radius count (listings_clean) while the same-building anchor
(#691/#694) replaced the headline + analogs list with the house comps. So every
UI counter («Аналогов N», «Показано N из M», «по N аналогам», histogram) still
read the radius number — producing «Показано 5 из 4» on the Олимп penthouse
(radius=4, anchor=5). #738 's Малышева case passed only because radius==anchor
(14=14) — mimicry, not a fix.
Fix: when anchor_tier is not None, set n_analogs = anchor['n'] (the comp count
the estimate is actually built on, = the displayed analogs capped at 10). All
counters now agree. Per #698 , for the anchor path that IS the «full count found».
Radius path unchanged.
Refs #695
2026-05-30 18:23:30 +03:00
2b3eb0b23d
fix(tradein): confidence_explanation no longer contradicts counters ( #695 ) ( #738 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / deploy (push) Successful in 33s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 15:10:31 +00:00
066fab11d3
fix(tradein): sanitize ДКП deal outliers (floor / ppm²) ( #699 ) ( #733 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / deploy (push) Successful in 40s
Deploy Trade-In / build-backend (push) Successful in 40s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 14:31:44 +00:00
a79cf7d5e0
fix(tradein): coarse-geo downgrade no longer shielded by Tier C anchor ( #693 ) ( #720 )
...
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / deploy (push) Successful in 33s
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 12:34:11 +00:00
0e2bba78b7
fix(tradein): coarse-geo downgrade works without DaData on prod ( #693 ) ( #718 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 24s
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 34s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 12:08:56 +00:00
961a3caf2b
fix(tradein): surface same-building comps as analogs when anchor fires ( #694 ) ( #708 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Failing after 24s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 09:21:20 +00:00
9d94beae4f
fix(tradein): flag coarse-geo estimates as low-confidence ( #693 ) ( #707 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Failing after 23s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 08:58:23 +00:00
f04728297b
fix(tradein): run same-building anchor without radius analogs ( #691 ) ( #704 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / test (push) Successful in 22s
Deploy Trade-In / deploy (push) Successful in 34s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 08:34:24 +00:00
705eebfca3
feat(tradein): enrich /estimate response for web map, distribution, exposure & trend ( #685 )
...
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 23s
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 32s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 07:32:40 +00:00
6fac54642a
fix(tradein): distinct asking median vs expected-sold price (no double-discount) ( #682 )
...
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 22s
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Successful in 32s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 06:35:46 +00:00
3361e434d4
feat(tradein): refine same-building anchor for within-building heterogeneity ( #681 )
...
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 22s
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 33s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 05:49:46 +00:00
351ec88104
fix(tradein): feed raw payload.address to same-building anchor (geocode-independent) ( #680 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 22s
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 32s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-29 23:17:09 +00:00
b5c26d2723
fix(tradein): harden same-building anchor address normalizer for prod formats ( #677 ) ( #679 )
...
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 22s
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 33s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-29 22:21:29 +00:00
03a3296332
feat(tradein): same-building anchor estimator (#651/#652 v2) behind flag ( #677 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Failing after 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-29 21:01:21 +00:00
96f02d37f3
feat(tradein): blend Avito IMV anchor into estimate + ДКП corridor advisory ( #651 , #652 ) ( #674 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 46s
Deploy Trade-In / build-frontend (push) Successful in 1m38s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-29 17:42:06 +00:00
29679a9545
fix(tradein): time-budget estimate enrichment + observable errors to stop opaque 502 ( #654 ) ( #673 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 34s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-29 17:22:02 +00:00
47fdd6e4df
fix(tradein): scope GET /history to caller, close cross-pilot data leak ( #656 ) ( #670 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / deploy (push) Successful in 59s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-29 15:59:03 +00:00
35bd0238ef
feat(tradein): estimator additive expected_sold price ( #648 S3) ( #661 )
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / deploy (push) Successful in 34s
2026-05-29 13:37:33 +00:00
e4b5f14939
test(tradein): estimator pure-helper unit tests + fix None crash in _filter_outliers ( #580 ) ( #640 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 48s
Deploy Trade-In / deploy (push) Successful in 33s
2026-05-29 08:24:18 +00:00
d842811390
refactor(tradein): normalize repair_state raw→enum at ingest ( #621 ) ( #629 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 49s
Deploy Trade-In / deploy (push) Successful in 36s
2026-05-28 15:18:11 +00:00
33ee00c065
feat(tradein): калибровка repair-коэффициентов с base 1.0 ( #7 )
...
_REPAIR_COEF → tunable market-эвристика: needs_repair=0.94, standard=1.00
(baseline no-op; было 0.98 — срезало 2% с каждой standard-оценки), good=1.05,
excellent=1.10. Деривация из данных отклонена: listings.repair_state покрытие
~2%, сырые un-normalized значения, медианы confounded площадью (issue #7 ).
+ regression-тест (читает _REPAIR_COEF динамически — переживёт рекалибровку):
ratio excellent/needs_repair, standard/None no-op, наличие/отсутствие note.
Поправлен mislabeled comment над _IMV_HOUSE_TYPE_MAP. _IMV_REPAIR_MAP не тронут.
code-reviewer: ✅ APPROVE no critical/minor. Tests: 5 new + 7 cian-integration.
Ruff clean.
Closes #7
2026-05-28 16:15:54 +05:00
492dd0aba6
feat(tradein): бейдж точности адреса (qc_geo) на карточке оценки (accuracy #1 )
...
Честность к пользователю: показываем насколько точно определён адрес —
«до дома» / «до улицы» / «приблизительно» — рядом с confidence.
- schemas/trade_in.py: address_precision: Literal["house","street","approximate"]|None
- estimator.py: _qc_geo_to_precision (qc_geo 0→house, 1→street, ≥2→approximate,
None→None), set в основном return + _empty_estimate
- api/v1/trade_in.py: get_estimate + estimate_pdf теперь rehydrate'ят DaData-поля
(canonical_address, house_cadnum, house_fias_id, address_precision, metro_nearest)
из row — раньше на ?id= reopen / в PDF вся Q1-обогащёнка пропадала (поймал
code-reviewer). Колонки уже persisted, фикс read-path.
- frontend: AddressPrecision type + precision-badge в HeroSummary (.card-meta),
токены --success/--accent-2/--bg-card-alt, без новых токенов.
Канон: tech-analyst (план) → backend-engineer + frontend-engineer → code-reviewer
(✅ APPROVE, поймал reopen-path gap) → fold-in fix. Tests: 7 passed, tsc clean, ruff clean.
match_house_readonly wiring отложен (fast-follow).
2026-05-28 15:37:33 +05:00
30a80ee608
feat(tradein): same-building матчинг аналогов по house_id ( #6 )
...
Estimator теперь резолвит target-адрес в КАНОНИЧЕСКИЙ house_id (read-only,
без создания записи) и матчит аналоги по listings.house_id_fk — детерминированный
Tier S «тот же дом» вместо хрупкого address-string prefix match. 99% листингов
слинкованы с houses, поэтому это срабатывает уже сегодня и точнее работает между
разнородными источниками (Avito/Cian/Yandex форматируют адрес по-разному).
- matching/houses.py: match_house_readonly() — read-only target→house резолвер
(cadastr_exact → fingerprint → geo_proximity 50m), без INSERT / house_sources /
advisory lock. Возвращает None если уверенного match нет.
- estimator.estimate_quality: после geocode+DaData резолвит target_house_id
(cadastr от DaData → cadastr_exact заработает по мере backfill houses), graceful.
- estimator._fetch_analogs: новый param target_house_id + канонический Tier S
(WHERE house_id_fk = target) ПЕРЕД address-prefix Tier S (теперь fallback).
tier label 'S' сохранён (frontend уже рендерит).
Эффект: вместо «похожие в радиусе 800-1000м» — «вот что в ЭТОМ доме», прямой
выигрыш в точности оценки. Foundation под cadastr/FIAS exact match (DaData Q1/Q3).
Tests: 9 новых (match_house_readonly tiers + never-inserts + canonical Tier S
fires/fallback/too-few). Ruff clean. Pre-existing 4 fail в test_estimator_source_quota
(unpack 2≠3, красные на main до этого PR) — не затронуты.
2026-05-28 13:55:51 +05:00
a7fa1a4ffa
feat(tradein): DaData on-demand enrichment в estimate flow (PR Q1)
...
Добавляет app/services/dadata.py — async client для DaData /clean/address,
обогащающий target адрес canonical-формой, kadastr_num, ФИАС, координатами
и ближайшим метро. Migration 069 расширяет trade_in_estimates 6 nullable
колонками; estimator.estimate_quality вызывает service после geocode и
сохраняет результат в основной INSERT. AggregatedEstimate отдаёт
canonical_address / house_cadnum / house_fias_id / metro_nearest наружу.
Service graceful: пустые credentials / quota 429 / 5xx / network fail → None,
estimator продолжает работу. Demo tier 100 req/день — хватит для low-traffic
prod и тестов. ENV: DADATA_API_TOKEN, DADATA_API_SECRET.
Tests: 20 unit-тестов через httpx.MockTransport, zero real DaData calls.
Покрыто: happy path, отсутствие creds, короткий адрес, timeout/network,
HTTP 429/401/403/500/502/503, пустой массив, malformed shape, partial
payload, coerce строковых qc-кодов в int, проверка request body+headers.
Закладывает базу для PR Q2 (frontend DaData Suggest, 10k/день free) и
PR Q3 (backfill 339 NULL-coords houses) — обе используют тот же сервис.
2026-05-27 18:50:12 +05:00
64e0d6f4e7
feat(tradein): estimator deals tier (PR M, #564 Phase 3) ( #600 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 47s
Deploy Trade-In / deploy (push) Successful in 34s
2026-05-27 12:40:09 +00:00
33c4c84467
feat(tradein): этаж/этажность optional + best test presets по deal count ( #558 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 44s
Deploy Trade-In / build-frontend (push) Successful in 1m53s
Deploy Trade-In / deploy (push) Successful in 44s
2026-05-24 21:44:44 +00:00
8c540ecec6
fix(tradein): extract_street_name handles Nominatim reverse format ( #557 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 38s
2026-05-24 21:03:42 +00:00
a63e459e25
feat(tradein): GET /street-deals — ДКП-сделки Росреестра по улице target адреса ( #555 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / deploy (push) Successful in 36s
2026-05-24 20:05:48 +00:00
596842df8d
fix(tradein): filter ДКП-only in rosreestr importer + re-enable deals ( #549 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 54s
Deploy Trade-In / build-frontend (push) Successful in 1m46s
Deploy Trade-In / deploy (push) Has been cancelled
2026-05-24 19:42:28 +00:00
08cf615ad7
feat(tradein/cian): surface valuation chart + rent + change-pct on /trade-in ( #530 )
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 48s
Deploy Trade-In / build-frontend (push) Has been cancelled
2026-05-24 14:32:54 +00:00
c8675ce6e2
feat(yandex-valuation): link history rows to houses via match_or_create_house ( #531 )
Deploy Trade-In / deploy (push) Successful in 36s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 44s
2026-05-24 14:28:30 +00:00
c6ab419100
feat(tradein-sql): bootstrap houses + link 98.8% of listings (Phase A+B) ( #527 )
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 37s
2026-05-24 14:17:32 +00:00
45ee0a2945
fix(tradein-estimator): extend cohort filter to Tier S + Tier H, fix late_soviet overlap ( #522 )
Deploy Trade-In / changes (push) Successful in 7s
Deploy Trade-In / deploy (push) Successful in 33s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
2026-05-24 13:14:59 +00:00
7cc7fafeeb
feat(tradein-estimator): cohort filter + Tier 0 for analog selection quality ( #519 )
Deploy Trade-In / deploy (push) Successful in 32s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 40s
2026-05-24 13:04:58 +00:00
a0d50bd282
feat(tradein-estimator): tiered house-match S→H→W ( #507 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 32s
Deploy Trade-In / build-backend (push) Successful in 38s
2026-05-24 12:41:12 +00:00
6cda0cf8d3
fix(tradein-estimator): restore CAST in IS NOT NULL predicates (revert audit #9 , prod fix) ( #518 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 41s
Deploy Trade-In / deploy (push) Successful in 31s
2026-05-24 12:35:28 +00:00
9402702f32
feat(tradein-estimator): unique-address-based confidence threshold ( #513 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 31s
2026-05-24 11:52:00 +00:00
7d8c22ff39
fix(tradein-estimator): atomic IMV link, batched yandex history, drop redundant CAST ( #509 )
Deploy Trade-In / deploy (push) Successful in 32s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 39s
2026-05-24 11:18:12 +00:00
7f23a9b3f1
feat(tradein-imv): retry with cleaned address + categorize errors ( #505 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 38s
2026-05-24 11:04:24 +00:00
6bfa686f16
feat(tradein-estimator): exclude rosreestr deals from output ( #504 )
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 38s
Deploy Trade-In / deploy (push) Successful in 36s
2026-05-24 10:52:55 +00:00
7874a5c97b
feat(tradein): source-quota in estimator analogs (fix Cian/Yandex starvation) ( #491 )
Deploy Trade-In / build-backend (push) Successful in 51s
Deploy Trade-In / deploy (push) Failing after 10m2s
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
2026-05-23 20:59:58 +00:00
52716a46c6
fix(tradein): geocode backfill + remove Avito exclusion from estimator ( #490 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / deploy (push) Successful in 24s
2026-05-23 20:03:48 +00:00
37c4574d0a
feat(tradein): estimator — Cian Valuation as on-demand 7th source (Stage 9) ( #476 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 40s
Deploy Trade-In / deploy (push) Successful in 21s
2026-05-23 14:29:52 +00:00
b26e0ff7c3
feat(tradein): estimator — Yandex Valuation as on-demand 6th source ( #473 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Successful in 21s
Stage 8 of YandexRealtyScraper v1. Adds Yandex Valuation (anonymous, no cookies) as 6th on-demand source in estimate_quality. Mirrors Avito IMV pattern: 24h cache via external_valuations(source='yandex_valuation', cache_key) [UNIQUE 026:34], idempotent history persistence via house_placement_history(source, ext_item_id) [UNIQUE 017:50] with synthesized SHA256(address|date|area|floor|prices)[:32] ext_item_id. Graceful degradation on geocode/fetch/cache/save errors. house_id=NULL — matching deferred to Stage 8.x. 11 new tests + 4 IMV regression = 15 green.
2026-05-23 14:14:49 +00:00
5051ebde2e
feat(tradein): integrate Avito IMV as 5th evaluation source (on-demand cached) ( #452 )
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Successful in 20s
2026-05-23 13:08:22 +00:00
5e3ba351a0
fix(tradein): security hotfix — C-3 config default + C-4 empty estimate persist + C-6 PDF URL allowlist ( #435 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 38s
Deploy Trade-In / deploy (push) Successful in 25s
2026-05-23 09:38:23 +00:00
9b2a54788b
fix(tradein): восстановленная оценка показывает этаж/площадь, не 0/0
...
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.
2026-05-22 15:50:19 +05:00
8bef0fd872
fix(tradein): оценка исключает Avito из радиусного поиска аналогов
...
У Avito-объявлений «координаты» = якорь cron-скрейпа ± jitter (DOM
Avito реальных coords не отдаёт). Фейковые точки кучкуются плотными
кластерами на 5 якорях ЕКБ — tier-1 радиус (1 км) набирался почти
целиком из них: оценка для центра давала sources_used=['avito'],
18 аналогов все Avito, при 1400 живых cian/yandex/n1 в БД.
_fetch_analogs теперь исключает source='avito'. Трёхтирный fallback
по радиусу доходит до реальных cian/yandex/n1 с настоящей геопривязкой
— оценка считается по корректным аналогам.
2026-05-22 14:26:29 +05:00
TradeIn Deploy
48ccbdafc8
feat(tradein): CRM-поля в форме оценки ( #395 )
...
Доп. поля для трейд-ин менеджера: тип собственности, ипотека/
обременение, имя и телефон клиента. На расчёт оценки не влияют —
сохраняются в trade_in_estimates вместе с записью.
- data/sql/008_crm_fields.sql — 4 колонки в trade_in_estimates.
- TradeInEstimateInput + estimator INSERT — приём и сохранение.
- EstimateForm — секция «CRM — для менеджера» (4 поля).
Closes #395
2026-05-22 11:15:15 +05:00
TradeIn Deploy
bf2886509d
feat(tradein): обогащение house_metadata через OSM Overpass ( #392 )
...
Когда пользователь не указал год постройки / тип дома, estimator
подтягивает их из OpenStreetMap (Overpass API) — building:levels,
start_date, building:material. Улучшает house-match аналогов (#6 ).
- app/services/house_metadata.py — Overpass-провайдер + кэш в таблице
house_metadata (TTL 30 дней, lookup по близости координат, 40 м).
- estimator.estimate_quality — обогащает target_year / target_house_type
перед _fetch_analogs. Best-effort: ошибка OSM → оценка без обогащения.
OSM по ЕКБ: building:levels населён хорошо, год постройки — частично.
Closes #392
2026-05-22 10:39:56 +05:00