from typing import Any, List from fastapi import APIRouter, Depends, HTTPException, Path, Response, status from sqlalchemy.orm import Session from app import crud, models, schemas from app.api.v1.deps import get_db, get_current_active_user, get_admin_user router = APIRouter() @router.get("/", response_model=List[schemas.Student]) def read_students( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Retrieve students. """ # Regular users can only see their own student profile if they are a student if crud.user.is_admin(current_user): students = crud.student.get_multi(db, skip=skip, limit=limit) else: student = db.query(models.Student).filter(models.Student.user_id == current_user.id).first() students = [student] if student else [] return students @router.get("/{student_id}", response_model=schemas.StudentWithUser) def read_student( *, db: Session = Depends(get_db), student_id: int = Path(..., title="The ID of the student to get"), current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Get student by ID with user details. """ student = crud.student.get(db=db, id=student_id) if not student: raise HTTPException( status_code=404, detail="Student not found", ) # Regular users can only see their own student profile if not crud.user.is_admin(current_user) and student.user_id != current_user.id: raise HTTPException( status_code=403, detail="Not enough permissions to view this student profile" ) # Get user details user = crud.user.get(db=db, id=student.user_id) # Create a combined response result = schemas.StudentWithUser.from_orm(student) result.user = user return result @router.post("/", response_model=schemas.Student) def create_student( *, db: Session = Depends(get_db), student_in: schemas.StudentCreate, current_user: models.User = Depends(get_admin_user), ) -> Any: """ Create new student. """ # Check if the user exists user = crud.user.get(db=db, id=student_in.user_id) if not user: raise HTTPException( status_code=404, detail=f"User with ID {student_in.user_id} not found", ) # Check if student profile already exists for this user existing_student = db.query(models.Student).filter(models.Student.user_id == user.id).first() if existing_student: raise HTTPException( status_code=400, detail=f"Student profile already exists for user ID {user.id}", ) # Check if student_id is unique existing_student_id = db.query(models.Student).filter(models.Student.student_id == student_in.student_id).first() if existing_student_id: raise HTTPException( status_code=400, detail=f"Student ID {student_in.student_id} is already taken", ) student = crud.student.create(db=db, obj_in=student_in) return student @router.put("/{student_id}", response_model=schemas.Student) def update_student( *, db: Session = Depends(get_db), student_id: int = Path(..., title="The ID of the student to update"), student_in: schemas.StudentUpdate, current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Update a student. """ student = crud.student.get(db=db, id=student_id) if not student: raise HTTPException( status_code=404, detail="Student not found", ) # Regular users can only update their own student profile if not crud.user.is_admin(current_user) and student.user_id != current_user.id: raise HTTPException( status_code=403, detail="Not enough permissions to update this student profile" ) # Check if student_id is unique if it's being updated if student_in.student_id and student_in.student_id != student.student_id: existing_student_id = db.query(models.Student).filter(models.Student.student_id == student_in.student_id).first() if existing_student_id: raise HTTPException( status_code=400, detail=f"Student ID {student_in.student_id} is already taken", ) student = crud.student.update(db=db, db_obj=student, obj_in=student_in) return student @router.delete("/{student_id}", response_model=None, status_code=status.HTTP_204_NO_CONTENT) def delete_student( *, db: Session = Depends(get_db), student_id: int = Path(..., title="The ID of the student to delete"), current_user: models.User = Depends(get_admin_user), ) -> Any: """ Delete a student. """ student = crud.student.get(db=db, id=student_id) if not student: raise HTTPException( status_code=404, detail="Student not found", ) crud.student.remove(db=db, id=student_id) return Response(status_code=status.HTTP_204_NO_CONTENT) @router.get("/{student_id}/exams", response_model=List[schemas.ExamResult]) def read_student_exam_results( *, db: Session = Depends(get_db), student_id: int = Path(..., title="The ID of the student to get exam results for"), current_user: models.User = Depends(get_current_active_user), ) -> Any: """ Get all exam results for a student. """ student = crud.student.get(db=db, id=student_id) if not student: raise HTTPException( status_code=404, detail="Student not found", ) # Regular users can only see their own exam results if not crud.user.is_admin(current_user) and student.user_id != current_user.id: raise HTTPException( status_code=403, detail="Not enough permissions to view this student's exam results" ) exam_results = crud.exam_result.get_by_student(db=db, student_id=student_id) return exam_results