teljes backend_mentés
This commit is contained in:
@@ -1,24 +1,90 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/api/v1/endpoints/search.py
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy import select, func, or_
|
||||
from sqlalchemy.orm import selectinload
|
||||
from app.db.session import get_db
|
||||
from app.api.deps import get_current_user
|
||||
from app.models.marketplace.organization import Organization # JAVÍTVA
|
||||
from app.models.marketplace.organization import Organization, Branch
|
||||
from geoalchemy2 import WKTElement
|
||||
from typing import Optional
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/match")
|
||||
async def match_service(lat: float, lng: float, radius: int = 20, db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user)):
|
||||
# PostGIS alapú keresés a fleet.branches táblában (a régi locations helyett)
|
||||
query = text("""
|
||||
SELECT o.id, o.name, b.city,
|
||||
ST_Distance(b.location, ST_SetSRID(ST_MakePoint(:lng, :lat), 4326)::geography) / 1000 as distance
|
||||
FROM fleet.organizations o
|
||||
JOIN fleet.branches b ON o.id = b.organization_id
|
||||
WHERE o.is_active = True AND b.is_active = True
|
||||
AND ST_DWithin(b.location, ST_SetSRID(ST_MakePoint(:lng, :lat), 4326)::geography, :r * 1000)
|
||||
ORDER BY distance ASC
|
||||
""")
|
||||
result = await db.execute(query, {"lat": lat, "lng": lng, "r": radius})
|
||||
return {"results": [dict(row._mapping) for row in result.fetchall()]}
|
||||
async def match_service(
|
||||
lat: Optional[float] = None,
|
||||
lng: Optional[float] = None,
|
||||
radius_km: float = 20.0,
|
||||
sort_by: str = "distance",
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Geofencing keresőmotor PostGIS segítségével.
|
||||
Ha nincs megadva lat/lng, akkor nem alkalmazunk távolságszűrést.
|
||||
"""
|
||||
# Alap lekérdezés: aktív szervezetek és telephelyek
|
||||
query = select(
|
||||
Organization.id,
|
||||
Organization.name,
|
||||
Branch.city,
|
||||
Branch.branch_rating,
|
||||
Branch.location
|
||||
).join(
|
||||
Branch, Organization.id == Branch.organization_id
|
||||
).where(
|
||||
Organization.is_active == True,
|
||||
Branch.is_deleted == False
|
||||
)
|
||||
|
||||
# Távolság számítás és szűrés, ha van koordináta
|
||||
if lat is not None and lng is not None:
|
||||
# WKT pont létrehozása a felhasználó helyéhez
|
||||
user_location = WKTElement(f'POINT({lng} {lat})', srid=4326)
|
||||
|
||||
# Távolság kiszámítása méterben (ST_DistanceSphere)
|
||||
distance_col = func.ST_DistanceSphere(Branch.location, user_location).label("distance_meters")
|
||||
query = query.add_columns(distance_col)
|
||||
|
||||
# Szűrés a sugárra (ST_DWithin) - a távolság méterben, radius_km * 1000
|
||||
query = query.where(
|
||||
func.ST_DWithin(Branch.location, user_location, radius_km * 1000)
|
||||
)
|
||||
else:
|
||||
# Ha nincs koordináta, ne legyen distance oszlop
|
||||
distance_col = None
|
||||
|
||||
# Rendezés a sort_by paraméter alapján
|
||||
if sort_by == "distance" and lat is not None and lng is not None:
|
||||
query = query.order_by(distance_col.asc())
|
||||
elif sort_by == "rating":
|
||||
query = query.order_by(Branch.branch_rating.desc())
|
||||
elif sort_by == "price":
|
||||
# Jelenleg nincs ár információ, ezért rendezés alapértelmezettként (pl. név)
|
||||
query = query.order_by(Organization.name.asc())
|
||||
else:
|
||||
# Alapértelmezett rendezés: távolság, ha van, különben név
|
||||
if distance_col is not None:
|
||||
query = query.order_by(distance_col.asc())
|
||||
else:
|
||||
query = query.order_by(Organization.name.asc())
|
||||
|
||||
# Lekérdezés végrehajtása
|
||||
result = await db.execute(query)
|
||||
rows = result.fetchall()
|
||||
|
||||
# Eredmények formázása
|
||||
results = []
|
||||
for row in rows:
|
||||
row_dict = {
|
||||
"id": row.id,
|
||||
"name": row.name,
|
||||
"city": row.city,
|
||||
"rating": row.branch_rating,
|
||||
}
|
||||
if lat is not None and lng is not None:
|
||||
row_dict["distance_km"] = round(row.distance_meters / 1000, 2) if row.distance_meters else None
|
||||
results.append(row_dict)
|
||||
|
||||
return {"results": results}
|
||||
Reference in New Issue
Block a user