diff --git a/tradein-mvp/backend/app/services/geocoder.py b/tradein-mvp/backend/app/services/geocoder.py index 8cd5d357..d5f0e146 100644 --- a/tradein-mvp/backend/app/services/geocoder.py +++ b/tradein-mvp/backend/app/services/geocoder.py @@ -536,11 +536,46 @@ async def geocode(address: str, db: Session) -> GeocodeResult | None: # ── Reverse: координаты → адрес (для map-picker'а) ────────────────────────── +def _format_reverse_address(addr: dict) -> str | None: + """Собирает чистый уличный адрес из Nominatim address-объекта. + + Nominatim `display_name` ведёт с названия ближайшего POI/организации + («NataliOlympic, 2к1, Трамвайный переулок, …»). Для map-picker'а это + ломает кейс: такой адрес нельзя forward-геокодировать обратно и оценка + не находит аналогов. Берём именно улицу + дом + город. + + Возвращает None если в объекте нет улицы — тогда вызывающий код + откатывается на display_name. + """ + road = ( + addr.get("road") + or addr.get("pedestrian") + or addr.get("footway") + ) + if not road: + return None + house = addr.get("house_number") + city = ( + addr.get("city") + or addr.get("town") + or addr.get("village") + or addr.get("municipality") + ) + parts: list[str] = [str(road)] + if house: + parts.append(str(house)) + if city: + parts.append(str(city)) + return ", ".join(parts) + + @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=8)) async def reverse_geocode(lat: float, lon: float) -> str | None: """Обратный геокодинг: координаты → адрес (Nominatim /reverse). Клик по дому на карте ЕКБ → адрес подставляется в форму оценки. + Возвращаем уличный адрес (улица, дом, город), а не `display_name` — + тот начинается с названия POI/организации и не геокодируется обратно. """ headers = { "User-Agent": f"TradeInMVP/0.1 (contact: {settings.contact_email})", @@ -562,4 +597,9 @@ async def reverse_geocode(lat: float, lon: float) -> str | None: data = response.json() if not isinstance(data, dict) or "error" in data: return None + addr = data.get("address") + if isinstance(addr, dict): + street = _format_reverse_address(addr) + if street: + return street return data.get("display_name")