Skip to content

Commit

Permalink
Merge pull request #604 from edx/matthugs/pass-through-reviewer-as-ov…
Browse files Browse the repository at this point in the history
…errider-of-grade

Pass through reviewer for grade override attribution purposes
  • Loading branch information
Matt Hughes authored Sep 27, 2019
2 parents 70eabef + e247740 commit ec890e5
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 7 deletions.
2 changes: 1 addition & 1 deletion edx_proctoring/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
from __future__ import absolute_import

# Be sure to update the version number in edx_proctoring/package.json
__version__ = '2.0.9'
__version__ = '2.1.0'

default_app_config = 'edx_proctoring.apps.EdxProctoringConfig' # pylint: disable=invalid-name
12 changes: 9 additions & 3 deletions edx_proctoring/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,8 @@ def mark_exam_attempt_as_ready(exam_id, user_id):


def update_attempt_status(exam_id, user_id, to_status,
raise_if_not_found=True, cascade_effects=True, timeout_timestamp=None):
raise_if_not_found=True, cascade_effects=True, timeout_timestamp=None,
update_attributable_to=None):
"""
Internal helper to handle state transitions of attempt status
"""
Expand Down Expand Up @@ -909,6 +910,8 @@ def update_attempt_status(exam_id, user_id, to_status,
cascade_effects=False
)

backend = get_backend_provider(exam)

if ProctoredExamStudentAttemptStatus.needs_grade_override(to_status):
grades_service = get_runtime_service('grades')

Expand All @@ -933,7 +936,11 @@ def update_attempt_status(exam_id, user_id, to_status,
course_key_or_id=exam['course_id'],
usage_key_or_id=exam_attempt_obj.proctored_exam.content_id,
earned_all=REJECTED_GRADE_OVERRIDE_EARNED,
earned_graded=REJECTED_GRADE_OVERRIDE_EARNED
earned_graded=REJECTED_GRADE_OVERRIDE_EARNED,
overrider=update_attributable_to,
comment=('Failed {backend} proctoring'.format(backend=backend.verbose_name)
if backend
else 'Failed Proctoring')
)

certificates_service = get_runtime_service('certificates')
Expand Down Expand Up @@ -1010,7 +1017,6 @@ def update_attempt_status(exam_id, user_id, to_status,
attempt = get_exam_attempt(exam_id, user_id)

# call back to the backend to register the end of the exam, if necessary
backend = get_backend_provider(exam)
if backend:
# When onboarding exams change state to a completed status,
# look up any exams in the onboarding error states, and delete them.
Expand Down
3 changes: 2 additions & 1 deletion edx_proctoring/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ def finish_review_workflow(sender, instance, signal, **kwargs): # pylint: disab
attempt['proctored_exam']['id'],
attempt['user']['id'],
attempt_status,
raise_if_not_found=False
raise_if_not_found=False,
update_attributable_to=review.reviewed_by or None
)

# emit an event for 'review_received'
Expand Down
37 changes: 37 additions & 0 deletions edx_proctoring/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,43 @@ def test_grade_override(self):
'earned_graded': 5.0
})

def test_grade_overrider(self):
"""
Check we pass along the overrider appropriately, as one would when a rejection-worthy review comes in
"""
grades_service = MockGradesService()
grades_service.override_subsection_grade = MagicMock()
set_runtime_service('grades', grades_service)
exam_attempt = self._create_started_exam_attempt()
update_attempt_status(
exam_attempt.proctored_exam_id,
self.user.id,
ProctoredExamStudentAttemptStatus.rejected,
update_attributable_to=self.user
)

assert grades_service.override_subsection_grade.called
# did we pass the user to whom we're attributing the override along?
assert grades_service.override_subsection_grade.call_args[1]['overrider'].id == self.user.id

def test_grade_override_comment(self):
"""
Check we pass along the backend of the exam for which something failed
"""
grades_service = MockGradesService()
grades_service.override_subsection_grade = MagicMock()
set_runtime_service('grades', grades_service)
exam_attempt = self._create_started_exam_attempt()
update_attempt_status(
exam_attempt.proctored_exam_id,
self.user.id,
ProctoredExamStudentAttemptStatus.rejected
)

assert grades_service.override_subsection_grade.called
# did we pass a comment referring to our backend?
assert "Unknown" in grades_service.override_subsection_grade.call_args[1]['comment']

def test_disabled_grade_override(self):
"""
Verify that when the REJECTED_EXAM_OVERRIDES_GRADE flag is disabled for a course,
Expand Down
2 changes: 1 addition & 1 deletion edx_proctoring/tests/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def get_subsection_grade_override(self, user_id, course_key_or_id, usage_key_or_
return self.overrides.get(key)

def override_subsection_grade(self, user_id, course_key_or_id, usage_key_or_id, earned_all=None,
earned_graded=None):
earned_graded=None, overrider=None, comment=None):
"""Sets grade override earned points for key (user_id + course_key + subsection)"""
key = (user_id, course_key_or_id, usage_key_or_id)
self.overrides[key] = MockGradeOverride(
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@edx/edx-proctoring",
"//": "Be sure to update the version number in edx_proctoring/__init__.py",
"//": "Note that the version format is slightly different than that of the Python version when using prereleases.",
"version": "2.0.9",
"version": "2.1.0",
"main": "edx_proctoring/static/index.js",
"repository": {
"type": "git",
Expand Down

0 comments on commit ec890e5

Please sign in to comment.