188 lines
6.0 KiB
Python

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