Commit 571802ef by Hasnain

Added API to get the student's course completion date and test for coverage

parent f2cc8597
......@@ -1054,6 +1054,23 @@ def get_filtered_exam_attempts(course_id, search_by):
return [ProctoredExamStudentAttemptSerializer(active_exam).data for active_exam in exam_attempts]
def get_last_exam_completion_date(course_id, username):
"""
return the completion date of last proctoring exam for the given course and username if
all the proctored exams are attempted and completed otherwise None
"""
exam_attempts = ProctoredExamStudentAttempt.objects.get_proctored_exam_attempts(course_id, username)
proctored_exams_count = ProctoredExam.get_all_exams_for_course(course_id, proctored_exams_only=True).count()
are_all_exams_attempted = len(exam_attempts) == proctored_exams_count
if are_all_exams_attempted:
for attempt in exam_attempts:
if not attempt.completed_at:
return None
# Last proctored exam will be at first index, because attempts are sorted descending on completed_at
return exam_attempts[0].completed_at if exam_attempts and are_all_exams_attempted else None
def get_active_exams_for_user(user_id, course_id=None):
"""
This method will return a list of active exams for the user,
......
......@@ -91,7 +91,8 @@ class ProctoredExam(TimeStampedModel):
return proctored_exam
@classmethod
def get_all_exams_for_course(cls, course_id, active_only=False, timed_exams_only=False):
def get_all_exams_for_course(cls, course_id, active_only=False, timed_exams_only=False,
proctored_exams_only=False):
"""
Returns all exams for a give course
"""
......@@ -101,6 +102,8 @@ class ProctoredExam(TimeStampedModel):
filtered_query = filtered_query & Q(is_active=True)
if timed_exams_only:
filtered_query = filtered_query & Q(is_proctored=False)
if proctored_exams_only:
filtered_query = filtered_query & Q(is_proctored=True) & Q(is_practice_exam=False)
return cls.objects.filter(filtered_query)
......@@ -394,6 +397,17 @@ class ProctoredExamStudentAttemptManager(models.Manager):
return self.filter(filtered_query).order_by('-created') # pylint: disable=no-member
def get_proctored_exam_attempts(self, course_id, username):
"""
Returns the Student's Proctored Exam Attempts for the given course_id.
"""
return self.filter(
proctored_exam__course_id=course_id,
user__username=username,
taking_as_proctored=True,
is_sample_attempt=False,
).order_by('-completed_at')
def get_active_student_attempts(self, user_id, course_id=None):
"""
Returns the active student exams (user in-progress exams)
......
......@@ -31,6 +31,7 @@ from edx_proctoring.api import (
remove_exam_attempt,
get_all_exam_attempts,
get_filtered_exam_attempts,
get_last_exam_completion_date,
mark_exam_attempt_timeout,
mark_exam_attempt_as_ready,
update_attempt_status,
......@@ -276,6 +277,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
"""
return create_exam(
course_id=self.course_id,
is_proctored=False,
content_id=self.disabled_content_id,
exam_name=self.exam_name,
time_limit_mins=self.default_time_limit,
......@@ -590,7 +592,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.assertEqual(timed_exam['exam_name'], self.exam_name)
exams = get_all_exams_for_course(self.course_id, True)
self.assertEqual(len(exams), 1)
self.assertEqual(len(exams), 2)
def test_get_invalid_proctored_exam(self):
"""
......@@ -962,6 +964,24 @@ class ProctoredExamApiTests(LoggedInTestCase):
self.assertEqual(filtered_attempts[0]['id'], new_exam_attempt)
self.assertEqual(filtered_attempts[1]['id'], exam_attempt.id)
def test_get_last_exam_completion_date_when_course_is_incomplete(self):
"""
Test to get the last proctored exam's completion date when course is not complete
"""
self._create_started_exam_attempt()
completion_date = get_last_exam_completion_date(self.course_id, self.user.username)
self.assertIsNone(completion_date)
def test_get_last_exam_completion_date_when_course_is_complete(self):
"""
Test to get the last proctored exam's completion date when course is complete
"""
exam_attempt = self._create_started_exam_attempt()
exam_attempt.completed_at = datetime.now(pytz.UTC)
exam_attempt.save()
completion_date = get_last_exam_completion_date(self.course_id, self.user.username)
self.assertIsNotNone(completion_date)
def test_get_all_exam_attempts(self):
"""
Test to get all the exam attempts.
......
......@@ -34,7 +34,7 @@ def load_requirements(*requirements_paths):
setup(
name='edx-proctoring',
version='0.12.8',
version='0.12.9',
description='Proctoring subsystem for Open edX',
long_description=open('README.md').read(),
author='edX',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment