Beispiel #1
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=""
     ))
Beispiel #2
0
    def assert_update_enrollment(self, search_string_type, new_mode):
        """ Dry method to update the enrollment and assert response."""
        self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
        url = reverse(
            'support:enrollment_list',
            kwargs={'username_or_email': getattr(self.student, search_string_type)}
        )

        with patch('support.views.enrollments.get_credit_provider_attribute_values') as mock_method:
            credit_provider = (
                [u'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': six.text_type(self.course.id),
                'old_mode': CourseMode.AUDIT,
                'new_mode': new_mode,
                'reason': 'Financial Assistance'
            })

        self.assertEqual(response.status_code, 200)
        self.assertIsNotNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
        self.assert_enrollment(new_mode)
        if new_mode == 'credit':
            enrollment_attr = CourseEnrollmentAttribute.objects.first()
            self.assertEqual(enrollment_attr.value, six.text_type(credit_provider[0]))
Beispiel #3
0
 def assert_update_enrollment(self, search_string_type, new_mode):
     """ Dry method to update the enrollment and assert response."""
     self.assertIsNone(
         ManualEnrollmentAudit.get_manual_enrollment_by_email(
             self.student.email))
     url = reverse('support:enrollment_list',
                   kwargs={
                       'username_or_email':
                       getattr(self.student, search_string_type)
                   })
     response = self.client.post(
         url,
         data={
             'course_id': unicode(self.course.id),  # pylint: disable=no-member
             'old_mode': CourseMode.AUDIT,
             'new_mode': new_mode,
             'reason': 'Financial Assistance'
         })
     # Enrollment cannot be changed to credit mode.
     if new_mode == CourseMode.CREDIT_MODE:
         self.assertEqual(response.status_code, 400)
     else:
         self.assertEqual(response.status_code, 200)
         self.assertIsNotNone(
             ManualEnrollmentAudit.get_manual_enrollment_by_email(
                 self.student.email))
         self.assert_enrollment(new_mode)
Beispiel #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)
     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
     enrollments = CourseEnrollment.objects.filter(user=self.user)
     ManualEnrollmentAudit.retire_manual_enrollments(enrollments=enrollments, 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=""
     ))
Beispiel #5
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_change_enrollment(self):
     self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
     response = self.client.post(self.url, data={
         'course_id': unicode(self.course.id),  # pylint: disable=no-member
         'old_mode': CourseMode.AUDIT,
         'new_mode': CourseMode.VERIFIED,
         'reason': 'Financial Assistance'
     })
     self.assertEqual(response.status_code, 200)
     self.assertIsNotNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
     self.assert_enrollment(CourseMode.VERIFIED)
Beispiel #7
0
 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)  # pylint: disable=no-member
     )
     response = self.client.get(self.url)
     self.assertEqual(response.status_code, 200)
     self.assertDictContainsSubset({
         'enrolled_by': self.user.email,
         'reason': 'Financial Assistance',
     }, json.loads(response.content)[0]['manual_enrollment'])
Beispiel #8
0
 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)  # pylint: disable=no-member
     )
     response = self.client.get(self.url)
     self.assertEqual(response.status_code, 200)
     self.assertDictContainsSubset({
         'enrolled_by': self.user.email,
         'reason': 'Financial Assistance',
     }, json.loads(response.content)[0]['manual_enrollment'])
