def test_get_group_for_user_with_skipped(self): # Check that a user is in verified allow group if that user has skipped # any ICRV block. user = self.create_user_and_enroll('verified') SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.first_checkpoint, user_id=user.id, course_id=self.course.id) self._assert_group_assignment(user, VerificationPartitionScheme.ALLOW)
def _get_user_statuses(user, course_key, checkpoint): """ Retrieve all the information we need to determine the user's group. This will retrieve the information as a multi-get from the cache. Args: user (User): User object course_key (CourseKey): Identifier for the course. checkpoint (unicode): Location of the checkpoint in the course (serialized usage key) Returns: tuple of booleans of the form (is_verified, has_skipped, has_completed) """ enrollment_cache_key = CourseEnrollment.cache_key_name(user.id, unicode(course_key)) has_skipped_cache_key = SkippedReverification.cache_key_name(user.id, unicode(course_key)) verification_status_cache_key = VerificationStatus.cache_key_name(user.id, unicode(course_key)) # Try a multi-get from the cache cache_values = cache.get_many([ enrollment_cache_key, has_skipped_cache_key, verification_status_cache_key ]) # Retrieve whether the user is enrolled in a verified mode. is_verified = cache_values.get(enrollment_cache_key) if is_verified is None: is_verified = CourseEnrollment.is_enrolled_as_verified(user, course_key) cache.set(enrollment_cache_key, is_verified) # Retrieve whether the user has skipped any checkpoints in this course has_skipped = cache_values.get(has_skipped_cache_key) if has_skipped is None: has_skipped = SkippedReverification.check_user_skipped_reverification_exists(user, course_key) cache.set(has_skipped_cache_key, has_skipped) # Retrieve the user's verification status for each checkpoint in the course. verification_statuses = cache_values.get(verification_status_cache_key) if verification_statuses is None: verification_statuses = VerificationStatus.get_all_checkpoints(user.id, course_key) cache.set(verification_status_cache_key, verification_statuses) # Check whether the user has completed this checkpoint # "Completion" here means *any* submission, regardless of its status # since we want to show the user the content if they've submitted # photos. checkpoint = verification_statuses.get(checkpoint) has_completed_check = bool(checkpoint) return (is_verified, has_skipped, has_completed_check)
def test_add_skipped_attempts(self): """ Test 'add_skipped_reverification_attempt' method. """ # add verification status SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id) ) # test the status of skipped reverification from database result = SkippedReverification.objects.filter(course_id=self.course.id)[0] self.assertEqual(result.checkpoint, self.checkpoint) self.assertEqual(result.user, self.user) self.assertEqual(result.course_id, self.course.id)
def get_status(self, user_id, course_id, related_assessment_location): """Get verification attempt status against a user for a given 'checkpoint' and 'course_id'. Args: user_id (str): User Id string course_id (str): A string of course id related_assessment_location (str): Location of Reverification XBlock Returns: str or None """ user = User.objects.get(id=user_id) course_key = CourseKey.from_string(course_id) if not CourseEnrollment.is_enrolled_as_verified(user, course_key): return self.NON_VERIFIED_TRACK elif SkippedReverification.check_user_skipped_reverification_exists( user_id, course_key): return self.SKIPPED_STATUS try: checkpoint_status = VerificationStatus.objects.filter( user_id=user_id, checkpoint__course_id=course_key, checkpoint__checkpoint_location=related_assessment_location ).latest() return checkpoint_status.status except ObjectDoesNotExist: return None
def test_cache_with_skipped_icrv(self): # Check that a user is in verified allow group if that user has skipped # any ICRV block. user = self.create_user_and_enroll('verified') SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.first_checkpoint, user_id=user.id, course_id=self.course.id ) # this will warm the cache. with self.assertNumQueries(3): self._assert_group_assignment(user, VerificationPartitionScheme.ALLOW) # no db queries this time. with self.assertNumQueries(0): self._assert_group_assignment(user, VerificationPartitionScheme.ALLOW)
def get_status(self, user_id, course_id, related_assessment_location): """Get verification attempt status against a user for a given 'checkpoint' and 'course_id'. Args: user_id (str): User Id string course_id (str): A string of course id related_assessment_location (str): Location of Reverification XBlock Returns: str or None """ user = User.objects.get(id=user_id) course_key = CourseKey.from_string(course_id) if not CourseEnrollment.is_enrolled_as_verified(user, course_key): return self.NON_VERIFIED_TRACK elif SkippedReverification.check_user_skipped_reverification_exists(user_id, course_key): return self.SKIPPED_STATUS try: checkpoint_status = VerificationStatus.objects.filter( user_id=user_id, checkpoint__course_id=course_key, checkpoint__checkpoint_location=related_assessment_location ).latest() return checkpoint_status.status except ObjectDoesNotExist: return None
def test_check_user_skipped_reverification_exists(self): """ Test the 'check_user_skipped_reverification_exists' method's response. """ # add verification status SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id)) self.assertTrue( SkippedReverification.check_user_skipped_reverification_exists( user_id=self.user.id, course_id=self.course.id)) user2 = UserFactory.create() self.assertFalse( SkippedReverification.check_user_skipped_reverification_exists( user_id=user2.id, course_id=self.course.id))
def test_add_skipped_attempts(self): """ Test 'add_skipped_reverification_attempt' method. """ # add verification status SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id)) # test the status of skipped reverification from database result = SkippedReverification.objects.filter( course_id=self.course.id)[0] self.assertEqual(result.checkpoint, self.checkpoint) self.assertEqual(result.user, self.user) self.assertEqual(result.course_id, self.course.id)
def skip_verification(self, user_id, course_id, related_assessment_location): """Add skipped verification attempt entry for a user against a given 'checkpoint'. Args: user_id(str): User Id string course_id(str): A string of course_id related_assessment_location(str): Location of Reverification XBlock Returns: None """ course_key = CourseKey.from_string(course_id) checkpoint = VerificationCheckpoint.objects.get( course_id=course_key, checkpoint_location=related_assessment_location) user = User.objects.get(id=user_id) # user can skip a reverification attempt only if that user has not already # skipped an attempt try: SkippedReverification.add_skipped_reverification_attempt( checkpoint, user_id, course_key) except IntegrityError: log.exception( "Skipped attempt already exists for user %s: with course %s:", user_id, unicode(course_id)) return try: # Avoid circular import from openedx.core.djangoapps.credit.api import set_credit_requirement_status # As a user skips the reverification it declines to fulfill the requirement so # requirement sets to declined. set_credit_requirement_status(user, course_key, 'reverification', checkpoint.checkpoint_location, status='declined') except Exception as err: # pylint: disable=broad-except log.error( "Unable to add credit requirement status for user with id %d: %s", user_id, err)
def skip_verification(self, user_id, course_id, related_assessment_location): """Add skipped verification attempt entry for a user against a given 'checkpoint'. Args: user_id(str): User Id string course_id(str): A string of course_id related_assessment_location(str): Location of Reverification XBlock Returns: None """ course_key = CourseKey.from_string(course_id) checkpoint = VerificationCheckpoint.objects.get( course_id=course_key, checkpoint_location=related_assessment_location ) user = User.objects.get(id=user_id) # user can skip a reverification attempt only if that user has not already # skipped an attempt try: SkippedReverification.add_skipped_reverification_attempt(checkpoint, user_id, course_key) except IntegrityError: log.exception("Skipped attempt already exists for user %s: with course %s:", user_id, unicode(course_id)) return try: # Avoid circular import from openedx.core.djangoapps.credit.api import set_credit_requirement_status # As a user skips the reverification it declines to fulfill the requirement so # requirement sets to declined. set_credit_requirement_status( user.username, course_key, 'reverification', checkpoint.checkpoint_location, status='declined' ) except Exception as err: # pylint: disable=broad-except log.error("Unable to add credit requirement status for user with id %d: %s", user_id, err)
def test_unique_constraint(self): """Test that adding skipped re-verification with same user and course id will raise 'IntegrityError' exception. """ # add verification object SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id)) with self.assertRaises(IntegrityError): SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id)) # create skipped attempt for different user user2 = UserFactory.create() SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=user2.id, course_id=unicode(self.course.id)) # test the status of skipped reverification from database result = SkippedReverification.objects.filter(user=user2)[0] self.assertEqual(result.checkpoint, self.checkpoint) self.assertEqual(result.user, user2) self.assertEqual(result.course_id, self.course.id)
def test_check_user_skipped_reverification_exists(self): """ Test the 'check_user_skipped_reverification_exists' method's response. """ # add verification status SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id) ) self.assertTrue( SkippedReverification.check_user_skipped_reverification_exists( user_id=self.user.id, course_id=self.course.id ) ) user2 = UserFactory.create() self.assertFalse( SkippedReverification.check_user_skipped_reverification_exists( user_id=user2.id, course_id=self.course.id ) )
def test_unique_constraint(self): """Test that adding skipped re-verification with same user and course id will raise 'IntegrityError' exception. """ # add verification object SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id) ) with self.assertRaises(IntegrityError): SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=self.user.id, course_id=unicode(self.course.id) ) # create skipped attempt for different user user2 = UserFactory.create() SkippedReverification.add_skipped_reverification_attempt( checkpoint=self.checkpoint, user_id=user2.id, course_id=unicode(self.course.id) ) # test the status of skipped reverification from database result = SkippedReverification.objects.filter(user=user2)[0] self.assertEqual(result.checkpoint, self.checkpoint) self.assertEqual(result.user, user2) self.assertEqual(result.course_id, self.course.id)