Skip to content

Commit

Permalink
feat: add grades event bus event handler for rejected special exam
Browse files Browse the repository at this point in the history
This commit adds an event bus event handler to the grades application. This event handler handles the EXAM_ATTEMPT_REJECTED Open edX event,
 which is emitted when a learner's exam attempt is rejected. The event handler creates a subsection grade override, overriding the grade to
 0.0.
  • Loading branch information
michaelroytman committed Oct 5, 2023
1 parent db25297 commit b4cb93e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
27 changes: 26 additions & 1 deletion lms/djangoapps/grades/signals/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from django.dispatch import receiver
from opaque_keys.edx.keys import LearningContextKey
from openedx_events.learning.signals import EXAM_ATTEMPT_VERIFIED
from openedx_events.learning.signals import EXAM_ATTEMPT_REJECTED, EXAM_ATTEMPT_VERIFIED
from submissions.models import score_reset, score_set
from xblock.scorable import ScorableXBlockMixin, Score

Expand Down Expand Up @@ -322,3 +322,28 @@ def exam_attempt_verified_event_handler(sender, signal, **kwargs): # pylint: di

if should_override_grade_on_rejected_exam(course_key):
undo_override_subsection_grade(user_data.id, course_key, usage_key, GradeOverrideFeatureEnum.proctoring)


@receiver(EXAM_ATTEMPT_REJECTED)
def exam_attempt_rejected_event_handler(sender, signal, **kwargs): # pylint: disable=unused-argument
"""
Consume `EXAM_ATTEMPT_REJECTED` events from the event bus. This will trigger a subsection override.
"""
from ..api import override_subsection_grade

event_data = kwargs.get('exam_attempt')
override_grade_value = 0.0
user_data = event_data.student_user
course_key = event_data.course_key
usage_key = event_data.usage_key

override_subsection_grade(
user_data.id,
course_key,
usage_key,
earned_all=override_grade_value,
earned_graded=override_grade_value,
feature=GradeOverrideFeatureEnum.proctoring,
overrider=None,
comment=None,
)
34 changes: 32 additions & 2 deletions lms/djangoapps/grades/tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
from opaque_keys.edx.keys import CourseKey, UsageKey
from openedx_events.data import EventsMetadata
from openedx_events.learning.data import ExamAttemptData, UserData, UserPersonalData
from openedx_events.learning.signals import EXAM_ATTEMPT_VERIFIED
from openedx_events.learning.signals import EXAM_ATTEMPT_REJECTED, EXAM_ATTEMPT_VERIFIED

from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.grades.signals.handlers import exam_attempt_verified_event_handler
from lms.djangoapps.grades.signals.handlers import (
exam_attempt_rejected_event_handler,
exam_attempt_verified_event_handler
)
from ..constants import GradeOverrideFeatureEnum


Expand Down Expand Up @@ -101,3 +104,30 @@ def test_exam_attempt_verified_event_handler(self, override_enabled, mock_undo_o
)
else:
mock_undo_override.assert_not_called()

@mock.patch('lms.djangoapps.grades.api.override_subsection_grade')
def test_exam_attempt_rejected_event_handler(self, mock_override):
exam_event_data = self._get_exam_event_data(self.student_user,
self.course_key,
self.usage_key,
exam_type='proctored')
event_metadata = self._get_exam_event_metadata(EXAM_ATTEMPT_REJECTED)

event_kwargs = {
'exam_attempt': exam_event_data,
'metadata': event_metadata
}
exam_attempt_rejected_event_handler(None, EXAM_ATTEMPT_REJECTED, ** event_kwargs)

override_grade_value = 0.0

mock_override.assert_called_once_with(
self.student_user.id,
self.course_key,
self.usage_key,
earned_all=override_grade_value,
earned_graded=override_grade_value,
feature=GradeOverrideFeatureEnum.proctoring,
overrider=None,
comment=None,
)

0 comments on commit b4cb93e

Please sign in to comment.