from typing import Any, List from fastapi import APIRouter, Depends, HTTPException, Path, Query, status from sqlalchemy.orm import Session from app.core.deps import get_current_active_user from app.db.session import get_db from app.models.shipment import ShipmentStatus from app.models.user import User from app.schemas.shipment import ( Shipment, ShipmentCreate, ShipmentItem, ShipmentTracking, ShipmentUpdate, ) from app.services import shipment as shipment_service router = APIRouter() @router.get("/", response_model=List[Shipment]) def read_shipments( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, order_id: int = Query(None, description="Filter by order ID"), current_user: User = Depends(get_current_active_user), ) -> Any: """ Retrieve shipments. """ shipments = shipment_service.get_multi( db, skip=skip, limit=limit, order_id=order_id ) return shipments @router.post("/", response_model=Shipment) def create_shipment( *, db: Session = Depends(get_db), shipment_in: ShipmentCreate, current_user: User = Depends(get_current_active_user), ) -> Any: """ Create new shipment. """ # Set current user as creator if not provided if not shipment_in.created_by_id: shipment_in.created_by_id = current_user.id # Only superusers can create shipments for other users if not current_user.is_superuser and shipment_in.created_by_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="You can only create shipments for yourself", ) try: shipment = shipment_service.create(db, obj_in=shipment_in) return shipment except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e), ) @router.get("/{shipment_id}", response_model=Shipment) def read_shipment( *, db: Session = Depends(get_db), shipment_id: int = Path(..., description="The ID of the shipment to get"), current_user: User = Depends(get_current_active_user), ) -> Any: """ Get shipment by ID. """ shipment = shipment_service.get(db, shipment_id=shipment_id) if not shipment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Shipment not found", ) return shipment @router.get("/tracking/{tracking_number}", response_model=ShipmentTracking) def read_shipment_by_tracking( *, db: Session = Depends(get_db), tracking_number: str = Path(..., description="The tracking number of the shipment"), ) -> Any: """ Get shipment tracking information by tracking number. This endpoint is public. """ shipment = shipment_service.get_by_tracking_number(db, tracking_number=tracking_number) if not shipment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Shipment not found", ) return { "tracking_number": shipment.tracking_number, "status": shipment.status, "carrier": shipment.carrier, "estimated_delivery": shipment.estimated_delivery, "actual_delivery": shipment.actual_delivery, } @router.put("/{shipment_id}", response_model=Shipment) def update_shipment( *, db: Session = Depends(get_db), shipment_id: int = Path(..., description="The ID of the shipment to update"), shipment_in: ShipmentUpdate, current_user: User = Depends(get_current_active_user), ) -> Any: """ Update a shipment. """ shipment = shipment_service.get(db, shipment_id=shipment_id) if not shipment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Shipment not found", ) # Only superusers or the creator can update shipments if not current_user.is_superuser and shipment.created_by_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions", ) shipment = shipment_service.update(db, db_obj=shipment, obj_in=shipment_in) return shipment @router.put("/{shipment_id}/status", response_model=Shipment) def update_shipment_status( *, db: Session = Depends(get_db), shipment_id: int = Path(..., description="The ID of the shipment to update"), status: ShipmentStatus, current_user: User = Depends(get_current_active_user), ) -> Any: """ Update shipment status. """ shipment = shipment_service.get(db, shipment_id=shipment_id) if not shipment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Shipment not found", ) # Only superusers or the creator can update shipment status if not current_user.is_superuser and shipment.created_by_id != current_user.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions", ) shipment = shipment_service.update_status(db, shipment_id=shipment_id, status=status) return shipment @router.get("/{shipment_id}/items", response_model=List[ShipmentItem]) def read_shipment_items( *, db: Session = Depends(get_db), shipment_id: int = Path(..., description="The ID of the shipment to get items for"), current_user: User = Depends(get_current_active_user), ) -> Any: """ Get all items for a specific shipment. """ shipment = shipment_service.get(db, shipment_id=shipment_id) if not shipment: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Shipment not found", ) items = shipment_service.get_shipment_items(db, shipment_id=shipment_id) return items