Beispiel #9
0
    def post(self, request):
        """
        POST /api/user/v1/accounts/retire_misc/

        {
            'username': '******'
        }

        Retires the user with the given username in the LMS.
        """

        username = request.data['username']

        try:
            retirement = UserRetirementStatus.get_retirement_for_retirement_action(
                username)
            RevisionPluginRevision.retire_user(retirement.user)
            ArticleRevision.retire_user(retirement.user)
            PendingNameChange.delete_by_user_value(retirement.user,
                                                   field='user')
            PasswordHistory.retire_user(retirement.user.id)
            course_enrollments = CourseEnrollment.objects.filter(
                user=retirement.user)
            ManualEnrollmentAudit.retire_manual_enrollments(
                course_enrollments, retirement.retired_email)

            CreditRequest.retire_user(retirement)
            ApiAccessRequest.retire_user(retirement.user)
            CreditRequirementStatus.retire_user(retirement)

            # This signal allows code in higher points of LMS to retire the user as necessary
            USER_RETIRE_LMS_MISC.send(sender=self.__class__,
                                      user=retirement.user)

            # This signal allows code in higher points of LMS to unsubscribe the user
            # from various types of mailings.
            USER_RETIRE_MAILINGS.send(sender=self.__class__,
                                      email=retirement.original_email,
                                      new_email=retirement.retired_email,
                                      user=retirement.user)
        except UserRetirementStatus.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        except RetirementStateError as exc:
            return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
        except Exception as exc:  # pylint: disable=broad-except
            return Response(text_type(exc),
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response(status=status.HTTP_204_NO_CONTENT)
Beispiel #10
0
 def test_change_enrollment(self, search_string_type):
     self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
     url = reverse(
         'support:enrollment_list',
         kwargs={'username_or_email': getattr(self.student, search_string_type)}
     )
     response = self.client.post(url, data={
         'course_id': unicode(self.course.id),  # pylint: disable=no-member
         'old_mode': CourseMode.AUDIT,
         'new_mode': CourseMode.VERIFIED,
         'reason': 'Financial Assistance'
     })
     self.assertEqual(response.status_code, 200)
     self.assertIsNotNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
     self.assert_enrollment(CourseMode.VERIFIED)
Beispiel #11
0
 def test_change_enrollment(self, search_string_type):
     self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
     url = reverse(
         'support:enrollment_list',
         kwargs={'username_or_email': getattr(self.student, search_string_type)}
     )
     response = self.client.post(url, data={
         'course_id': unicode(self.course.id),  # pylint: disable=no-member
         'old_mode': CourseMode.AUDIT,
         'new_mode': CourseMode.VERIFIED,
         'reason': 'Financial Assistance'
     })
     self.assertEqual(response.status_code, 200)
     self.assertIsNotNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
     self.assert_enrollment(CourseMode.VERIFIED)
Beispiel #12
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)
Beispiel #13
0
 def test_change_enrollment(self):
     self.assertIsNone(
         ManualEnrollmentAudit.get_manual_enrollment_by_email(
             self.student.email))
     response = self.client.post(
         self.url,
         data={
             'course_id': unicode(self.course.id),  # pylint: disable=no-member
             'old_mode': CourseMode.AUDIT,
             'new_mode': CourseMode.VERIFIED,
             'reason': 'Financial Assistance'
         })
     self.assertEqual(response.status_code, 200)
     self.assertIsNotNone(
         ManualEnrollmentAudit.get_manual_enrollment_by_email(
             self.student.email))
     self.assert_enrollment(CourseMode.VERIFIED)
    def get_enrollment_info(self, user, course_id):
        """
        Returns the User Enrollment information.
        """
        course = get_course_by_id(course_id, depth=0)
        is_course_staff = bool(has_access(user, 'staff', course))

        # check the user enrollment role
        if user.is_staff:
            platform_name = microsite.get_value('platform_name',
                                                settings.PLATFORM_NAME)
            enrollment_role = _('{platform_name} Staff').format(
                platform_name=platform_name)
        elif is_course_staff:
            enrollment_role = _('Course Staff')
        else:
            enrollment_role = _('Student')

        course_enrollment = CourseEnrollment.get_enrollment(
            user=user, course_key=course_id)

        if is_course_staff:
            enrollment_source = _('Staff')
        else:
            # get the registration_code_redemption object if exists
            registration_code_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(
                course_enrollment)
            # get the paid_course registration item if exists
            paid_course_reg_item = PaidCourseRegistration.get_course_item_for_user_enrollment(
                user=user,
                course_id=course_id,
                course_enrollment=course_enrollment)

            # from where the user get here
            if registration_code_redemption is not None:
                enrollment_source = _('Used Registration Code')
            elif paid_course_reg_item is not None:
                enrollment_source = _('Credit Card - Individual')
            else:
                manual_enrollment = ManualEnrollmentAudit.get_manual_enrollment(
                    course_enrollment)
                if manual_enrollment is not None:
                    enrollment_source = _(
                        'manually enrolled by user_id {user_id}, enrollment state transition: {transition}'
                    ).format(user_id=manual_enrollment.enrolled_by_id,
                             transition=manual_enrollment.state_transition)
                else:
                    enrollment_source = _('Manually Enrolled')

        enrollment_date = course_enrollment.created.strftime("%B %d, %Y")
        currently_enrolled = course_enrollment.is_active

        course_enrollment_data = collections.OrderedDict()
        course_enrollment_data['Enrollment Date'] = enrollment_date
        course_enrollment_data['Currently Enrolled'] = currently_enrolled
        course_enrollment_data['Enrollment Source'] = enrollment_source
        course_enrollment_data['Enrollment Role'] = enrollment_role
        return course_enrollment_data
    def get_enrollment_info(self, user, course_id):
        """
        Returns the User Enrollment information.
        """
        course = get_course_by_id(course_id, depth=0)
        is_course_staff = bool(has_access(user, 'staff', course))
        manual_enrollment_reason = 'N/A'

        # check the user enrollment role
        if user.is_staff:
            platform_name = configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME)
            enrollment_role = _('{platform_name} Staff').format(platform_name=platform_name)
        elif is_course_staff:
            enrollment_role = _('Course Staff')
        else:
            enrollment_role = _('Student')

        course_enrollment = CourseEnrollment.get_enrollment(user=user, course_key=course_id)

        if is_course_staff:
            enrollment_source = _('Staff')
        else:
            # get the registration_code_redemption object if exists
            registration_code_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(
                course_enrollment)
            # get the paid_course registration item if exists
            paid_course_reg_item = PaidCourseRegistration.get_course_item_for_user_enrollment(
                user=user,
                course_id=course_id,
                course_enrollment=course_enrollment
            )

            # from where the user get here
            if registration_code_redemption is not None:
                enrollment_source = _('Used Registration Code')
            elif paid_course_reg_item is not None:
                enrollment_source = _('Credit Card - Individual')
            else:
                manual_enrollment = ManualEnrollmentAudit.get_manual_enrollment(course_enrollment)
                if manual_enrollment is not None:
                    enrollment_source = _(
                        'manually enrolled by username: {username}'
                    ).format(username=manual_enrollment.enrolled_by.username)

                    manual_enrollment_reason = manual_enrollment.reason
                else:
                    enrollment_source = _('Manually Enrolled')

        enrollment_date = course_enrollment.created.strftime("%B %d, %Y")
        currently_enrolled = course_enrollment.is_active

        course_enrollment_data = collections.OrderedDict()
        course_enrollment_data['Enrollment Date'] = enrollment_date
        course_enrollment_data['Currently Enrolled'] = currently_enrolled
        course_enrollment_data['Enrollment Source'] = enrollment_source
        course_enrollment_data['Manual (Un)Enrollment Reason'] = manual_enrollment_reason
        course_enrollment_data['Enrollment Role'] = enrollment_role
        return course_enrollment_data
