first commit
This commit is contained in:
202
backend/routes/grade_routes.py
Normal file
202
backend/routes/grade_routes.py
Normal file
@@ -0,0 +1,202 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||||
from typing import List, Optional
|
||||
from models import GradeCreate, GradeUpdate, GradeResponse, GradeInDB, UserInDB
|
||||
from database import get_database
|
||||
from routes.auth_routes import get_current_user
|
||||
from bson import ObjectId
|
||||
from datetime import datetime
|
||||
|
||||
router = APIRouter(prefix="/grades", tags=["grades"])
|
||||
|
||||
|
||||
@router.post("", response_model=GradeResponse, status_code=status.HTTP_201_CREATED)
|
||||
async def create_grade(
|
||||
grade: GradeCreate,
|
||||
current_user: UserInDB = Depends(get_current_user)
|
||||
):
|
||||
"""Create a new grade/test entry"""
|
||||
db = get_database()
|
||||
|
||||
# Verify subject exists and belongs to user
|
||||
if not ObjectId.is_valid(grade.subject_id):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Invalid subject ID"
|
||||
)
|
||||
|
||||
subject = await db.subjects.find_one({
|
||||
"_id": ObjectId(grade.subject_id),
|
||||
"user_id": current_user.id
|
||||
})
|
||||
|
||||
if not subject:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Subject not found"
|
||||
)
|
||||
|
||||
# Verify category exists in subject
|
||||
category_names = [cat["name"] for cat in subject.get("grading_categories", [])]
|
||||
if grade.category_name not in category_names:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Category '{grade.category_name}' not found in subject. Available: {', '.join(category_names)}"
|
||||
)
|
||||
|
||||
grade_in_db = GradeInDB(
|
||||
**grade.model_dump(),
|
||||
user_id=current_user.id
|
||||
)
|
||||
|
||||
grade_dict = grade_in_db.model_dump(by_alias=True)
|
||||
grade_dict["_id"] = ObjectId(grade_dict["_id"])
|
||||
|
||||
result = await db.grades.insert_one(grade_dict)
|
||||
grade_dict["_id"] = str(result.inserted_id)
|
||||
|
||||
return GradeResponse(**grade_dict)
|
||||
|
||||
|
||||
@router.get("", response_model=List[GradeResponse])
|
||||
async def get_grades(
|
||||
subject_id: Optional[str] = Query(None),
|
||||
current_user: UserInDB = Depends(get_current_user)
|
||||
):
|
||||
"""Get all grades for the current user, optionally filtered by subject"""
|
||||
db = get_database()
|
||||
|
||||
query = {"user_id": current_user.id}
|
||||
if subject_id:
|
||||
if not ObjectId.is_valid(subject_id):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Invalid subject ID"
|
||||
)
|
||||
query["subject_id"] = subject_id
|
||||
|
||||
cursor = db.grades.find(query).sort("date", -1) # Most recent first
|
||||
grades = await cursor.to_list(length=None)
|
||||
|
||||
for grade in grades:
|
||||
grade["_id"] = str(grade["_id"])
|
||||
|
||||
return [GradeResponse(**grade) for grade in grades]
|
||||
|
||||
|
||||
@router.get("/{grade_id}", response_model=GradeResponse)
|
||||
async def get_grade(
|
||||
grade_id: str,
|
||||
current_user: UserInDB = Depends(get_current_user)
|
||||
):
|
||||
"""Get a specific grade"""
|
||||
db = get_database()
|
||||
|
||||
if not ObjectId.is_valid(grade_id):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Invalid grade ID"
|
||||
)
|
||||
|
||||
grade = await db.grades.find_one({
|
||||
"_id": ObjectId(grade_id),
|
||||
"user_id": current_user.id
|
||||
})
|
||||
|
||||
if not grade:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Grade not found"
|
||||
)
|
||||
|
||||
grade["_id"] = str(grade["_id"])
|
||||
return GradeResponse(**grade)
|
||||
|
||||
|
||||
@router.put("/{grade_id}", response_model=GradeResponse)
|
||||
async def update_grade(
|
||||
grade_id: str,
|
||||
grade_update: GradeUpdate,
|
||||
current_user: UserInDB = Depends(get_current_user)
|
||||
):
|
||||
"""Update a grade"""
|
||||
db = get_database()
|
||||
|
||||
if not ObjectId.is_valid(grade_id):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Invalid grade ID"
|
||||
)
|
||||
|
||||
# Check if grade exists and belongs to user
|
||||
existing_grade = await db.grades.find_one({
|
||||
"_id": ObjectId(grade_id),
|
||||
"user_id": current_user.id
|
||||
})
|
||||
|
||||
if not existing_grade:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Grade not found"
|
||||
)
|
||||
|
||||
# If updating category, verify it exists in subject
|
||||
if grade_update.category_name:
|
||||
subject = await db.subjects.find_one({
|
||||
"_id": ObjectId(existing_grade["subject_id"]),
|
||||
"user_id": current_user.id
|
||||
})
|
||||
|
||||
if subject:
|
||||
category_names = [cat["name"] for cat in subject.get("grading_categories", [])]
|
||||
if grade_update.category_name not in category_names:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Category '{grade_update.category_name}' not found in subject"
|
||||
)
|
||||
|
||||
# Update only provided fields
|
||||
update_data = grade_update.model_dump(exclude_unset=True)
|
||||
if update_data:
|
||||
update_data["updated_at"] = datetime.utcnow()
|
||||
await db.grades.update_one(
|
||||
{"_id": ObjectId(grade_id)},
|
||||
{"$set": update_data}
|
||||
)
|
||||
|
||||
# Fetch updated grade
|
||||
updated_grade = await db.grades.find_one({"_id": ObjectId(grade_id)})
|
||||
updated_grade["_id"] = str(updated_grade["_id"])
|
||||
|
||||
return GradeResponse(**updated_grade)
|
||||
|
||||
|
||||
@router.delete("/{grade_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def delete_grade(
|
||||
grade_id: str,
|
||||
current_user: UserInDB = Depends(get_current_user)
|
||||
):
|
||||
"""Delete a grade"""
|
||||
db = get_database()
|
||||
|
||||
if not ObjectId.is_valid(grade_id):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Invalid grade ID"
|
||||
)
|
||||
|
||||
# Check if grade exists and belongs to user
|
||||
grade = await db.grades.find_one({
|
||||
"_id": ObjectId(grade_id),
|
||||
"user_id": current_user.id
|
||||
})
|
||||
|
||||
if not grade:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Grade not found"
|
||||
)
|
||||
|
||||
# Delete grade
|
||||
await db.grades.delete_one({"_id": ObjectId(grade_id)})
|
||||
|
||||
return None
|
||||
Reference in New Issue
Block a user