mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: grading, mark as done and grade showing
This commit is contained in:
parent
9530ee6930
commit
40ef2d0cec
7 changed files with 572 additions and 94 deletions
|
|
@ -20,7 +20,10 @@ from src.services.courses.activities.assignments import (
|
|||
delete_assignment_submission,
|
||||
delete_assignment_task,
|
||||
delete_assignment_task_submission,
|
||||
get_grade_assignment_submission,
|
||||
grade_assignment_submission,
|
||||
handle_assignment_task_submission,
|
||||
mark_activity_as_done_for_user,
|
||||
put_assignment_task_reference_file,
|
||||
put_assignment_task_submission_file,
|
||||
read_assignment,
|
||||
|
|
@ -263,7 +266,9 @@ async def api_handle_assignment_task_submissions(
|
|||
)
|
||||
|
||||
|
||||
@router.get("/{assignment_uuid}/tasks/{assignment_task_uuid}/submissions/user/{user_id}")
|
||||
@router.get(
|
||||
"/{assignment_uuid}/tasks/{assignment_task_uuid}/submissions/user/{user_id}"
|
||||
)
|
||||
async def api_read_user_assignment_task_submissions(
|
||||
request: Request,
|
||||
assignment_task_uuid: str,
|
||||
|
|
@ -410,7 +415,7 @@ async def api_update_user_assignment_submissions(
|
|||
@router.delete("/{assignment_uuid}/submissions/{user_id}")
|
||||
async def api_delete_user_assignment_submissions(
|
||||
request: Request,
|
||||
assignment_id: str,
|
||||
assignment_uuid: str,
|
||||
user_id: str,
|
||||
current_user: PublicUser = Depends(get_current_user),
|
||||
db_session=Depends(get_db_session),
|
||||
|
|
@ -419,5 +424,53 @@ async def api_delete_user_assignment_submissions(
|
|||
Delete submissions for an assignment from a user
|
||||
"""
|
||||
return await delete_assignment_submission(
|
||||
request, assignment_id, user_id, current_user, db_session
|
||||
request, user_id, assignment_uuid, current_user, db_session
|
||||
)
|
||||
@router.get("/{assignment_uuid}/submissions/{user_id}/grade")
|
||||
async def api_get_submission_grade(
|
||||
request: Request,
|
||||
assignment_uuid: str,
|
||||
user_id: str,
|
||||
current_user: PublicUser = Depends(get_current_user),
|
||||
db_session=Depends(get_db_session),
|
||||
):
|
||||
"""
|
||||
Grade submissions for an assignment from a user
|
||||
"""
|
||||
|
||||
return await get_grade_assignment_submission(
|
||||
request, user_id, assignment_uuid, current_user, db_session
|
||||
)
|
||||
|
||||
@router.post("/{assignment_uuid}/submissions/{user_id}/grade")
|
||||
async def api_final_grade_submission(
|
||||
request: Request,
|
||||
assignment_uuid: str,
|
||||
user_id: str,
|
||||
current_user: PublicUser = Depends(get_current_user),
|
||||
db_session=Depends(get_db_session),
|
||||
):
|
||||
"""
|
||||
Grade submissions for an assignment from a user
|
||||
"""
|
||||
|
||||
return await grade_assignment_submission(
|
||||
request, user_id, assignment_uuid, current_user, db_session
|
||||
)
|
||||
|
||||
|
||||
@router.post("/{assignment_uuid}/submissions/{user_id}/done")
|
||||
async def api_submission_mark_as_done(
|
||||
request: Request,
|
||||
assignment_uuid: str,
|
||||
user_id: str,
|
||||
current_user: PublicUser = Depends(get_current_user),
|
||||
db_session=Depends(get_db_session),
|
||||
):
|
||||
"""
|
||||
Grade submissions for an assignment from a user
|
||||
"""
|
||||
|
||||
return await mark_activity_as_done_for_user(
|
||||
request, user_id, assignment_uuid, current_user, db_session
|
||||
)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ from src.db.courses.assignments import (
|
|||
)
|
||||
from src.db.courses.courses import Course
|
||||
from src.db.organizations import Organization
|
||||
from src.db.users import AnonymousUser, PublicUser
|
||||
from src.db.trail_runs import TrailRun
|
||||
from src.db.trail_steps import TrailStep
|
||||
from src.db.users import AnonymousUser, PublicUser, User
|
||||
from src.security.rbac.rbac import (
|
||||
authorization_verify_based_on_roles_and_authorship_and_usergroups,
|
||||
authorization_verify_if_element_is_public,
|
||||
|
|
@ -39,6 +41,7 @@ from src.services.courses.activities.uploads.sub_file import upload_submission_f
|
|||
from src.services.courses.activities.uploads.tasks_ref_files import (
|
||||
upload_reference_file,
|
||||
)
|
||||
from src.services.trail.trail import check_trail_presence
|
||||
|
||||
## > Assignments CRUD
|
||||
|
||||
|
|
@ -1097,6 +1100,80 @@ async def create_assignment_submission(
|
|||
db_session.add(assignment_user_submission)
|
||||
db_session.commit()
|
||||
|
||||
# User
|
||||
statement = select(User).where(User.id == current_user.id)
|
||||
user = db_session.exec(statement).first()
|
||||
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="User not found",
|
||||
)
|
||||
|
||||
# Activity
|
||||
statement = select(Activity).where(Activity.id == assignment.activity_id)
|
||||
activity = db_session.exec(statement).first()
|
||||
|
||||
if not activity:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Activity not found",
|
||||
)
|
||||
|
||||
# Add TrailStep
|
||||
trail = await check_trail_presence(
|
||||
org_id=course.org_id,
|
||||
user_id=user.id,
|
||||
request=request,
|
||||
user=user,
|
||||
db_session=db_session,
|
||||
)
|
||||
|
||||
statement = select(TrailRun).where(
|
||||
TrailRun.trail_id == trail.id,
|
||||
TrailRun.course_id == course.id,
|
||||
TrailRun.user_id == user.id,
|
||||
)
|
||||
trailrun = db_session.exec(statement).first()
|
||||
|
||||
if not trailrun:
|
||||
trailrun = TrailRun(
|
||||
trail_id=trail.id if trail.id is not None else 0,
|
||||
course_id=course.id if course.id is not None else 0,
|
||||
org_id=course.org_id,
|
||||
user_id=user.id,
|
||||
creation_date=str(datetime.now()),
|
||||
update_date=str(datetime.now()),
|
||||
)
|
||||
db_session.add(trailrun)
|
||||
db_session.commit()
|
||||
db_session.refresh(trailrun)
|
||||
|
||||
statement = select(TrailStep).where(
|
||||
TrailStep.trailrun_id == trailrun.id,
|
||||
TrailStep.activity_id == activity.id,
|
||||
TrailStep.user_id == user.id,
|
||||
)
|
||||
trailstep = db_session.exec(statement).first()
|
||||
|
||||
if not trailstep:
|
||||
trailstep = TrailStep(
|
||||
trailrun_id=trailrun.id if trailrun.id is not None else 0,
|
||||
activity_id=activity.id if activity.id is not None else 0,
|
||||
course_id=course.id if course.id is not None else 0,
|
||||
trail_id=trail.id if trail.id is not None else 0,
|
||||
org_id=course.org_id,
|
||||
complete=True,
|
||||
teacher_verified=False,
|
||||
grade="",
|
||||
user_id=user.id,
|
||||
creation_date=str(datetime.now()),
|
||||
update_date=str(datetime.now()),
|
||||
)
|
||||
db_session.add(trailstep)
|
||||
db_session.commit()
|
||||
db_session.refresh(trailstep)
|
||||
|
||||
# return assignment user submission read
|
||||
return AssignmentUserSubmissionRead.model_validate(assignment_user_submission)
|
||||
|
||||
|
|
@ -1262,14 +1339,24 @@ async def update_assignment_submission(
|
|||
async def delete_assignment_submission(
|
||||
request: Request,
|
||||
user_id: str,
|
||||
assignment_id: str,
|
||||
assignment_uuid: str,
|
||||
current_user: PublicUser | AnonymousUser,
|
||||
db_session: Session,
|
||||
):
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.assignment_uuid == assignment_uuid)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
||||
if not assignment:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
# Check if assignment user submission exists
|
||||
statement = select(AssignmentUserSubmission).where(
|
||||
AssignmentUserSubmission.user_id == user_id,
|
||||
AssignmentUserSubmission.assignment_id == assignment_id,
|
||||
AssignmentUserSubmission.assignment_id == assignment.id,
|
||||
)
|
||||
assignment_user_submission = db_session.exec(statement).first()
|
||||
|
||||
|
|
@ -1279,18 +1366,6 @@ async def delete_assignment_submission(
|
|||
detail="Assignment User Submission not found",
|
||||
)
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(
|
||||
Assignment.id == assignment_user_submission.assignment_id
|
||||
)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
||||
if not assignment:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
# Check if course exists
|
||||
statement = select(Course).where(Course.id == assignment.course_id)
|
||||
course = db_session.exec(statement).first()
|
||||
|
|
@ -1311,6 +1386,197 @@ async def delete_assignment_submission(
|
|||
return {"message": "Assignment User Submission deleted"}
|
||||
|
||||
|
||||
## > Assignments Submissions Grading
|
||||
async def grade_assignment_submission(
|
||||
request: Request,
|
||||
user_id: str,
|
||||
assignment_uuid: str,
|
||||
current_user: PublicUser | AnonymousUser,
|
||||
db_session: Session,
|
||||
):
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.assignment_uuid == assignment_uuid)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
||||
if not assignment:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
# Check if assignment user submission exists
|
||||
statement = select(AssignmentUserSubmission).where(
|
||||
AssignmentUserSubmission.user_id == user_id,
|
||||
AssignmentUserSubmission.assignment_id == assignment.id,
|
||||
)
|
||||
assignment_user_submission = db_session.exec(statement).first()
|
||||
|
||||
if not assignment_user_submission:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment User Submission not found",
|
||||
)
|
||||
|
||||
# Get all the task submissions for the user
|
||||
task_subs = select(AssignmentTaskSubmission).where(
|
||||
AssignmentTaskSubmission.user_id == user_id,
|
||||
AssignmentTaskSubmission.activity_id == assignment.activity_id,
|
||||
)
|
||||
task_submissions = db_session.exec(task_subs).all()
|
||||
|
||||
# Calculate the grade
|
||||
grade = 0
|
||||
for task_submission in task_submissions:
|
||||
grade += task_submission.grade
|
||||
|
||||
# Update the assignment user submission
|
||||
assignment_user_submission.grade = grade
|
||||
|
||||
# Insert Assignment User Submission in DB
|
||||
db_session.add(assignment_user_submission)
|
||||
db_session.commit()
|
||||
db_session.refresh(assignment_user_submission)
|
||||
|
||||
# Change the status of the submission
|
||||
assignment_user_submission.submission_status = AssignmentUserSubmissionStatus.GRADED
|
||||
|
||||
# Insert Assignment User Submission in DB
|
||||
db_session.add(assignment_user_submission)
|
||||
db_session.commit()
|
||||
db_session.refresh(assignment_user_submission)
|
||||
|
||||
# return OK
|
||||
return {
|
||||
"message": "Assignment User Submission graded with the grade of " + str(grade)
|
||||
}
|
||||
|
||||
|
||||
async def get_grade_assignment_submission(
|
||||
request: Request,
|
||||
user_id: str,
|
||||
assignment_uuid: str,
|
||||
current_user: PublicUser | AnonymousUser,
|
||||
db_session: Session,
|
||||
):
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.assignment_uuid == assignment_uuid)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
||||
if not assignment:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
# Check if assignment user submission exists
|
||||
statement = select(AssignmentUserSubmission).where(
|
||||
AssignmentUserSubmission.user_id == user_id,
|
||||
AssignmentUserSubmission.assignment_id == assignment.id,
|
||||
)
|
||||
assignment_user_submission = db_session.exec(statement).first()
|
||||
|
||||
if not assignment_user_submission:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment User Submission not found",
|
||||
)
|
||||
|
||||
# Get the max grade value from the sum of every assignmenttask
|
||||
statement = select(AssignmentTask).where(
|
||||
AssignmentTask.assignment_id == assignment.id
|
||||
)
|
||||
assignment_tasks = db_session.exec(statement).all()
|
||||
max_grade = 0
|
||||
|
||||
for task in assignment_tasks:
|
||||
max_grade += task.max_grade_value
|
||||
|
||||
# Now get the grade from the user submission
|
||||
statement = select(AssignmentUserSubmission).where(
|
||||
AssignmentUserSubmission.user_id == user_id,
|
||||
AssignmentUserSubmission.assignment_id == assignment.id,
|
||||
)
|
||||
assignment_user_submission = db_session.exec(statement).first()
|
||||
|
||||
if not assignment_user_submission:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment User Submission not found",
|
||||
)
|
||||
|
||||
# return the grade
|
||||
return {
|
||||
"grade": int(assignment_user_submission.grade),
|
||||
"max_grade": max_grade,
|
||||
"grading_type": assignment.grading_type,
|
||||
}
|
||||
|
||||
|
||||
async def mark_activity_as_done_for_user(
|
||||
request: Request,
|
||||
user_id: str,
|
||||
assignment_uuid: str,
|
||||
current_user: PublicUser | AnonymousUser,
|
||||
db_session: Session,
|
||||
):
|
||||
# Get Assignment
|
||||
statement = select(Assignment).where(Assignment.assignment_uuid == assignment_uuid)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
||||
if not assignment:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
# Check if activity exists
|
||||
statement = select(Activity).where(Activity.id == assignment.activity_id)
|
||||
activity = db_session.exec(statement).first()
|
||||
|
||||
if not activity:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Activity not found",
|
||||
)
|
||||
|
||||
# Check if user exists
|
||||
statement = select(User).where(User.id == user_id)
|
||||
user = db_session.exec(statement).first()
|
||||
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="User not found",
|
||||
)
|
||||
|
||||
# Check if user is enrolled in the course
|
||||
trailsteps = select(TrailStep).where(
|
||||
TrailStep.activity_id == activity.id,
|
||||
TrailStep.user_id == user_id,
|
||||
)
|
||||
trailstep = db_session.exec(trailsteps).first()
|
||||
|
||||
if not trailstep:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="User not enrolled in the course",
|
||||
)
|
||||
|
||||
# Mark activity as done
|
||||
trailstep.complete = True
|
||||
trailstep.update_date = str(datetime.now())
|
||||
|
||||
# Insert TrailStep in DB
|
||||
db_session.add(trailstep)
|
||||
db_session.commit()
|
||||
db_session.refresh(trailstep)
|
||||
|
||||
# return OK
|
||||
return {"message": "Activity marked as done for user"}
|
||||
|
||||
|
||||
## 🔒 RBAC Utils ##
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ async def add_activity_to_trail(
|
|||
course_id=course.id if course.id is not None else 0,
|
||||
trail_id=trail.id if trail.id is not None else 0,
|
||||
org_id=course.org_id,
|
||||
complete=False,
|
||||
complete=True,
|
||||
teacher_verified=False,
|
||||
grade="",
|
||||
user_id=user.id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue