from typing import Any, List from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.schemas import route as route_schema from app.services.crud_route import route as crud_route from geoalchemy2.shape import to_shape from shapely.geometry import mapping router = APIRouter() @router.get("/peak/{peak_id}", response_model=List[route_schema.Route]) async def read_routes_by_peak( peak_id: int, db: AsyncSession = Depends(get_db), ): """ Retrieve routes for a specific peak. """ routes = await crud_route.get_by_peak(db, peak_id=peak_id) results = [] for r in routes: r_dict = r.__dict__.copy() # Handle Route Geometry if r.path_geometry is not None: sh = to_shape(r.path_geometry) r_dict['path_geometry'] = mapping(sh) # Handle Camps Geometry (Nested) # Since we used selectinload, r.camps should be populated # But we need to convert their WKB locations to GeoJSON as well if 'camps' in r_dict: camps_data = [] for camp in r.camps: c_dict = camp.__dict__.copy() if camp.location is not None: c_sh = to_shape(camp.location) c_dict['location'] = mapping(c_sh) camps_data.append(c_dict) r_dict['camps'] = camps_data results.append(r_dict) return results @router.post("/", response_model=route_schema.Route) async def create_route( *, db: AsyncSession = Depends(get_db), route_in: route_schema.RouteCreate, ): """ Create new route. """ route = await crud_route.create(db=db, obj_in=route_in) r_dict = route.__dict__.copy() if route.path_geometry is not None: sh = to_shape(route.path_geometry) r_dict['path_geometry'] = mapping(sh) return r_dict