from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, status, Request from sqlalchemy.orm import Session from datetime import date from app.api.deps import get_db, get_current_read_user, get_current_operator_user from app.crud.crud_departure import departure as crud_departure from app.schemas.departure import Departure, DepartureCreate, DepartureUpdate, DepartureStatus, DepartureStatusUpdate from app.models.ppr import User from app.core.utils import get_client_ip router = APIRouter() @router.get("/", response_model=List[Departure]) async def get_departures( request: Request, skip: int = 0, limit: int = 100, status: Optional[DepartureStatus] = None, date_from: Optional[date] = None, date_to: Optional[date] = None, db: Session = Depends(get_db), current_user: User = Depends(get_current_read_user) ): """Get departure records with optional filtering""" departures = crud_departure.get_multi( db, skip=skip, limit=limit, status=status, date_from=date_from, date_to=date_to ) return departures @router.post("/", response_model=Departure) async def create_departure( request: Request, departure_in: DepartureCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Create a new departure record""" departure = crud_departure.create(db, obj_in=departure_in, created_by=current_user.username) # Send real-time update via WebSocket if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "departure_booked_out", "data": { "id": departure.id, "registration": departure.registration, "out_to": departure.out_to, "status": departure.status.value } }) return departure @router.get("/{departure_id}", response_model=Departure) async def get_departure( departure_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_read_user) ): """Get a specific departure record""" departure = crud_departure.get(db, departure_id=departure_id) if not departure: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Departure record not found" ) return departure @router.put("/{departure_id}", response_model=Departure) async def update_departure( request: Request, departure_id: int, departure_in: DepartureUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Update a departure record""" db_departure = crud_departure.get(db, departure_id=departure_id) if not db_departure: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Departure record not found" ) # Get user IP from request user_ip = request.client.host if request.client else None departure = crud_departure.update( db, db_obj=db_departure, obj_in=departure_in, user=current_user.username, user_ip=user_ip ) # Send real-time update if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "departure_updated", "data": { "id": departure.id, "registration": departure.registration, "status": departure.status.value } }) return departure @router.patch("/{departure_id}/status", response_model=Departure) async def update_departure_status( request: Request, departure_id: int, status_update: DepartureStatusUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Update departure status""" client_ip = get_client_ip(request) departure = crud_departure.update_status( db, departure_id=departure_id, status=status_update.status, timestamp=status_update.timestamp, user=current_user.username, user_ip=client_ip ) if not departure: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Departure record not found" ) # Send real-time update if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "departure_status_update", "data": { "id": departure.id, "registration": departure.registration, "status": departure.status.value, "departed_dt": departure.departed_dt.isoformat() if departure.departed_dt else None } }) return departure @router.delete("/{departure_id}", response_model=Departure) async def cancel_departure( request: Request, departure_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_operator_user) ): """Cancel a departure record""" departure = crud_departure.cancel(db, departure_id=departure_id) if not departure: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Departure record not found" ) # Send real-time update if hasattr(request.app.state, 'connection_manager'): await request.app.state.connection_manager.broadcast({ "type": "departure_cancelled", "data": { "id": departure.id, "registration": departure.registration } }) return departure