from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func from app.models.service import ServiceProfile, ExpertiseTag, ServiceExpertise from app.models.organization import Organization from geoalchemy2.functions import ST_Distance, ST_MakePoint class SearchService: @staticmethod async def find_nearby_services( db: AsyncSession, lat: float, lon: float, expertise_key: str = None, radius_km: int = 50, is_premium: bool = False ): """ Keresés távolság és szakértelem alapján. Premium: Trust Score + Valós távolság. Free: Trust Score + Légvonal. """ user_point = ST_MakePoint(lon, lat) # PostGIS pont létrehozása # Alap lekérdezés: ServiceProfile + Organization adatok stmt = select(ServiceProfile, Organization).join( Organization, ServiceProfile.organization_id == Organization.id ) # 1. Sugár alapú szűrés (radius_km * 1000 méter) stmt = stmt.where( func.ST_DWithin(ServiceProfile.location, user_point, radius_km * 1000) ) # 2. Szakterület szűrése if expertise_key: stmt = stmt.join(ServiceProfile.expertises).join(ExpertiseTag).where( ExpertiseTag.key == expertise_key ) # 3. Távolság és Trust Score alapú sorrend # A ST_Distance méterben adja vissza az eredményt stmt = stmt.order_by(ST_Distance(ServiceProfile.location, user_point)) result = await db.execute(stmt.limit(50)) rows = result.all() # Rangsorolási logika alkalmazása results = [] for s_prof, org in rows: results.append({ "id": org.id, "name": org.full_name, "trust_score": s_prof.trust_score, "is_verified": s_prof.is_verified, "phone": s_prof.contact_phone, "website": s_prof.website, "is_premium_partner": s_prof.trust_score >= 90 }) # Súlyozott rendezés: Prémium partnerek és Trust Score előre return sorted(results, key=lambda x: (not is_premium, -x['trust_score']))