def test_create_new_enrollment(self, search_string_type):
     """
     Assert that a new enrollment is created through post request endpoint.
     """
     test_user = UserFactory.create(username='******',
                                    email='*****@*****.**',
                                    password='******')
     assert ManualEnrollmentAudit.get_manual_enrollment_by_email(
         test_user.email) is None
     url = reverse('support:enrollment_list',
                   kwargs={
                       'username_or_email':
                       getattr(test_user, search_string_type)
                   })
     response = self.client.post(url,
                                 data={
                                     'course_id': str(self.course.id),
                                     'mode': CourseMode.AUDIT,
                                     'reason': 'Financial Assistance'
                                 })
     assert response.status_code == 200
     manual_enrollment = ManualEnrollmentAudit.get_manual_enrollment_by_email(
         test_user.email)
     assert manual_enrollment is not None
     assert manual_enrollment.reason == response.json()['reason']
     assert manual_enrollment.enrolled_email == '*****@*****.**'
     assert manual_enrollment.state_transition == UNENROLLED_TO_ENROLLED
    def assert_update_enrollment(self, search_string_type, new_mode):
        """ Dry method to update the enrollment and assert response."""
        assert ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email) is None
        url = reverse(
            'support:enrollment_list',
            kwargs={'username_or_email': getattr(self.student, search_string_type)}
        )

        with patch('lms.djangoapps.support.views.enrollments.get_credit_provider_attribute_values') as mock_method:
            credit_provider = (
                ['Arizona State University'], 'You are now eligible for credit from Arizona State University'
            )
            mock_method.return_value = credit_provider
            response = self.client.post(url, data={
                'course_id': str(self.course.id),
                'old_mode': CourseMode.AUDIT,
                'new_mode': new_mode,
                'reason': 'Financial Assistance'
            })

        assert response.status_code == 200
        assert ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email) is not None
        self.assert_enrollment(new_mode)
        if new_mode == 'credit':
            enrollment_attr = CourseEnrollmentAttribute.objects.first()
            assert enrollment_attr.value == str(credit_provider[0])
    def test_change_enrollment_mode_fullfills_entitlement(self, search_string_type, mock_get_course_uuid):
        """
        Assert that changing student's enrollment fulfills it's respective entitlement if it exists.
        """
        assert ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email) is None
        enrollment = CourseEnrollment.get_enrollment(self.student, self.course.id)
        entitlement = CourseEntitlementFactory.create(
            user=self.user,
            mode=CourseMode.VERIFIED,
            enrollment_course_run=enrollment
        )
        mock_get_course_uuid.return_value = entitlement.course_uuid

        url = reverse(
            'support:enrollment_list',
            kwargs={'username_or_email': getattr(self.student, search_string_type)}
        )
        response = self.client.post(url, data={
            'course_id': str(self.course.id),
            'old_mode': CourseMode.AUDIT,
            'new_mode': CourseMode.VERIFIED,
            'reason': 'Financial Assistance'
        })
        entitlement.refresh_from_db()
        assert response.status_code == 200
        assert ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email) is not None
        assert entitlement.enrollment_course_run is not None
        assert entitlement.is_entitlement_redeemable() is False
        self.assert_enrollment(CourseMode.VERIFIED)
Exemplo n.º 4
0
 def test_retirement(self):
     """
     Tests that calling the retirement method for a specific enrollment retires
     the enrolled_email and reason columns of each row associated with that
     enrollment.
     """
     enrollment = CourseEnrollment.enroll(self.user, self.course.id)  # lint-amnesty, pylint: disable=no-member
     other_enrollment = CourseEnrollment.enroll(self.user,
                                                self.other_course.id)  # lint-amnesty, pylint: disable=no-member
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user', enrollment)
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user again', enrollment)
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user', other_enrollment)
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user again', other_enrollment)
     assert ManualEnrollmentAudit.objects.filter(
         enrollment=enrollment).exists()
     # retire the ManualEnrollmentAudit objects associated with the above enrollments
     ManualEnrollmentAudit.retire_manual_enrollments(user=self.user,
                                                     retired_email="xxx")
     assert ManualEnrollmentAudit.objects.filter(
         enrollment=enrollment).exists()
     assert not ManualEnrollmentAudit.objects.filter(
         enrollment=enrollment).exclude(enrolled_email='xxx')
     assert not ManualEnrollmentAudit.objects.filter(
         enrollment=enrollment).exclude(reason='')
