TEST-FRANKO / api /geocoding_routes.py
Franko Fišter
Added geocoding repository and endpoints
a31ad35
from fastapi import APIRouter, HTTPException, BackgroundTasks, Query
from typing import Optional
import logging
from db.geocoding_repository import GeocodingRepository
from config.settings import GEOAPIFY_API_KEY
router = APIRouter(prefix="/geocoding", tags=["Geocoding"])
logger = logging.getLogger(__name__)
# Global variable to track geocoding status
geocoding_status = {
"running": False,
"last_run": None,
"last_result": None
}
async def run_geocoding_task(api_key: str = None):
"""Background task to run geocoding"""
global geocoding_status
try:
geocoding_status["running"] = True
geocoding_status["last_result"] = None
async with GeocodingRepository() as repo:
result = await repo.batch_geocode_stores(api_key=api_key)
geocoding_status["last_result"] = result
geocoding_status["last_run"] = "completed"
except Exception as e:
logger.error(f"Error in geocoding task: {e}")
geocoding_status["last_result"] = {"error": str(e)}
geocoding_status["last_run"] = "failed"
finally:
geocoding_status["running"] = False
@router.post("/start")
async def start_geocoding(
background_tasks: BackgroundTasks,
api_key: Optional[str] = Query(None, description="Geoapify API key (optional - will use settings if not provided)")
):
"""
Start the geocoding process for all stores without coordinates using Geoapify.
- **api_key**: Geoapify API key (optional - will use environment variable if not provided)
"""
if geocoding_status["running"]:
raise HTTPException(
status_code=400,
detail="Geocoding process is already running"
)
# Use provided API key or fallback to settings
final_api_key = api_key or GEOAPIFY_API_KEY
if not final_api_key:
raise HTTPException(
status_code=400,
detail="Geoapify API key is required. Provide it as parameter or set GEOAPIFY_API_KEY environment variable."
)
# Start background task
background_tasks.add_task(run_geocoding_task, final_api_key)
return {
"message": "Geocoding process started",
"status": "running",
"service": "Geoapify"
}
@router.get("/status")
async def get_geocoding_status():
"""Get the current status of the geocoding process"""
return {
"running": geocoding_status["running"],
"last_run": geocoding_status["last_run"],
"last_result": geocoding_status["last_result"]
}
@router.get("/stores-without-coordinates")
async def get_stores_without_coordinates():
"""Get count of stores that still need geocoding"""
try:
async with GeocodingRepository() as repo:
stores = repo.get_stores_without_coordinates()
return {
"count": len(stores),
"stores": stores[:10] # Return first 10 as sample
}
except Exception as e:
logger.error(f"Error getting stores without coordinates: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/geocode-single/{store_id}")
async def geocode_single_store(
store_id: str,
api_key: Optional[str] = Query(None, description="Geoapify API key")
):
"""Geocode a single store by ID"""
try:
# Use provided API key or fallback to settings
final_api_key = api_key or GEOAPIFY_API_KEY
if not final_api_key:
raise HTTPException(
status_code=400,
detail="Geoapify API key is required"
)
async with GeocodingRepository() as repo:
# Get store details
store_response = repo.supabase.table('stores').select('*').eq('store_id', store_id).execute()
if not store_response.data:
raise HTTPException(status_code=404, detail="Store not found")
store = store_response.data[0]
address = store.get('store_address', '')
if not address:
raise HTTPException(status_code=400, detail="Store has no address")
# Geocode address using Geoapify
coordinates = await repo.geocode_address_geoapify(address, store_id, final_api_key)
if coordinates:
lat, lng = coordinates
if repo.update_store_coordinates(store_id, lat, lng):
return {
"message": "Store geocoded successfully",
"store_id": store_id,
"coordinates": {"lat": lat, "lng": lng}
}
else:
raise HTTPException(status_code=500, detail="Failed to update coordinates")
else:
raise HTTPException(status_code=400, detail="Failed to geocode address")
except HTTPException:
raise
except Exception as e:
logger.error(f"Error geocoding single store: {e}")
raise HTTPException(status_code=500, detail=str(e))