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 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]))
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_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="" ))
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)
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 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)
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)
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)
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
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))
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)
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))
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')
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
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)
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)
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)