def clean_email_or_username(self): """ Clean email form field Returns: str: the cleaned value, converted to an email address (or an empty string) """ email_or_username = self.cleaned_data[ self.Fields.EMAIL_OR_USERNAME].strip() if not email_or_username: # The field is blank; we just return the existing blank value. return email_or_username email = email_or_username__to__email(email_or_username) bulk_entry = len(split_usernames_and_emails(email)) > 1 if bulk_entry: for email in split_usernames_and_emails(email): validate_email_to_link( email, None, ValidationMessages.INVALID_EMAIL_OR_USERNAME, ignore_existing=True) email = email_or_username else: validate_email_to_link( email, email_or_username, ValidationMessages.INVALID_EMAIL_OR_USERNAME, ignore_existing=True) return email
def _handle_singular(cls, request, enterprise_customer, manage_learners_form): """ Link single user by email or username. Arguments: enterprise_customer (EnterpriseCustomer): learners will be linked to this Enterprise Customer instance manage_learners_form (ManageLearnersForm): bound ManageLearners form instance """ form_field_value = manage_learners_form.cleaned_data[ ManageLearnersForm.Fields.EMAIL_OR_USERNAME] email = email_or_username__to__email(form_field_value) try: existing_record = validate_email_to_link( email, form_field_value, ValidationMessages.INVALID_EMAIL_OR_USERNAME, True) except ValidationError as exc: manage_learners_form.add_error( ManageLearnersForm.Fields.EMAIL_OR_USERNAME, exc) else: if isinstance(existing_record, PendingEnterpriseCustomerUser) and existing_record.enterprise_customer \ != enterprise_customer: messages.warning( request, ValidationMessages.PENDING_USER_ALREADY_LINKED.format( user_email=email, ec_name=existing_record.enterprise_customer.name)) return None EnterpriseCustomerUser.objects.link_user(enterprise_customer, email) return [email]
def _handle_bulk_upload(cls, enterprise_customer, manage_learners_form, request, email_list=None): """ Bulk link users by email. Arguments: enterprise_customer (EnterpriseCustomer): learners will be linked to this Enterprise Customer instance manage_learners_form (ManageLearnersForm): bound ManageLearners form instance request (django.http.request.HttpRequest): HTTP Request instance email_list (iterable): A list of pre-processed email addresses to handle using the form """ errors = [] emails = set() course_id_with_emails = {} already_linked_emails = [] duplicate_emails = [] csv_file = manage_learners_form.cleaned_data[ ManageLearnersForm.Fields.BULK_UPLOAD] if email_list: parsed_csv = [{ ManageLearnersForm.CsvColumns.EMAIL: email } for email in email_list] else: parsed_csv = parse_csv( csv_file, expected_columns={ManageLearnersForm.CsvColumns.EMAIL}) try: for index, row in enumerate(parsed_csv): email = row[ManageLearnersForm.CsvColumns.EMAIL] course_id = row.get(ManageLearnersForm.CsvColumns.COURSE_ID, None) # optional column course_details = None try: already_linked = validate_email_to_link( email, ignore_existing=True) if course_id: course_details = validate_course_exists_for_enterprise( enterprise_customer, course_id) except ValidationError as exc: message = _("Error at line {line}: {message}\n").format( line=index + 1, message=exc) errors.append(message) else: if already_linked: already_linked_emails.append( (email, already_linked.enterprise_customer)) elif email in emails: duplicate_emails.append(email) else: emails.add(email) # course column exists for row, is a valid course id, and exists in the enterprise's catalog(s). if course_details: if course_details[ 'course_id'] not in course_id_with_emails: course_id_with_emails[ course_details['course_id']] = {email} else: course_id_with_emails[ course_details['course_id']].add(email) except ValidationError as exc: errors.append(exc) if errors: cls._handle_bulk_upload_errors( cls, manage_learners_form=manage_learners_form, errors=errors) # There were validation errors, so prevent any further action. return [], {} # There were no errors. Now do the actual linking: for email in emails: EnterpriseCustomerUser.objects.link_user(enterprise_customer, email) # Process the bulk uploaded data: processable_emails = cls._process_bulk_upload_data( cls, request=request, enterprise_customer=enterprise_customer, emails=emails, already_linked_emails=already_linked_emails, duplicate_emails=duplicate_emails, ) return processable_emails, course_id_with_emails
def enterprise_learners(self, request, pk): """ Creates a set of enterprise_learners by enrolling them in the specified course. """ enterprise_customer = self.get_object() serializer = serializers.EnterpriseCustomerBulkEnrollmentsSerializer( data=request.data, context={ 'enterprise_customer': enterprise_customer, 'request_user': request.user, }) if serializer.is_valid(raise_exception=True): singular_email = serializer.validated_data.get('email') emails = set() already_linked_emails = [] duplicate_emails = [] errors = [] if singular_email: emails.add(singular_email) try: for email in emails: try: already_linked = validate_email_to_link( email, ignore_existing=True) except ValidationError as error: errors.append(error) else: if already_linked: already_linked_emails.append( (email, already_linked.enterprise_customer)) elif email in emails: duplicate_emails.append(email) else: emails.add(email) except ValidationError as exc: errors.append(exc) if errors: return Response(errors, status=HTTP_400_BAD_REQUEST) for email in emails: models.EnterpriseCustomerUser.objects.link_user( enterprise_customer, email) course_run_key = serializer.validated_data.get('course_run_key') mode = serializer.validated_data.get('course_mode') if course_run_key: this_customer_linked_emails = [ email for email, customer in already_linked_emails if customer == enterprise_customer ] linked_learners = list(emails) + this_customer_linked_emails if linked_learners: discount = serializer.validated_data.get('discount', 0.0) enrollment_reason = serializer.validated_data.get('reason') succeeded, pending, _ = enroll_users_in_course( enterprise_customer=enterprise_customer, course_id=course_run_key, course_mode=mode, emails=emails, enrollment_requester=request.user, enrollment_reason=enrollment_reason, discount=discount, sales_force_id=serializer.validated_data.get( 'salesforce_id'), ) if serializer.validated_data.get('notify'): enterprise_customer.notify_enrolled_learners( catalog_api_user=request.user, course_id=course_run_key, users=succeeded + pending, ) paid_modes = ['verified', 'professional'] if mode in paid_modes: enrollments = [{ "lms_user_id": success.id, "email": success.email, "username": success.username, "course_run_key": course_run_key, "discount_percentage": float(discount), "enterprise_customer_name": enterprise_customer.name, "enterprise_customer_uuid": str(enterprise_customer.uuid), "mode": mode, "sales_force_id": serializer.validated_data.get('salesforce_id'), } for success in succeeded] EcommerceApiClient(get_ecommerce_worker_user( )).create_manual_enrollment_orders(enrollments) return Response(status=HTTP_202_ACCEPTED) return Response(status=HTTP_400_BAD_REQUEST)