Beispiel #16
0
    def post(self, request):
        """
        POST /api/user/v1/accounts/retire_misc/

        {
            'username': '******'
        }

        Retires the user with the given username in the LMS.
        """

        username = request.data['username']

        try:
            retirement = UserRetirementStatus.get_retirement_for_retirement_action(username)
            RevisionPluginRevision.retire_user(retirement.user)
            ArticleRevision.retire_user(retirement.user)
            PendingNameChange.delete_by_user_value(retirement.user, field='user')
            PasswordHistory.retire_user(retirement.user.id)
            course_enrollments = CourseEnrollment.objects.filter(user=retirement.user)
            ManualEnrollmentAudit.retire_manual_enrollments(course_enrollments, retirement.retired_email)

            CreditRequest.retire_user(retirement.original_username, retirement.retired_username)
            ApiAccessRequest.retire_user(retirement.user)
            CreditRequirementStatus.retire_user(retirement.user.username)

            # This signal allows code in higher points of LMS to retire the user as necessary
            USER_RETIRE_LMS_MISC.send(sender=self.__class__, user=retirement.user)

            # This signal allows code in higher points of LMS to unsubscribe the user
            # from various types of mailings.
            USER_RETIRE_MAILINGS.send(
                sender=self.__class__,
                email=retirement.original_email,
                new_email=retirement.retired_email,
                user=retirement.user
            )
        except UserRetirementStatus.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        except RetirementStateError as exc:
            return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
        except Exception as exc:  # pylint: disable=broad-except
            return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response(status=status.HTTP_204_NO_CONTENT)
 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(
                 u'User {username} is not enrolled with mode {old_mode}.'.
                 format(username=user.username, old_mode=old_mode))
     except KeyError as err:
         return HttpResponseBadRequest(u'The field {} is required.'.format(
             text_type(err)))
     except InvalidKeyError:
         return HttpResponseBadRequest(u'Could not parse course key.')
     except (CourseEnrollment.DoesNotExist, User.DoesNotExist):
         return HttpResponseBadRequest(
             u'Could not find enrollment for user {username} in course {course}.'
             .format(username=username_or_email,
                     course=six.text_type(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])
             return JsonResponse(
                 ManualEnrollmentSerializer(
                     instance=manual_enrollment).data)
     except CourseModeNotFoundError as err:
         return HttpResponseBadRequest(text_type(err))
Beispiel #18
0
    def post(self, request):
        """
        POST /api/user/v1/accounts/retire_misc/

        {
            'username': '******'
        }

        Retires the user with the given username in the LMS.
        """

        username = request.data['username']
        if is_username_retired(username):
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            retirement = UserRetirementStatus.get_retirement_for_retirement_action(
                username)
            RevisionPluginRevision.retire_user(retirement.user)
            ArticleRevision.retire_user(retirement.user)
            PendingNameChange.delete_by_user_value(retirement.user,
                                                   field='user')
            PasswordHistory.retire_user(retirement.user.id)
            course_enrollments = CourseEnrollment.objects.filter(
                user=retirement.user)
            ManualEnrollmentAudit.retire_manual_enrollments(
                course_enrollments, retirement.retired_email)

            CreditRequest.retire_user(retirement.original_username,
                                      retirement.retired_username)
            ApiAccessRequest.retire_user(retirement.user)
            CreditRequirementStatus.retire_user(retirement.user.username)
            SurveyAnswer.retire_user(retirement.user.id)

        except UserRetirementStatus.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        except RetirementStateError as exc:
            return Response(text_type(exc), status=status.HTTP_400_BAD_REQUEST)
        except Exception as exc:  # pylint: disable=broad-except
            return Response(text_type(exc),
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response(status=status.HTTP_204_NO_CONTENT)
Beispiel #19
0
 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'] = unicode(self.course.id)  # pylint: disable=no-member
     response = self.client.post(self.url, data)
     self.assertEqual(response.status_code, 400)
     self.assertIsNotNone(re.match(error_message, response.content))
     self.assert_enrollment(CourseMode.AUDIT)
     self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
Beispiel #20
0
 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'] = unicode(self.course.id)  # pylint: disable=no-member
     response = self.client.post(self.url, data)
     self.assertEqual(response.status_code, 400)
     self.assertIsNotNone(re.match(error_message, response.content))
     self.assert_enrollment(CourseMode.AUDIT)
     self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
Beispiel #21
0
 def assert_update_enrollment(self, search_string_type, new_mode):
     """ Dry method to update the enrollment and assert response."""
     self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
     url = reverse(
         'support:enrollment_list',
         kwargs={'username_or_email': getattr(self.student, search_string_type)}
     )
     response = self.client.post(url, data={
         'course_id': unicode(self.course.id),  # pylint: disable=no-member
         'old_mode': CourseMode.AUDIT,
         'new_mode': new_mode,
         'reason': 'Financial Assistance'
     })
     # Enrollment cannot be changed to credit mode.
     if new_mode == CourseMode.CREDIT_MODE:
         self.assertEqual(response.status_code, 400)
     else:
         self.assertEqual(response.status_code, 200)
         self.assertIsNotNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
         self.assert_enrollment(new_mode)
    def test_student_manually_enrolled_in_detailed_enrollment_source(self):
        """
        test to check the manually enrolled user enrollment report status
        and enrollment source.
        """
        student = UserFactory()
        enrollment = CourseEnrollment.enroll(student, self.course.id)
        ManualEnrollmentAudit.create_manual_enrollment_audit(
            self.instructor, student.email, ALLOWEDTOENROLL_TO_ENROLLED,
            'manually enrolling unenrolled user', enrollment
        )

        task_input = {'features': []}
        with patch('instructor_task.tasks_helper._get_current_task'):
            result = upload_enrollment_report(None, None, self.course.id, task_input, 'generating_enrollment_report')

        enrollment_source = u'manually enrolled by user_id {user_id}, enrollment state transition: {transition}'.format(
            user_id=self.instructor.id, transition=ALLOWEDTOENROLL_TO_ENROLLED)  # pylint: disable=no-member
        self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result)
        self._verify_cell_data_in_csv(student.username, 'Enrollment Source', enrollment_source)
        self._verify_cell_data_in_csv(student.username, 'Payment Status', 'TBD')
Beispiel #23
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
Beispiel #24
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
Beispiel #25
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(u'User {username} is not enrolled with mode {old_mode}.'.format(
                 username=user.username,
                 old_mode=old_mode
             ))
         if new_mode == CourseMode.CREDIT_MODE:
             return HttpResponseBadRequest(u'Enrollment cannot be changed to credit mode.')
     except KeyError as err:
         return HttpResponseBadRequest(u'The field {} is required.'.format(text_type(err)))
     except InvalidKeyError:
         return HttpResponseBadRequest(u'Could not parse course key.')
     except (CourseEnrollment.DoesNotExist, User.DoesNotExist):
         return HttpResponseBadRequest(
             u'Could not find enrollment for user {username} in course {course}.'.format(
                 username=username_or_email,
                 course=unicode(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
             )
             return JsonResponse(ManualEnrollmentSerializer(instance=manual_enrollment).data)
     except CourseModeNotFoundError as err:
         return HttpResponseBadRequest(text_type(err))
 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(
                 u'User {username} is not enrolled with mode {old_mode}.'.
                 format(username=user.username, old_mode=old_mode))
     except KeyError as err:
         return HttpResponseBadRequest(u'The field {} is required.'.format(
             err.message))
     except InvalidKeyError:
         return HttpResponseBadRequest(u'Could not parse course key.')
     except (CourseEnrollment.DoesNotExist, User.DoesNotExist):
         return HttpResponseBadRequest(
             u'Could not find enrollment for user {username} in course {course}.'
             .format(username=username_or_email,
                     course=unicode(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)
             manual_enrollment = ManualEnrollmentAudit.create_manual_enrollment_audit(
                 request.user,
                 enrollment.user.email,
                 ENROLLED_TO_ENROLLED,
                 reason=reason,
                 enrollment=enrollment)
             return JsonResponse(
                 ManualEnrollmentSerializer(
                     instance=manual_enrollment).data)
     except CourseModeNotFoundError as err:
         return HttpResponseBadRequest(err.message)
Beispiel #27
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)
Beispiel #28
0
    def post(self, request, *args, **kwargs):

        course_id = request.POST.get('course_id', False)
        try:
            course_id = SlashSeparatedCourseKey.from_deprecated_string(
                course_id)
        except Exception:
            course_id = None

        if not course_id:
            self.msg = u"课程ID错误"
            context = {'msg': self.msg, 'datatable': self.make_datatable()}
            return render_to_response(self.template_name, context)
        elif not request.POST.get('identifiers'):
            self.msg = u"邮箱用户名错误"
            context = {'msg': self.msg, 'datatable': self.make_datatable()}
            return render_to_response(self.template_name, context)

        action = request.POST.get('action')
        identifiers_raw = request.POST.get('identifiers')
        identifiers = _split_input_list(identifiers_raw)
        auto_enroll = _get_boolean_param(request, 'auto_enroll')
        email_students = _get_boolean_param(request, 'email_students')
        is_white_label = CourseMode.is_white_label(course_id)
        reason = request.POST.get('reason')

        if is_white_label:
            if not reason:
                self.msg = "400"
                context = {'msg': self.msg, 'datatable': self.make_datatable()}
                return render_to_response(self.template_name, context)

        enrollment_obj = None
        state_transition = DEFAULT_TRANSITION_STATE

        email_params = {}
        if email_students:
            course = get_course_by_id(course_id)
            email_params = get_email_params(course,
                                            auto_enroll,
                                            secure=request.is_secure())

        results = []
        for identifier in identifiers:
            # First try to get a user object from the identifer
            user = None
            email = None
            language = None
            try:
                user = get_student_from_identifier(identifier)
            except User.DoesNotExist:
                email = identifier
            else:
                email = user.email
                language = get_user_email_language(user)

            try:
                # Use django.core.validators.validate_email to check email address
                # validity (obviously, cannot check if email actually /exists/,
                # simply that it is plausibly valid)
                validate_email(email)  # Raises ValidationError if invalid
                if action == 'enroll':
                    before, after, enrollment_obj = enroll_email(
                        course_id,
                        email,
                        auto_enroll,
                        email_students,
                        email_params,
                        language=language)
                    before_enrollment = before.to_dict()['enrollment']
                    before_user_registered = before.to_dict()['user']
                    before_allowed = before.to_dict()['allowed']
                    after_enrollment = after.to_dict()['enrollment']
                    after_allowed = after.to_dict()['allowed']

                    if before_user_registered:
                        if after_enrollment:
                            if before_enrollment:
                                state_transition = ENROLLED_TO_ENROLLED
                            else:
                                if before_allowed:
                                    state_transition = ALLOWEDTOENROLL_TO_ENROLLED
                                else:
                                    state_transition = UNENROLLED_TO_ENROLLED
                    else:
                        if after_allowed:
                            state_transition = UNENROLLED_TO_ALLOWEDTOENROLL

                elif action == 'unenroll':
                    before, after = unenroll_email(course_id,
                                                   email,
                                                   email_students,
                                                   email_params,
                                                   language=language)
                    before_enrollment = before.to_dict()['enrollment']
                    before_allowed = before.to_dict()['allowed']
                    enrollment_obj = CourseEnrollment.get_enrollment(
                        user, course_id)

                    if before_enrollment:
                        state_transition = ENROLLED_TO_UNENROLLED
                    else:
                        if before_allowed:
                            state_transition = ALLOWEDTOENROLL_TO_UNENROLLED
                        else:
                            state_transition = UNENROLLED_TO_UNENROLLED

                else:
                    return HttpResponseBadRequest(
                        strip_tags("Unrecognized action '{}'".format(action)))

            except ValidationError:
                # Flag this email as an error if invalid, but continue checking
                # the remaining in the list
                results.append({
                    'identifier': identifier,
                    'invalidIdentifier': True,
                })

            except Exception as exc:  # pylint: disable=broad-except
                # catch and log any exceptions
                # so that one error doesn't cause a 500.
                log.exception(u"Error while #{}ing student")
                log.exception(exc)
                results.append({
                    'identifier': identifier,
                    'error': True,
                })

            else:
                ManualEnrollmentAudit.create_manual_enrollment_audit(
                    request.user, email, state_transition, reason,
                    enrollment_obj)
                results.append({
                    'identifier': identifier,
                    'before': before.to_dict(),
                    'after': after.to_dict(),
                })

        invalid_id = []
        valid_id = []

        for result in results:
            if ('error' in result) or ('invalidIdentifier' in result):
                invalid_id.append(result['identifier'])
            else:
                valid_id.append(result['identifier'])

        invalid_message = [
            "{} 无效 <br>".format(i.encode('utf-8')) for i in invalid_id
        ]
        valid_message = []

        action = "选课" if action == "enroll" else "弃选"

        for i in valid_id:
            if action == "弃选":
                valid_message.append("{0}  {1} 成功 <br>".format(i, action))
                continue
            if email_students:
                valid_message.append("{0}  {1} 成功,并向他发送电子邮件 <br>".format(
                    i, action))
            else:
                valid_message.append("{0}  {1} 成功<br>".format(i, action))
        invalid_message.extend(valid_message)

        self.msg = "".join(invalid_message)

        context = {'msg': self.msg, 'datatable': self.make_datatable()}
        return render_to_response(self.template_name, context)