Skip to content

Commit

Permalink
Sort unassessed exercises by most recent submission
Browse files Browse the repository at this point in the history
Fixes #1110
  • Loading branch information
EerikSaksi authored and markkuriekkinen committed May 30, 2023
1 parent a250bdb commit 0a5d7f5
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 16 deletions.
47 changes: 31 additions & 16 deletions exercise/staff_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.validators import URLValidator
from django.db.models import Count, Max, Prefetch, Q
from django.db.models import Count, Max, Prefetch, Q, F
from django.http.request import HttpRequest
from django.http.response import HttpResponse, JsonResponse, Http404
from django.shortcuts import get_object_or_404
Expand Down Expand Up @@ -324,27 +324,42 @@ class NextUnassessedSubmitterView(ExerciseBaseView, BaseRedirectView):
access_mode = ACCESS.ASSISTANT

def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
# Query submitters who have not been assessed yet.
submitter = None
submitters = (UserProfile.objects
.filter(submissions__exercise=self.exercise)
.annotate(
count_assessed=Count(
'submissions__id',
filter=(Q(submissions__grader__isnull=False)),
),
)
.filter(count_assessed=0)
.order_by('id'))

# submissions for this exercise
submissions = Submission.objects.filter(exercise=self.exercise)

# filter only the latest submissions
submissions = (submissions.annotate(latest=Max('submission_time'))
.filter(submission_time=F('latest'))
.order_by('latest'))

previous_user_id = request.GET.get('prev')
previous_submission_time = None

# if we had a previous user then we need to find their submission time before we filter already assessed users.
if previous_user_id:
# Find specifically the submitter AFTER the previously inspected one.
submitters_after = submitters.filter(id__gt=previous_user_id)
submitter = submitters_after.first()
previous_submission_time = submissions.filter(submitters__id=previous_user_id).first().submission_time

# filter users who's have submissions that have been assessed
submissions = (submissions.annotate(
count_assessed=Count(
'id',
filter=(Q(grader__isnull=False)),
),
)
.filter(count_assessed=0))

# if we had a previous time then try find the next submitter after this time
if previous_submission_time:
submission = submissions.filter(submission_time__gt=previous_submission_time).first()
if submission:
submitter = submission.submitters.first()

# if we don't have one just take the first submitter
if not submitter:
submitter = submitters.first()
if submissions.first():
submitter = submissions.first().submitters.first()

if not submitter:
# There are no more unassessed submitters.
Expand Down
83 changes: 83 additions & 0 deletions exercise/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1349,3 +1349,86 @@ def test_enrollment_questionaire_opening_time(self):
self.enrollment_exercise.check_submission_allowed(self.user.userprofile)[0],
BaseExercise.SUBMIT_STATUS.CANNOT_ENROLL,
)

def test_next_unassessed_submitter_view(self):
# parses the user ID from the URL response of NextUnassessedSubmitterView
def get_url_user_id(args=''):
response = self.client.get(
f"{exercise.get_absolute_url()}submitters/next-unassessed/{args}")

return int(response.url.split('/submissions/')[1].split('/inspect/')[0])

self.client.login(username="staff", password="staffPassword")

exercise = BaseExercise.objects.create(
order=10,
name="Unassessed Exercise Submitter View",
course_module=self.course_module,
category=self.learning_object_category,
url="unassessed",
max_submissions=1,
)
exercise.save()

user_submission = Submission.objects.create(
exercise=exercise,
)
user_submission.submitters.add(self.user.userprofile)
user_submission.submission_time = self.tomorrow
user_submission.save()

user2_submission = Submission.objects.create(
exercise=exercise,
)
user2_submission.submitters.add(self.user2.userprofile)
user2_submission.submission_time = self.two_days_from_now
user2_submission.save()

# user submission day before user2
self.assertEqual(user_submission.id, get_url_user_id())
self.assertEqual(user2_submission.id,
get_url_user_id(f"?prev={self.user.id}"))

user_submission.submission_time = self.three_days_from_now
user_submission.save()

# now user2 submission is earlier
self.assertEqual(user2_submission.id, get_url_user_id())


# we should now expect to get user1's submission first since user2s earlier submission has been graded
user2_submission.grader = self.teacher.userprofile
user2_submission.save()
self.assertEqual(user_submission.id, get_url_user_id())

# test with prev parameter
self.assertEqual(user_submission.id, get_url_user_id(f"?prev={self.user2.id}"))

# remove grader for further tests
user2_submission.grader = None
user2_submission.save()

# create a submission for user so the newest submission was made by user again and not user2
user_earlier_submission = Submission.objects.create(
exercise=exercise,
)
user_earlier_submission.submitters.add(self.user.userprofile)
user_earlier_submission.submission_time = self.today
user_earlier_submission.save()

self.assertEqual(user_submission.id, get_url_user_id())

user2_other_exercise_submission = Submission.objects.create(
exercise=self.base_exercise,
)
user2_other_exercise_submission.submitters.add(self.user.userprofile)
user2_other_exercise_submission.submission_time = self.yesterday
user2_other_exercise_submission.save()

# an even earlier submission in another exercise doesn't matter
self.assertEqual(user_submission.id, get_url_user_id())

# we should now expect user2's submission to be shown because one of user1's submissions has been graded
user_earlier_submission.grader = self.teacher.userprofile
user_earlier_submission.save()
self.assertEqual(user2_submission.id, get_url_user_id())

0 comments on commit 0a5d7f5

Please sign in to comment.