feat(tradein): estimator — Yandex Valuation as on-demand 6th source #473
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
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#473
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-estimator-yandex-integration"
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?
Motivation
Stage 8 of 9 for YandexRealtyScraper v1 (Wave 6). Adds Yandex Valuation tool (anonymous, no cookies — vs Cian Calculator's auth requirement) as on-demand enrichment source in
estimate_quality. Mirrors the proven Avito IMV pattern: 24h cache viaexternal_valuations, graceful degradation, idempotent history persistence.Changes —
estimator.py_yandex_valuation_cache_key(address, category, type)_get_or_fetch_yandex_valuation_cached(db, address, ...)external_valuations(source='yandex_valuation'). Any error →None+ log warning._save_yandex_history_items(db, result)house_placement_history(source='yandex_valuation')with synthesizedext_item_id(sha256 of address+date+area+floor+prices, first 32 chars). Idempotent via UNIQUE (source, ext_item_id).house_id=NULL— matching pipeline not wired into estimator yet.estimate_quality'yandex_valuation'tosources_usedon hit.Constants
Why "6th source", not "7th"
The vault plan called this "7th source" assuming Cian Valuation was already wired into estimator as #6. Inspection of current
estimator.pyshows only Avito IMV (5th) integrated — Cian Valuation lives in the scraper layer but isn't called fromestimate_qualityyet. So Yandex slots in as the 6th source currently active in the estimator. Plan numbering is aspirational; the integration order is what matters.Graceful degradation
_empty_estimate(Yandex block skipped — needsgeo.full_address)None, sources_used omitsyandex_valuationTests
Coverage: cache key determinism + uniqueness, TTL constant, cache hit/miss paths, fetch error/empty handling, history item save / dedup / per-item-error continuation.
Files
tradein-mvp/backend/app/services/estimator.pytradein-mvp/backend/tests/test_estimator_yandex_integration.pyReviewer note
Reviewer: deep-code-reviewer — only merge after APPROVE. After merge → Wave 7 (Stage 9 qa-tester post-deploy smoke).
Merged via deep-code-reviewer — verdict APPROVE.
Verified blast radius:
external_valuations (source, cache_key)UNIQUE —data/sql/026_external_valuations.sql:34✅house_placement_history (source, ext_item_id)UNIQUE —data/sql/017_house_placement_history.sql:50✅source='yandex_valuation'enum value documented —data/sql/032_yandex_history.sql:20✅Pattern fidelity vs Avito IMV:
CAST(:payload AS jsonb)/CAST(:raw AS jsonb)— psycopg v3 compliant ✅ON CONFLICT (source, ext_item_id) DO NOTHINGon history — idempotent ✅Cache key determinism:
SHA256(address|category|type)— deterministic, defaultsAPARTMENT/SELLalways passed by estimator caller (no None ambiguity, callsite line 537-539 doesn't pass kwargs).ext_item_id determinism:
SHA256(address|publish_date|area|floor|start_price|last_price)[:32]= 128 bits — collision-resistant. Stable across re-fetches (testtest_save_history_items_ext_id_stable_across_callsproves it).Follow-ups (non-blocking, separate PRs):
"Ленина 1"vs"ленина 1"→ different cache keys). Acceptable for v1 since geocoder produces canonicalgeo.full_address.match_or_create_house(PR #470) to backfillhouse_idinhouse_placement_historyrows. Currentlyhouse_id=NULL— confirmed schema allows NULL (017:22).estimate_qualityyet) — explicitly out-of-scope per PR description.asyncio.gatherif total estimate latency becomes UX concern.code/modules/tradein/Estimator_Yandex_Integration.mdfor worker to create.Verify steps post-deploy:
deploy-tradein.ymltriggers on merge to mainPOST /api/v1/trade-in/estimateдля ЕКБ адреса → responsesources_usedсодержитyandex_valuationSELECT count(*) FROM house_placement_history WHERE source='yandex_valuation'> 0SELECT count(*) FROM external_valuations WHERE source='yandex_valuation' AND expires_at > NOW()> 0yandex_valuation: cache HIT key=...)Wave 7 (Stage 9 qa-tester post-deploy smoke) unblocked.