Fixes 500 on /trade-in/api/v1/geocode/reverse when Nominatim bans prod IP
after geocode_missing batch. Cadastral lookup via main backend new
endpoint /api/v1/cadastral/reverse is primary (37k buildings in ЕКБ,
<10ms, no external API). Nominatim is fallback wrapped in try/except
so HTTPStatusError no longer bubbles to FastAPI 500.
Architecture:
- main backend: new GET /api/v1/cadastral/reverse — cad_buildings nearest
within radius, filters out гаражи/СНТ. Added to gendesign_shared network
with alias gendesign-backend for cross-stack DNS.
- tradein backend: _cadastral_reverse() calls main backend, returns None
on any error. reverse_geocode prefers cadastral → falls back to
Nominatim → returns None (endpoint becomes 404 instead of 500).
Env: MAIN_BACKEND_URL=http://gendesign-backend:8000 in tradein prod.
Tests: 7 new cases covering cadastral/nominatim/fallback/error paths.
Обратный геокодинг (Nominatim /reverse) возвращал display_name,
который ведёт с названия ближайшей организации/POI — клик по
ЖК Малевич давал «NataliOlympic, 2к1, Трамвайный переулок…»
вместо адреса дома. Такой адрес не геокодировался обратно,
и оценка находила 0 аналогов.
Теперь reverse_geocode собирает адрес из Nominatim address-объекта
(улица + дом + город), display_name остаётся фолбэком. Follow-up к #415.
Кнопка справа от поля адреса → модалка с картой Екатеринбурга.
Клик по дому → reverse-геокодинг → адрес подставляется в форму.
- geocoder.reverse_geocode + GET /api/v1/geocode/reverse — Nominatim
/reverse (координаты → адрес).
- MapPicker.tsx — модалка с Leaflet + OSM-тайлами (Leaflet с CDN,
без npm-зависимости), circleMarker по клику.
- EstimateForm — кнопка-карта справа от AddressInput.
Карта на OSM (без API-ключа). При появлении ключа Yandex (#402)
можно перейти на Я.Карты.
Closes#415