Exemplo n.º 5
0
 def test_retirement(self):
     """
     Tests that calling the retirement method for a specific enrollment retires
     the enrolled_email and reason columns of each row associated with that
     enrollment.
     """
     enrollment = CourseEnrollment.enroll(self.user, self.course.id)
     other_enrollment = CourseEnrollment.enroll(self.user, self.other_course.id)
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user', enrollment
     )
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user again', enrollment
     )
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user', other_enrollment
     )
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.instructor, self.user.email, ALLOWEDTOENROLL_TO_ENROLLED,
         'manually enrolling unenrolled user again', other_enrollment
     )
     self.assertTrue(ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exists())
     # retire the ManualEnrollmentAudit objects associated with the above enrollments
     ManualEnrollmentAudit.retire_manual_enrollments(user=self.user, retired_email="xxx")
     self.assertTrue(ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exists())
     self.assertFalse(ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exclude(
         enrolled_email="xxx"
     ))
     self.assertFalse(ManualEnrollmentAudit.objects.filter(enrollment=enrollment).exclude(
         reason=""
     ))
Exemplo n.º 6
0
def create_manual_enrollment_audit(  # lint-amnesty, pylint: disable=missing-function-docstring
        enrolled_by, user_email, state_transition, reason, course_enrollment):
    _ManualEnrollmentAudit.create_manual_enrollment_audit(
        user=enrolled_by,
        email=user_email,
        state_transition=state_transition,
        reason=reason,
        enrollment=course_enrollment,
    )
Exemplo n.º 7
0
def create_manual_enrollment_audit(enrolled_by, user_email, state_transition,
                                   reason, course_enrollment, role):
    _ManualEnrollmentAudit.create_manual_enrollment_audit(
        user=enrolled_by,
        email=user_email,
        state_transition=state_transition,
        reason=reason,
        enrollment=course_enrollment,
        role=role,
    )
 def test_get_manual_enrollment_history(self):
     ManualEnrollmentAudit.create_manual_enrollment_audit(
         self.user,
         self.student.email,
         ENROLLED_TO_ENROLLED,
         'Financial Assistance',
         CourseEnrollment.objects.get(course_id=self.course.id, user=self.student)
     )
     response = self.client.get(self.url)
     assert response.status_code == 200
     self.assertDictContainsSubset({
         'enrolled_by': self.user.email,
         'reason': 'Financial Assistance',
     }, json.loads(response.content.decode('utf-8'))[0]['manual_enrollment'])
 def test_change_enrollment(self, search_string_type):
     assert ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email) is None
     url = reverse(
         'support:enrollment_list',
         kwargs={'username_or_email': getattr(self.student, search_string_type)}
     )
     response = self.client.post(url, data={
         'course_id': str(self.course.id),
         'old_mode': CourseMode.AUDIT,
         'new_mode': CourseMode.VERIFIED,
         'reason': 'Financial Assistance'
     })
     assert response.status_code == 200
     assert ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email) is not None
     self.assert_enrollment(CourseMode.VERIFIED)
Exemplo n.º 10
0
 def test_update_enrollments_with_expired_mode(self, search_string_type):
     """ Verify that enrollment can be updated to verified mode. """
     self.set_course_end_date_and_expiry()
     self.assertIsNone(
         ManualEnrollmentAudit.get_manual_enrollment_by_email(
             self.student.email))
     self.assert_update_enrollment(search_string_type, CourseMode.VERIFIED)
