117 lines
4.9 KiB
Python
117 lines
4.9 KiB
Python
# /opt/docker/dev/service_finder/backend/app/services/geo_service.py
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import text, select
|
|
from typing import Optional, List
|
|
import uuid
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class GeoService:
|
|
@staticmethod
|
|
async def get_street_suggestions(db: AsyncSession, zip_code: str, q: str) -> List[str]:
|
|
"""
|
|
Azonnali utca-kiegészítés (Autocomplete) támogatása.
|
|
Kizárólag az adott irányítószámhoz már rögzített utcákat keresi.
|
|
"""
|
|
query = text("""
|
|
SELECT DISTINCT s.name
|
|
FROM data.geo_streets s
|
|
JOIN data.geo_postal_codes p ON s.postal_code_id = p.id
|
|
WHERE p.zip_code = :zip AND s.name ILIKE :q
|
|
ORDER BY s.name ASC LIMIT 10
|
|
""")
|
|
try:
|
|
res = await db.execute(query, {"zip": zip_code, "q": f"{q}%"})
|
|
return [row[0] for row in res.fetchall()]
|
|
except Exception as e:
|
|
logger.error(f"Street Suggestion Error: {e}")
|
|
return []
|
|
|
|
@staticmethod
|
|
async def get_or_create_full_address(
|
|
db: AsyncSession,
|
|
zip_code: str,
|
|
city: str,
|
|
street_name: str,
|
|
street_type: str,
|
|
house_number: str,
|
|
stairwell: Optional[str] = None,
|
|
floor: Optional[str] = None,
|
|
door: Optional[str] = None,
|
|
parcel_id: Optional[str] = None
|
|
) -> uuid.UUID:
|
|
"""
|
|
Hibrid címrögzítés: ellenőrzi a szótárakat és létrehozza a központi címet.
|
|
Az atomizált mezők (lépcsőház, emelet, ajtó) kezelése Master Book 2.0 szerint.
|
|
"""
|
|
try:
|
|
# 1. 📬 Irányítószám és Város (Auto-learning)
|
|
zip_id_query = text("""
|
|
INSERT INTO data.geo_postal_codes (zip_code, city, country_code)
|
|
VALUES (:z, :c, 'HU')
|
|
ON CONFLICT (country_code, zip_code, city) DO UPDATE SET city = EXCLUDED.city
|
|
RETURNING id
|
|
""")
|
|
zip_res = await db.execute(zip_id_query, {"z": zip_code, "c": city})
|
|
zip_id = zip_res.scalar()
|
|
|
|
# 2. 🛣️ Utca szótár frissítése
|
|
await db.execute(text("""
|
|
INSERT INTO data.geo_streets (postal_code_id, name) VALUES (:zid, :n)
|
|
ON CONFLICT (postal_code_id, name) DO NOTHING
|
|
"""), {"zid": zip_id, "n": street_name})
|
|
|
|
# 3. 🏷️ Közterület típus (út, utca, köz...)
|
|
await db.execute(text("""
|
|
INSERT INTO data.geo_street_types (name) VALUES (:n)
|
|
ON CONFLICT (name) DO NOTHING
|
|
"""), {"n": street_type.lower()})
|
|
|
|
# 4. 📝 Szöveges cím generálása a kereshetőséghez
|
|
full_text_parts = [f"{zip_code} {city}, {street_name} {street_type} {house_number}."]
|
|
if stairwell: full_text_parts.append(f"{stairwell}. lph.")
|
|
if floor: full_text_parts.append(f"{floor}. em.")
|
|
if door: full_text_parts.append(f"{door}. ajtó")
|
|
full_text = " ".join(full_text_parts)
|
|
|
|
# 5. 🏠 Központi Address rekord rögzítése vagy lekérése
|
|
# Az aszinkron környezetben a RETURNING a legbiztosabb módszer
|
|
address_query = text("""
|
|
INSERT INTO data.addresses (
|
|
postal_code_id, street_name, street_type, house_number,
|
|
stairwell, floor, door, parcel_id, full_address_text
|
|
)
|
|
VALUES (:zid, :sn, :st, :hn, :sw, :fl, :dr, :pid, :txt)
|
|
ON CONFLICT DO NOTHING
|
|
RETURNING id
|
|
""")
|
|
|
|
params = {
|
|
"zid": zip_id, "sn": street_name, "st": street_type,
|
|
"hn": house_number, "sw": stairwell, "fl": floor,
|
|
"dr": door, "pid": parcel_id, "txt": full_text
|
|
}
|
|
|
|
res = await db.execute(address_query, params)
|
|
addr_id = res.scalar()
|
|
|
|
if not addr_id:
|
|
# Ha már létezett, megkeressük az ID-t a teljes szöveg alapján
|
|
# (Az IS NOT DISTINCT FROM kezeli a NULL értékeket az összehasonlításnál)
|
|
lookup_query = text("""
|
|
SELECT id FROM data.addresses
|
|
WHERE street_name = :sn AND house_number = :hn
|
|
AND (stairwell IS NOT DISTINCT FROM :sw)
|
|
AND (floor IS NOT DISTINCT FROM :fl)
|
|
AND (door IS NOT DISTINCT FROM :dr)
|
|
LIMIT 1
|
|
""")
|
|
lookup_res = await db.execute(lookup_query, params)
|
|
addr_id = lookup_res.scalar()
|
|
|
|
return addr_id
|
|
|
|
except Exception as e:
|
|
logger.error(f"Address Normalization Error: {str(e)}")
|
|
raise ValueError(f"Hiba a cím rögzítése során: {str(e)}") |