Exemple #1
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,
    )
Exemple #2
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'])
Exemple #3
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'])
 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=""
     ))
Exemple #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=""
     ))
 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))
    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')
Exemple #8
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)
Exemple #10
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)