Exemplo n.º 11
0
 def post(self, request, username_or_email):
     """Allows support staff to alter a user's enrollment."""
     try:
         user = User.objects.get(
             Q(username=username_or_email) | Q(email=username_or_email))
         course_id = request.data['course_id']
         course_key = CourseKey.from_string(course_id)
         old_mode = request.data['old_mode']
         new_mode = request.data['new_mode']
         reason = request.data['reason']
         enrollment = CourseEnrollment.objects.get(user=user,
                                                   course_id=course_key)
         if enrollment.mode != old_mode:
             return HttpResponseBadRequest(
                 'User {username} is not enrolled with mode {old_mode}.'.
                 format(username=user.username, old_mode=old_mode))
     except KeyError as err:
         return HttpResponseBadRequest('The field {} is required.'.format(
             str(err)))
     except InvalidKeyError:
         return HttpResponseBadRequest('Could not parse course key.')
     except (CourseEnrollment.DoesNotExist, User.DoesNotExist):
         return HttpResponseBadRequest(
             'Could not find enrollment for user {username} in course {course}.'
             .format(username=username_or_email, course=str(course_key)))
     try:
         # Wrapped in a transaction so that we can be sure the
         # ManualEnrollmentAudit record is always created correctly.
         with transaction.atomic():
             update_enrollment(user.username,
                               course_id,
                               mode=new_mode,
                               include_expired=True)
             manual_enrollment = ManualEnrollmentAudit.create_manual_enrollment_audit(
                 request.user,
                 enrollment.user.email,
                 ENROLLED_TO_ENROLLED,
                 reason=reason,
                 enrollment=enrollment)
             if new_mode == CourseMode.CREDIT_MODE:
                 provider_ids = get_credit_provider_attribute_values(
                     course_key, 'id')
                 credit_provider_attr = {
                     'namespace': 'credit',
                     'name': 'provider_id',
                     'value': provider_ids[0],
                 }
                 CourseEnrollmentAttribute.add_enrollment_attr(
                     enrollment=enrollment,
                     data_list=[credit_provider_attr])
             entitlement = CourseEntitlement.get_fulfillable_entitlement_for_user_course_run(
                 user=user, course_run_key=course_id)
             if entitlement is not None and entitlement.mode == new_mode:
                 entitlement.set_enrollment(
                     CourseEnrollment.get_enrollment(user, course_id))
             return JsonResponse(
                 ManualEnrollmentSerializer(
                     instance=manual_enrollment).data)
     except CourseModeNotFoundError as err:
         return HttpResponseBadRequest(str(err))
    def test_change_enrollment_bad_data(self, data, error_message):
        # `self` isn't available from within the DDT declaration, so
        # assign the course ID here
        if 'course_id' in data and data['course_id'] is None:
            data['course_id'] = str(self.course.id)
        response = self.client.post(self.url, data)

        assert response.status_code == 400
        assert re.match(error_message, response.content.decode('utf-8').replace("'", '').replace('"', '')) is not None
        self.assert_enrollment(CourseMode.AUDIT)
        assert ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email) is None
 def test_create_existing_enrollment(self, search_string_type):
     """
     Assert that a new enrollment is not created when an enrollment already exist for that course.
     """
     assert ManualEnrollmentAudit.get_manual_enrollment_by_email(
         self.student.email) is None
     url = reverse('support:enrollment_list',
                   kwargs={
                       'username_or_email':
                       getattr(self.student, search_string_type)
                   })
     response = self.client.post(url,
                                 data={
                                     'course_id': str(self.course.id),
                                     'mode': CourseMode.AUDIT,
                                     'reason': 'Financial Assistance'
                                 })
     assert response.status_code == 400
     assert ManualEnrollmentAudit.get_manual_enrollment_by_email(
         self.student.email) is None
    def post(self, request, username_or_email):
        """
        Allows support staff to create a user's enrollment.
        """
        try:
            course_id = request.data['course_id']
            course_key = CourseKey.from_string(course_id)
            mode = request.data['mode']
            reason = request.data['reason']
            user = User.objects.get(
                Q(username=username_or_email) | Q(email=username_or_email))
        except KeyError as err:
            return HttpResponseBadRequest(f'The field {str(err)} is required.')
        except InvalidKeyError:
            return HttpResponseBadRequest('Could not parse course key.')
        except User.DoesNotExist:
            return HttpResponseBadRequest(
                'Could not find user {username}.'.format(
                    username=username_or_email))

        enrollment = CourseEnrollment.get_enrollment(user=user,
                                                     course_key=course_key)
        if enrollment is not None:
            return HttpResponseBadRequest(
                f'The user {str(username_or_email)} is already enrolled in {str(course_id)}.'
            )

        enrollment_modes = [
            enrollment_mode['slug']
            for enrollment_mode in self.get_course_modes(course_key)
        ]
        if mode not in enrollment_modes:
            return HttpResponseBadRequest(
                f'{str(mode)} is not a valid mode for {str(course_id)}. '
                f'Possible valid modes are {str(enrollment_modes)}')

        enrollment = CourseEnrollment.enroll(user=user,
                                             course_key=course_key,
                                             mode=mode)

        # Wrapped in a transaction so that we can be sure the
        # ManualEnrollmentAudit record is always created correctly.
        with transaction.atomic():
            manual_enrollment = ManualEnrollmentAudit.create_manual_enrollment_audit(
                request.user,
                enrollment.user.email,
                UNENROLLED_TO_ENROLLED,
                reason=reason,
                enrollment=enrollment)
            return JsonResponse(
                ManualEnrollmentSerializer(instance=manual_enrollment).data)
Exemplo n.º 15
0
    def manual_enrollment_data(enrollment_data, course_key):
        """
        Returns serialized information about the manual enrollment
        belonging to this enrollment, if it exists.

        Args:
          enrollment_data (dict): Representation of a single course enrollment.
          course_key (CourseKey): The course for this enrollment.

        Returns:
          None: If no manual enrollment change has been made.
          dict: Serialization of the latest manual enrollment change.
        """
        user = User.objects.get(username=enrollment_data['user'])
        enrollment = CourseEnrollment.get_enrollment(user, course_key)
        manual_enrollment_audit = ManualEnrollmentAudit.get_manual_enrollment(enrollment)
        if manual_enrollment_audit is None:
            return {}
        return ManualEnrollmentSerializer(instance=manual_enrollment_audit).data