gendesign/tradein-mvp/backend/app/services
Light1YT 74026ef1d9 feat(tradein): MapPicker snap marker на canonical building point (PR H, #582 Phase 5)
Backend /api/v1/geocode/reverse теперь возвращает snapped_lat/snapped_lon
центра matched здания (от Yandex Point.pos / Nominatim response.lat-lon /
cadastral row) + precision. Раньше endpoint echo'ил input lat/lon —
адрес resolved'ился до canonical «ул. Малышева, 125», но marker
оставался где кликнул user (часто в проезде / дворе).

Backend:
- reverse_geocode: str | None → ReverseGeocodeResult | None
  (address + snapped_lat/snapped_lon + precision + provider).
  Provider fallback Cadastral FDW → Yandex (если key) → Nominatim.
  Yandex /reverse дёргаем с kind=house чтобы сразу получить здание.
- /api/v1/geocode/reverse: новый Pydantic ReverseResponse model.
- snap_precision_useful() helper для frontend logic parity.
- Legacy _cadastral_reverse_sync сохранён для backward compat.

Frontend MapPicker:
- После reverse — если precision in (exact, number, cadastral) и
  snapped >5m от клика → marker.setLatLng + map.panTo с animate
- precision=street/range/locality → marker остаётся где кликнули
  (не врём что нашли точное здание).
- Hint «Точка дома по Яндексу» под address с aria-live="polite"
  (var(--fg-tertiary) — token compliance).
- haversineMeters helper для distance check (6371000m Earth radius).

Tests: 37 backend pass, ruff + tsc clean.
Code-reviewer LGTM, 1 nit applied inline (hex → var(--fg-tertiary)).

Closes #582 (Phase 5).
2026-05-27 14:29:51 +05:00
..
exporters feat(tradein): этаж/этажность optional + best test presets по deal count (#558) 2026-05-24 21:44:44 +00:00
matching fix(tradein-matching): pg_advisory_xact_lock to prevent duplicate house INSERTs (#501) 2026-05-24 10:52:10 +00:00
scrapers fix(tradein): yandex_realty captures house number + parse_rub strips NBSP (#593) 2026-05-27 07:23:36 +00:00
__init__.py feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in) 2026-05-21 00:25:39 +03:00
brand.py feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in) 2026-05-21 00:25:39 +03:00
cache.py feat(tradein): Phase 3.2 — /api/v1/search endpoint + Redis cache (#479) 2026-05-23 14:44:22 +00:00
cian_session.py fix(tradein): CIAN_REQUIRED_COOKIES — add real auth cookies (DMIR_AUTH + Cian session) (#480) 2026-05-23 14:52:24 +00:00
estimator.py feat(tradein): этаж/этажность optional + best test presets по deal count (#558) 2026-05-24 21:44:44 +00:00
geocoder.py feat(tradein): MapPicker snap marker на canonical building point (PR H, #582 Phase 5) 2026-05-27 14:29:51 +05:00
house_metadata.py feat(tradein): postgres_fdw live read of gendesign.cad_buildings (replaces snapshot) (#493) 2026-05-24 08:57:30 +00:00
image_sanitizer.py fix(tradein-photos): sanitize uploaded images via Pillow re-encode (#511) 2026-05-24 11:32:04 +00:00
scheduler.py feat(tradein): in-app scheduler — UI-managed schedule (replaces SSH crontab) (#482) 2026-05-23 14:54:25 +00:00
scrape_pipeline.py fix(tradein/avito): anti-bot hardening — sleep + abort + shared session (#487) 2026-05-23 20:08:40 +00:00
scrape_runs.py fix(tradein/avito): anti-bot hardening — sleep + abort + shared session (#487) 2026-05-23 20:08:40 +00:00
scraper_settings.py feat(tradein): global scraper delay setting (applies across all scrapers) (#485) 2026-05-23 15:43:28 +00:00
search_query.py feat(tradein): Phase 3.2 — /api/v1/search endpoint + Redis cache (#479) 2026-05-23 14:44:22 +00:00