refaktor címjegyzék
This commit is contained in:
93
backend/app/api/v1/endpoints/locations.py
Normal file
93
backend/app/api/v1/endpoints/locations.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
🌍 Location Autocomplete API Endpoint.
|
||||
|
||||
Provides autocomplete search for postal codes and cities from the
|
||||
system.geo_postal_codes table. Used by the frontend SmartLocationInput
|
||||
component to let users quickly find and select a zip/city pair.
|
||||
|
||||
Schema: system.geo_postal_codes
|
||||
"""
|
||||
import logging
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy import select, or_
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.api.deps import get_db
|
||||
from app.models.identity.address import GeoPostalCode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class LocationAutocompleteItem(BaseModel):
|
||||
"""Egy találat a település autocomplete keresőben."""
|
||||
id: int
|
||||
zip_code: str
|
||||
city: str
|
||||
country_code: str = "HU"
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
@router.get("/locations/autocomplete", response_model=List[LocationAutocompleteItem])
|
||||
async def autocomplete_locations(
|
||||
q: str = Query(..., min_length=1, max_length=100, description="Keresőszó (irányítószám vagy városrészlet)"),
|
||||
country_code: str = Query("HU", max_length=5, description="Országkód szűrő (alapértelmezett: HU)"),
|
||||
limit: int = Query(15, ge=1, le=50, description="Max találatok száma"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
GET /api/v1/locations/autocomplete?q=budapest
|
||||
|
||||
Autocomplete keresés a system.geo_postal_codes táblában.
|
||||
A keresés az irányítószámra (zip_code) és a város névre (city) is
|
||||
történik ILIKE operátorral.
|
||||
|
||||
Példák:
|
||||
/api/v1/locations/autocomplete?q=1011 -> 1011 Budapest
|
||||
/api/v1/locations/autocomplete?q=budapest -> 1011 Budapest, 1012 Budapest, ...
|
||||
/api/v1/locations/autocomplete?q=101 -> 1011 Budapest, 1012 Budapest, ...
|
||||
/api/v1/locations/autocomplete?q=bud&country_code=AT -> 5020 Salzburg, ...
|
||||
"""
|
||||
if not q.strip():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="A keresőszó (q) nem lehet üres.",
|
||||
)
|
||||
|
||||
try:
|
||||
stmt = (
|
||||
select(GeoPostalCode)
|
||||
.where(
|
||||
GeoPostalCode.country_code == country_code,
|
||||
or_(
|
||||
GeoPostalCode.zip_code.ilike(f"%{q.strip()}%"),
|
||||
GeoPostalCode.city.ilike(f"%{q.strip()}%"),
|
||||
),
|
||||
)
|
||||
.order_by(GeoPostalCode.zip_code, GeoPostalCode.city)
|
||||
.limit(limit)
|
||||
)
|
||||
result = await db.execute(stmt)
|
||||
items = result.scalars().all()
|
||||
|
||||
return [
|
||||
LocationAutocompleteItem(
|
||||
id=item.id,
|
||||
zip_code=item.zip_code,
|
||||
city=item.city,
|
||||
country_code=item.country_code,
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Hiba a location autocomplete során: {e}", exc_info=True)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Hiba történt a település keresés során.",
|
||||
)
|
||||
Reference in New Issue
Block a user