FairRelay / brain /app /api /driver_api.py
MouleeswaranM's picture
Upload folder using huggingface_hub
fcf8749 verified
"""
Phase 2 Driver-facing API endpoints.
Handles driver operations: assignments, stats, deliveries, feedback, swaps, issues.
"""
from datetime import date as date_type
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.ext.asyncio import AsyncSession
from uuid import UUID
from app.database import get_db
from app.schemas.driver_api import (
TodayAssignmentResponse,
DriverStatsWindowResponse,
DeliveryLogRequest,
DeliveryLogResponse,
RouteSwapRequestCreate,
RouteSwapRequestResponse,
StopIssueRequest,
StopIssueResponse,
)
from app.services.driver_service import (
get_today_assignment,
get_driver_stats,
log_delivery,
create_route_swap_request,
create_stop_issue,
)
router = APIRouter(tags=["Driver"])
@router.get(
"/assignments/today",
response_model=TodayAssignmentResponse,
summary="Get today's assignment",
description="Fetch the driver's assignment for the given date with full stop details.",
)
async def get_assignment_today(
driver_id: UUID = Query(..., description="Driver UUID"),
target_date: date_type = Query(default=None, description="Date (defaults to today)"),
db: AsyncSession = Depends(get_db),
) -> TodayAssignmentResponse:
"""Get driver's assignment for today or specified date."""
actual_date = target_date or date_type.today()
result = await get_today_assignment(db, driver_id, actual_date)
if not result:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="No assignment found for driver on given date",
)
return result
@router.get(
"/drivers/{driver_id}/stats",
response_model=DriverStatsWindowResponse,
summary="Get driver stats",
description="Get driver statistics over a time window.",
)
async def get_driver_stats_endpoint(
driver_id: UUID,
window_days: int = Query(default=7, ge=1, le=90, description="Days to look back"),
db: AsyncSession = Depends(get_db),
) -> DriverStatsWindowResponse:
"""Get driver stats over time window."""
result = await get_driver_stats(db, driver_id, window_days)
if not result:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Driver not found",
)
return result
@router.post(
"/deliveries/log",
response_model=DeliveryLogResponse,
status_code=status.HTTP_201_CREATED,
summary="Log delivery",
description="Log a delivery attempt at a stop.",
)
async def log_delivery_endpoint(
request: DeliveryLogRequest,
db: AsyncSession = Depends(get_db),
) -> DeliveryLogResponse:
"""Log a delivery at a stop."""
try:
result = await log_delivery(
db=db,
assignment_id=request.assignment_id,
route_id=request.route_id,
driver_id=request.driver_id,
stop_order=request.stop_order,
status=request.status,
issue_type=request.issue_type,
package_id=request.package_id,
photo_url=request.photo_url,
signature_data=request.signature_data,
notes=request.notes,
)
await db.commit()
return result
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)
@router.post(
"/route_swap_requests",
response_model=RouteSwapRequestResponse,
status_code=status.HTTP_201_CREATED,
summary="Request route swap",
description="Submit a route swap request.",
)
async def create_route_swap_endpoint(
request: RouteSwapRequestCreate,
db: AsyncSession = Depends(get_db),
) -> RouteSwapRequestResponse:
"""Create a route swap request."""
try:
result = await create_route_swap_request(
db=db,
from_driver_id=request.from_driver_id,
assignment_id=request.assignment_id,
reason=request.reason,
to_driver_id=request.to_driver_id,
preferred_date=request.preferred_date,
)
await db.commit()
return result
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)
@router.post(
"/stop_issues",
response_model=StopIssueResponse,
status_code=status.HTTP_201_CREATED,
summary="Report stop issue",
description="Report an issue at a specific stop.",
)
async def create_stop_issue_endpoint(
request: StopIssueRequest,
db: AsyncSession = Depends(get_db),
) -> StopIssueResponse:
"""Create a stop issue report."""
try:
result = await create_stop_issue(
db=db,
assignment_id=request.assignment_id,
route_id=request.route_id,
driver_id=request.driver_id,
stop_order=request.stop_order,
issue_type=request.issue_type,
notes=request.notes,
)
await db.commit()
return result
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)