def test_freeze_user_final_grade_error3(self, raise_on_exception, mock_refr, mock_get_fg): """ Test for freeze_user_final_grade function in case of problems with getting the final grade """ mock_get_fg.side_effect = AttributeError if not raise_on_exception: final_grade = api.freeze_user_final_grade( self.user, self.run_fa, raise_on_exception=raise_on_exception) assert final_grade is None else: with self.assertRaises(FreezeGradeFailedException): api.freeze_user_final_grade( self.user, self.run_fa, raise_on_exception=raise_on_exception) mock_refr.assert_called_once_with(self.user) mock_get_fg.assert_called_once_with(self.user, self.run_fa) assert FinalGrade.objects.filter( user=self.user, course_run=self.run_fa).exists() is False con = get_redis_connection("redis") failed_users_cache_key = api.CACHE_KEY_FAILED_USERS_BASE_STR.format( self.run_fa.edx_course_key) failed_users_count = con.llen(failed_users_cache_key) failed_users_list = list( map(int, con.lrange(failed_users_cache_key, 0, failed_users_count))) assert self.user.id in failed_users_list
def test_freeze_user_final_grade_error1_improperly_configured(self, raise_on_exception, mock_refr, mock_get_fg): """ Test for freeze_user_final_grade function in case of problems with can_freeze_grades """ # case without freeze date with self.assertRaises(ImproperlyConfigured): api.freeze_user_final_grade(self.user, self.run_fa_with_cert, raise_on_exception=raise_on_exception) assert mock_refr.called is False assert mock_get_fg.called is False assert FinalGrade.objects.filter(user=self.user, course_run=self.run_fa_with_cert).exists() is False
def test_freeze_user_final_grade_error1(self, raise_on_exception, mock_refr, mock_get_fg): """ Test for freeze_user_final_grade function in case of problems with can_freeze_grades """ # case not ready to be frozen because the freeze date is in the future if not raise_on_exception: final_grade = api.freeze_user_final_grade( self.user, self.run_no_fa, raise_on_exception=raise_on_exception) assert final_grade is None else: with self.assertRaises(FreezeGradeFailedException): api.freeze_user_final_grade( self.user, self.run_no_fa, raise_on_exception=raise_on_exception) assert mock_refr.called is False assert mock_get_fg.called is False assert FinalGrade.objects.filter(user=self.user, course_run=self.run_no_fa).exists() is False
def get_final_grade(mmtrack, course_run): """ returns final grade if available otherwise freezes the grade. Args: course_run (CourseRun): a course run mmtrack (dashboard.utils.MMTrack): a instance of all user information about a program Returns: final_grade: an object representing the FinalGrade """ try: final_grade = mmtrack.get_required_final_grade( course_run.edx_course_key) except FinalGrade.DoesNotExist: # this is a very special case that happens if the user has logged in # for the first time after we have already frozen the final grades log.warning( 'The user "%s" doesn\'t have a final grade for the course run "%s" ' 'but the course run has already been frozen. Trying to freeze the user now.', mmtrack.user.username, course_run.edx_course_key, ) final_grade = api.freeze_user_final_grade(mmtrack.user, course_run, raise_on_exception=True) return final_grade
def get_final_grade(mmtrack, course_run): """ returns final grade if available otherwise freezes the grade. Args: course_run (CourseRun): a course run mmtrack (dashboard.utils.MMTrack): a instance of all user information about a program Returns: final_grade: an object representing the FinalGrade """ try: final_grade = mmtrack.get_required_final_grade(course_run.edx_course_key) except FinalGrade.DoesNotExist: # this is a very special case that happens if the user has logged in # for the first time after we have already frozen the final grades log.warning( 'The user "%s" doesn\'t have a final grade for the course run "%s" ' 'but the course run has already been frozen. Trying to freeze the user now.', mmtrack.user.username, course_run.edx_course_key, ) final_grade = api.freeze_user_final_grade(mmtrack.user, course_run, raise_on_exception=True) return final_grade
def test_freeze_user_final_grade_multiple_calls(self, mock_refr): """ Test for freeze_user_final_grade function in case it is called multiple times """ fg_qset = FinalGrade.objects.filter(user=self.user, course_run=self.run_fa) assert fg_qset.count() == 0 # first call final_grade = api.freeze_user_final_grade(self.user, self.run_fa) assert final_grade is not None mock_refr.assert_called_once_with(self.user) assert fg_qset.count() == 1 # second call final_grade = api.freeze_user_final_grade(self.user, self.run_fa) assert final_grade is not None assert mock_refr.call_count == 2 assert fg_qset.count() == 1
def test_freeze_user_final_grade_error3(self, raise_on_exception, mock_refr, mock_get_fg): """ Test for freeze_user_final_grade function in case of problems with getting the final grade """ mock_get_fg.side_effect = AttributeError if not raise_on_exception: final_grade = api.freeze_user_final_grade(self.user, self.run_fa, raise_on_exception=raise_on_exception) assert final_grade is None else: with self.assertRaises(FreezeGradeFailedException): api.freeze_user_final_grade(self.user, self.run_fa, raise_on_exception=raise_on_exception) mock_refr.assert_called_once_with(self.user) mock_get_fg.assert_called_once_with(self.user, self.run_fa) assert FinalGrade.objects.filter(user=self.user, course_run=self.run_fa).exists() is False con = get_redis_connection("redis") failed_users_cache_key = api.CACHE_KEY_FAILED_USERS_BASE_STR.format(self.run_fa.edx_course_key) failed_users_count = con.llen(failed_users_cache_key) failed_users_list = list(map(int, con.lrange(failed_users_cache_key, 0, failed_users_count))) assert self.user.id in failed_users_list
def freeze_users_final_grade_async(user_ids, course_run_id): """ Async task to freeze the final grade in a course run for a list of users. Args: user_ids (list): a list of django user ids course_run_id (int): a course run id Returns: None """ # pylint: disable=bare-except course_run = CourseRun.objects.get(id=course_run_id) for user in User.objects.filter(id__in=user_ids): try: api.freeze_user_final_grade(user, course_run) except: log.exception( 'Impossible to freeze final grade for user "%s" in course %s', user.username, course_run.edx_course_key)
def freeze_users_final_grade_async(user_ids, course_run_id): """ Async task to freeze the final grade in a course run for a list of users. Args: user_ids (list): a list of django user ids course_run_id (int): a course run id Returns: None """ # pylint: disable=bare-except course_run = CourseRun.objects.get(id=course_run_id) for user in User.objects.filter(id__in=user_ids): try: api.freeze_user_final_grade(user, course_run) except: log.exception( 'Impossible to freeze final grade for user "%s" in course %s', user.username, course_run.edx_course_key )
def test_freeze_user_final_grade(self, mock_refr): """ Test for happy path for freeze_user_final_grade function """ final_grade = api.freeze_user_final_grade(self.user, self.run_fa) assert final_grade is not None mock_refr.assert_called_once_with(self.user) fg_qset = FinalGrade.objects.filter(user=self.user, course_run=self.run_fa) assert fg_qset.exists() is True fg_status = fg_qset.first() assert fg_status.status == FinalGradeStatus.COMPLETE assert fg_status.user == self.user assert fg_status.course_run == self.run_fa assert fg_status.grade == final_grade.grade assert fg_status.passed == final_grade.passed
def get_status_for_courserun(course_run, mmtrack): # pylint: disable=too-many-return-statements """ Checks the status of a course run for a user given her enrollments Args: course_run (CourseRun): a course run mmtrack (dashboard.utils.MMTrack): a instance of all user information about a program Returns: CourseRunUserStatus: an object representing the run status for the user """ if mmtrack.has_paid_final_grade(course_run.edx_course_key): return CourseRunUserStatus(CourseRunStatus.CHECK_IF_PASSED, course_run) elif mmtrack.has_final_grade(course_run.edx_course_key): if course_run.is_upgradable: final_grade = get_final_grade(mmtrack, course_run) if final_grade.passed: return CourseRunUserStatus(CourseRunStatus.CAN_UPGRADE, course_run) else: return CourseRunUserStatus(CourseRunStatus.NOT_PASSED, course_run) else: return CourseRunUserStatus(CourseRunStatus.MISSED_DEADLINE, course_run) elif not mmtrack.is_enrolled(course_run.edx_course_key): if mmtrack.has_paid(course_run.edx_course_key): return CourseRunUserStatus(CourseRunStatus.PAID_BUT_NOT_ENROLLED, course_run) return CourseRunUserStatus(CourseRunStatus.NOT_ENROLLED, course_run) status = None if mmtrack.is_enrolled_mmtrack(course_run.edx_course_key): if course_run.is_current: status = CourseRunStatus.CURRENTLY_ENROLLED elif course_run.is_future or course_run.is_promised: status = CourseRunStatus.WILL_ATTEND # the following statement needs to happen only with the new version of the algorithm elif course_run.has_frozen_grades: # be sure that the user has a final grade or freeze now if not mmtrack.has_final_grade(course_run.edx_course_key): api.freeze_user_final_grade(mmtrack.user, course_run, raise_on_exception=True) status = CourseRunStatus.CHECK_IF_PASSED # this last check needs to be done as last one elif course_run.is_past: # At this point the course has no frozen final grades yet status = CourseRunStatus.CURRENTLY_ENROLLED else: raise ImproperlyConfigured( 'The course {0} results are not either current, past, or future at the same time' .format(course_run.edx_course_key)) else: if not course_run.is_past: if course_run.is_upgradable: status = CourseRunStatus.CAN_UPGRADE else: status = CourseRunStatus.MISSED_DEADLINE else: if not course_run.is_upgradable: status = CourseRunStatus.MISSED_DEADLINE else: if not course_run.has_frozen_grades: status = CourseRunStatus.CAN_UPGRADE else: final_grade = get_final_grade(mmtrack, course_run) if final_grade.passed: status = CourseRunStatus.CAN_UPGRADE else: status = CourseRunStatus.NOT_PASSED return CourseRunUserStatus(status=status, course_run=course_run)
def get_status_for_courserun(course_run, mmtrack): # pylint: disable=too-many-return-statements """ Checks the status of a course run for a user given her enrollments Args: course_run (CourseRun): a course run mmtrack (dashboard.utils.MMTrack): a instance of all user information about a program Returns: CourseRunUserStatus: an object representing the run status for the user """ if mmtrack.has_paid_final_grade(course_run.edx_course_key): return CourseRunUserStatus(CourseRunStatus.CHECK_IF_PASSED, course_run) elif mmtrack.has_final_grade(course_run.edx_course_key): if course_run.is_upgradable: final_grade = get_final_grade(mmtrack, course_run) if final_grade.passed: return CourseRunUserStatus(CourseRunStatus.CAN_UPGRADE, course_run) else: return CourseRunUserStatus(CourseRunStatus.NOT_PASSED, course_run) else: return CourseRunUserStatus(CourseRunStatus.MISSED_DEADLINE, course_run) elif not mmtrack.is_enrolled(course_run.edx_course_key): if mmtrack.has_paid(course_run.edx_course_key): return CourseRunUserStatus(CourseRunStatus.PAID_BUT_NOT_ENROLLED, course_run) return CourseRunUserStatus(CourseRunStatus.NOT_ENROLLED, course_run) status = None if mmtrack.is_enrolled_mmtrack(course_run.edx_course_key): if course_run.is_current: status = CourseRunStatus.CURRENTLY_ENROLLED elif course_run.is_future or course_run.is_promised: status = CourseRunStatus.WILL_ATTEND # the following statement needs to happen only with the new version of the algorithm elif course_run.has_frozen_grades: # be sure that the user has a final grade or freeze now if not mmtrack.has_final_grade(course_run.edx_course_key): api.freeze_user_final_grade(mmtrack.user, course_run, raise_on_exception=True) status = CourseRunStatus.CHECK_IF_PASSED # this last check needs to be done as last one elif course_run.is_past: # At this point the course has no frozen final grades yet status = CourseRunStatus.CURRENTLY_ENROLLED else: raise ImproperlyConfigured( 'The course {0} results are not either current, past, or future at the same time'.format( course_run.edx_course_key ) ) else: if not course_run.is_past: if course_run.is_upgradable: status = CourseRunStatus.CAN_UPGRADE else: status = CourseRunStatus.MISSED_DEADLINE else: if not course_run.is_upgradable: status = CourseRunStatus.MISSED_DEADLINE else: if not course_run.has_frozen_grades: status = CourseRunStatus.CAN_UPGRADE else: final_grade = get_final_grade(mmtrack, course_run) if final_grade.passed: status = CourseRunStatus.CAN_UPGRADE else: status = CourseRunStatus.NOT_PASSED return CourseRunUserStatus( status=status, course_run=course_run )