Merge pull request #18436 from edx/noraiz/EDUCATOR-2773

add delay in score recalculation on enrollment update
This commit is contained in:
Noraiz Anwar
2018-06-25 22:06:30 +05:00
committed by GitHub
3 changed files with 50 additions and 3 deletions

View File

@@ -103,6 +103,7 @@ UNENROLLED_TO_ENROLLED = 'from unenrolled to enrolled'
ALLOWEDTOENROLL_TO_UNENROLLED = 'from allowed to enroll to enrolled'
UNENROLLED_TO_UNENROLLED = 'from unenrolled to unenrolled'
DEFAULT_TRANSITION_STATE = 'N/A'
SCORE_RECALCULATION_DELAY_ON_ENROLLMENT_UPDATE = 30
TRANSITION_STATES = (
(UNENROLLED_TO_ALLOWEDTOENROLL, UNENROLLED_TO_ALLOWEDTOENROLL),
@@ -1342,7 +1343,15 @@ class CourseEnrollment(models.Model):
# Only emit mode change events when the user's enrollment
# mode has changed from its previous setting
self.emit_event(EVENT_NAME_ENROLLMENT_MODE_CHANGED)
ENROLLMENT_TRACK_UPDATED.send(sender=None, user=self.user, course_key=self.course_id)
# this signal is meant to trigger a score recalculation celery task,
# `countdown` is added to celery task as delay so that cohort is duly updated
# before starting score recalculation
ENROLLMENT_TRACK_UPDATED.send(
sender=None,
user=self.user,
course_key=self.course_id,
countdown=SCORE_RECALCULATION_DELAY_ON_ENROLLMENT_UPDATE
)
def send_signal(self, event, cost=None, currency=None):
"""

View File

@@ -12,7 +12,13 @@ from nose.plugins.attrib import attr
from course_modes.models import CourseMode
from course_modes.tests.factories import CourseModeFactory
from openedx.core.djangoapps.embargo.test_utils import restrict_course
from student.models import CourseEnrollment, CourseEnrollmentAllowed, CourseFullError, EnrollmentClosedError
from student.models import (
CourseEnrollment,
CourseEnrollmentAllowed,
CourseFullError,
EnrollmentClosedError,
SCORE_RECALCULATION_DELAY_ON_ENROLLMENT_UPDATE,
)
from student.roles import CourseInstructorRole, CourseStaffRole
from student.tests.factories import CourseEnrollmentAllowedFactory, UserFactory
from util.testing import UrlResetMixin
@@ -340,3 +346,34 @@ class EnrollmentTest(UrlResetMixin, SharedModuleStoreTestCase):
# Still same
cea.refresh_from_db()
self.assertEqual(cea.user, user1)
def test_score_recalculation_on_enrollment_update(self):
"""
Test that an update in enrollment cause score recalculation.
Note:
Score recalculation task must be called with a delay of SCORE_RECALCULATION_DELAY_ON_ENROLLMENT_UPDATE
"""
course_modes = ['verified', 'audit']
for mode_slug in course_modes:
CourseModeFactory.create(
course_id=self.course.id,
mode_slug=mode_slug,
mode_display_name=mode_slug,
)
CourseEnrollment.enroll(self.user, self.course.id, mode="audit")
local_task_args = dict(
user_id=self.user.id,
course_key=str(self.course.id)
)
with patch(
'lms.djangoapps.grades.tasks.recalculate_course_and_subsection_grades_for_user.apply_async',
return_value=None
) as mock_task_apply:
CourseEnrollment.enroll(self.user, self.course.id, mode="verified")
mock_task_apply.assert_called_once_with(
countdown=SCORE_RECALCULATION_DELAY_ON_ENROLLMENT_UPDATE,
kwargs=local_task_args
)

View File

@@ -241,12 +241,13 @@ def recalculate_course_grade_only(sender, course, course_structure, user, **kwar
@receiver(ENROLLMENT_TRACK_UPDATED)
@receiver(COHORT_MEMBERSHIP_UPDATED)
def recalculate_course_and_subsection_grades(sender, user, course_key, **kwargs):
def recalculate_course_and_subsection_grades(sender, user, course_key, countdown=None, **kwargs): # pylint: disable=unused-argument
"""
Updates a saved course grade, forcing the subsection grades
from which it is calculated to update along the way.
"""
recalculate_course_and_subsection_grades_for_user.apply_async(
countdown=countdown,
kwargs=dict(
user_id=user.id,
course_key=six.text_type(course_key)