예제 #1
0
    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
예제 #2
0
    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]
예제 #3
0
    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
예제 #4
0
    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)