Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-proctoring
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-proctoring
Commits
74db30f6
Commit
74db30f6
authored
Feb 11, 2016
by
Douglas Hall
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #269 from edx/hasnain-naveed/PHX-244
PHX-244 / Added API to get the student's course completion date
parents
61a45253
571802ef
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
54 additions
and
3 deletions
+54
-3
edx_proctoring/api.py
+17
-0
edx_proctoring/models.py
+15
-1
edx_proctoring/tests/test_api.py
+21
-1
setup.py
+1
-1
No files found.
edx_proctoring/api.py
View file @
74db30f6
...
...
@@ -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,
...
...
edx_proctoring/models.py
View file @
74db30f6
...
...
@@ -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)
...
...
edx_proctoring/tests/test_api.py
View file @
74db30f6
...
...
@@ -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.
...
...
setup.py
View file @
74db30f6
...
...
@@ -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'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment