Skip to content

Commit

Permalink
Merge pull request openedx#34441 from openedx/hajorg/au-1945-course-r…
Browse files Browse the repository at this point in the history
…eset-clear-grades

feat: add clear grades to course reset task
  • Loading branch information
hajorg authored Mar 28, 2024
2 parents 68c3e24 + 7fc2f57 commit 19d6c0c
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 3 deletions.
3 changes: 3 additions & 0 deletions lms/djangoapps/support/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from lms.djangoapps.courseware.models import StudentModule
from lms.djangoapps.instructor.enrollment import reset_student_attempts
from lms.djangoapps.support.models import CourseResetAudit
from lms.djangoapps.grades.api import clear_user_course_grades

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -67,6 +68,8 @@ def reset_student_course(course_id, learner_email, reset_by_user_email):

# Clear block completion data
BlockCompletion.objects.clear_learning_context_completion(user, course.id)
# Clear a student grades for a course
clear_user_course_grades(user.id, course.id)

update_audit_status(course_reset_audit, CourseResetAudit.CourseResetStatus.COMPLETE)
except Exception as e: # pylint: disable=broad-except
Expand Down
9 changes: 9 additions & 0 deletions lms/djangoapps/support/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ def setUp(self):
self.mock_block_completion = completion_patcher.start()
self.addCleanup(completion_patcher.stop)

# Patch clear_user_course_grades for the whole test
grades_patcher = patch('lms.djangoapps.support.tasks.clear_user_course_grades')
self.mock_clear_user_course_grades = grades_patcher.start()
self.addCleanup(grades_patcher.stop)

@property
def mock_clear_block_completion(self):
""" Helper property to access the two-mock-layers-deep clear_learning_context_completion """
Expand Down Expand Up @@ -144,6 +149,7 @@ def test_reset_student_course(self):
])

self.mock_clear_block_completion.assert_called_once_with(self.student_user, self.course.id)
self.mock_clear_user_course_grades.assert_called_once_with(self.student_user.id, self.course.id)
course_reset_audit = CourseResetAudit.objects.get(course_enrollment=self.enrollment)
self.assertIsNotNone(course_reset_audit.completed_at)
self.assertEqual(course_reset_audit.status, CourseResetAudit.CourseResetStatus.COMPLETE)
Expand Down Expand Up @@ -181,6 +187,7 @@ def test_reset_student_course_student_module_not_found(self):
])

self.mock_clear_block_completion.assert_called_once_with(self.student_user, self.course.id)
self.mock_clear_user_course_grades.assert_called_once_with(self.student_user.id, self.course.id)
course_reset_audit = CourseResetAudit.objects.get(course_enrollment=self.enrollment)
self.assertRaises(StudentModule.DoesNotExist, mock_reset_student_attempts)
self.assertIsNotNone(course_reset_audit.completed_at)
Expand All @@ -195,6 +202,7 @@ def test_reset_student_course_fail(self, mock_reset_student_attempts):
reset_student_course(self.course_id, self.student_user.email, self.user.email)
mock_reset_student_attempts.assert_not_called()
self.mock_clear_block_completion.assert_not_called()
self.mock_clear_user_course_grades.assert_not_called()
course_reset_audit = CourseResetAudit.objects.get(course_enrollment=self.enrollment)
self.assertIsNone(course_reset_audit.completed_at)
self.assertEqual(course_reset_audit.status, CourseResetAudit.CourseResetStatus.FAILED)
Expand All @@ -208,6 +216,7 @@ def test_reset_student_attempts_raise_exception(self):
reset_student_course(self.course_id, self.student_user.email, self.user.email)
mock_reset_student_attempts.assert_called_once()
self.mock_clear_block_completion.assert_not_called()
self.mock_clear_user_course_grades.assert_not_called()
course_reset_audit = CourseResetAudit.objects.get(course_enrollment=self.enrollment)
self.assertIsNone(course_reset_audit.completed_at)
self.assertEqual(course_reset_audit.status, CourseResetAudit.CourseResetStatus.FAILED)
4 changes: 2 additions & 2 deletions lms/djangoapps/support/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2428,7 +2428,7 @@ def test_learner_course_reset(self, mock_reset_student_course):
'display_name': self.course.display_name
})
# The reset task should be queued
mock_reset_student_course.delay.assert_called_once_with(self.course_id, self.learner.id, self.user.id)
mock_reset_student_course.delay.assert_called_once_with(self.course_id, self.learner.email, self.user.email)
# And an audit should be created as ENQUEUED
self.assertEqual(
self.enrollment.courseresetaudit_set.first().status,
Expand All @@ -2453,7 +2453,7 @@ def test_course_reset_failed(self, mock_reset_student_course):
'comment': '',
'display_name': self.course.display_name
})
mock_reset_student_course.delay.assert_called_once_with(self.course_id, self.learner.id, self.user.id)
mock_reset_student_course.delay.assert_called_once_with(self.course_id, self.learner.email, self.user.email)

def test_course_reset_already_reset(self):
""" A course that has an audit that hasn't failed should not be allowed to be run again """
Expand Down
2 changes: 1 addition & 1 deletion lms/djangoapps/support/views/course_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,5 @@ def post(self, request, username_or_email):
'display_name': course_enrollment.course_overview.display_name
}

reset_student_course.delay(course_id, user.id, request.user.id)
reset_student_course.delay(course_id, user.email, request.user.email)
return Response(resp, status=201)

0 comments on commit 19d6c0c

Please sign in to comment.