fix(tradein-phase-c): prepend region prefix to addresses for IMV geocoder

Avito /coords/by_address mis-resolves ambiguous addresses to wrong regions.
Examples: 'улица Академика Королева, 8Г' -> Беларусь, Могилёв (404);
'р-н Орджоникидзевский, мкр. Уралмаш...' -> Хакасия (404).

Add _REGION_BBOX lookup (lat/lon -> region name) + _enrich_address_for_imv()
that prepends region prefix if address doesn't already have one. Default EKB
fallback when coords are NULL.
This commit is contained in:
lekss361 2026-05-24 18:27:02 +03:00
parent ba9cc3aef1
commit 57dd989e58

View file

@ -70,6 +70,46 @@ def _map_house_type(raw: str | None) -> str:
return _HOUSE_TYPE_DEFAULT
return _HOUSE_TYPE_TO_IMV.get(raw.lower().strip(), _HOUSE_TYPE_DEFAULT)
# Bounding boxes for known regions in our DB.
# When house.lat/lon falls inside one, we prepend the region name to address
# before sending to Avito (resolves ambiguity — e.g. "Орджоникидзевский район" exists
# in EKB AND in Khakasia republic).
_REGION_BBOX = [
# (region_name, lat_min, lat_max, lon_min, lon_max)
("Свердловская область, Екатеринбург", 56.5, 57.1, 59.9, 61.0),
("Свердловская область", 56.0, 61.0, 58.0, 65.0), # rest of region
("Кировская область, Киров", 58.4, 58.8, 49.4, 49.9),
("Ставропольский край, Ставрополь", 44.9, 45.2, 41.7, 42.2),
("Тюменская область, Тюмень", 57.0, 57.3, 65.3, 65.8),
("Челябинская область, Челябинск", 55.0, 55.4, 61.2, 61.7),
]
_REGION_DEFAULT = "Свердловская область, Екатеринбург" # bulk of our data is EKB
def _detect_region_prefix(lat: float | None, lon: float | None) -> str:
if lat is None or lon is None:
return _REGION_DEFAULT
for name, lat_min, lat_max, lon_min, lon_max in _REGION_BBOX:
if lat_min <= lat <= lat_max and lon_min <= lon <= lon_max:
return name
return _REGION_DEFAULT
def _enrich_address_for_imv(raw: str, lat: float | None, lon: float | None) -> str:
"""Prepend region prefix if address lacks one (ambiguity fix for Avito geocoder)."""
addr = (raw or "").strip()
# Already has region marker? skip
addr_lower = addr.lower()
if any(
m in addr_lower
for m in ("область,", " обл.,", " обл,", "край,", "респ.,", "республика,")
):
return addr
prefix = _detect_region_prefix(lat, lon)
return f"{prefix}, {addr}"
DATABASE_URL = os.environ.get("DATABASE_URL")
if not DATABASE_URL:
raise SystemExit(
@ -317,8 +357,14 @@ async def process_one(db: Session, house: dict) -> str:
mark_status(db, house["id"], "no_address", "house.address is NULL")
return "no_address"
# Enrich with region prefix to prevent Avito geocoder mis-resolving ambiguous
# street names to wrong regions (e.g. "улица Победы" exists in EKB and Khakasia).
enriched = _enrich_address_for_imv(address, house.get("lat"), house.get("lon"))
if enriched != address:
logger.debug("enriched address house=%d %r -> %r", house["id"], address, enriched)
try:
result = await evaluate_via_imv(address=address, **params)
result = await evaluate_via_imv(address=enriched, **params)
except IMVAddressNotFoundError as e:
mark_status(db, house["id"], "not_found", str(e)[:200])
return "not_found"