def bulk_update_users(request, user_file_content, test_run):
    imported_emails = {clean_email(line.decode().split(',')[1]) for line in user_file_content.splitlines()}
    emails_of_users_to_be_created = []
    users_to_be_updated = []
    skipped_external_emails_counter = 0
    for imported_email in imported_emails:
        if is_external_email(imported_email):
            skipped_external_emails_counter += 1
            continue
        try:
            matching_user = find_matching_internal_user_for_email(request, imported_email)
        except UserProfile.MultipleObjectsReturned as e:
            messages.error(request, format_html(_('Multiple users match the email {}:{}'), imported_email, create_user_list_html_string_for_message(e.args[0])))
            return False
        if (not matching_user):
            emails_of_users_to_be_created.append(imported_email)
        elif (matching_user.email != imported_email):
            users_to_be_updated.append((matching_user, imported_email))
    emails_of_non_obsolete_users = (set(imported_emails) | {user.email for (user, _) in users_to_be_updated})
    (deletable_users, users_to_mark_inactive) = ([], [])
    for user in UserProfile.objects.exclude(email__in=emails_of_non_obsolete_users):
        if user.can_be_deleted_by_manager:
            deletable_users.append(user)
        elif (user.is_active and user.can_be_marked_inactive_by_manager):
            users_to_mark_inactive.append(user)
    messages.info(request, _('The uploaded text file contains {} internal and {} external users. The external users will be ignored. {} users are currently in the database. Of those, {} will be updated, {} will be deleted and {} will be marked inactive. {} new users will be created.').format((len(imported_emails) - skipped_external_emails_counter), skipped_external_emails_counter, UserProfile.objects.count(), len(users_to_be_updated), len(deletable_users), len(users_to_mark_inactive), len(emails_of_users_to_be_created)))
    if users_to_be_updated:
        messages.info(request, format_html(_('Users to be updated are:{}'), format_html_join('', '<br />{} {} ({} &gt; {})', ((user.first_name, user.last_name, user.email, email) for (user, email) in users_to_be_updated))))
    if deletable_users:
        messages.info(request, format_html(_('Users to be deleted are:{}'), create_user_list_html_string_for_message(deletable_users)))
    if users_to_mark_inactive:
        messages.info(request, format_html(_('Users to be marked inactive are:{}'), create_user_list_html_string_for_message(users_to_mark_inactive)))
    if emails_of_users_to_be_created:
        messages.info(request, format_html(_('Users to be created are:{}'), format_html_join('', '<br />{}', ((email,) for email in emails_of_users_to_be_created))))
    with transaction.atomic():
        for user in (deletable_users + users_to_mark_inactive):
            for message in remove_user_from_represented_and_ccing_users(user, (deletable_users + users_to_mark_inactive), test_run):
                messages.warning(request, message)
        if test_run:
            messages.info(request, _('No data was changed in this test run.'))
        else:
            for user in deletable_users:
                user.delete()
            for user in users_to_mark_inactive:
                user.is_active = False
                user.save()
            for (user, email) in users_to_be_updated:
                user.email = email
                user.save()
            userprofiles_to_create = []
            for email in emails_of_users_to_be_created:
                userprofiles_to_create.append(UserProfile(email=email))
            UserProfile.objects.bulk_create(userprofiles_to_create)
            messages.success(request, _('Users have been successfully updated.'))
    return True
def bulk_update_users(request, user_file_content, test_run):
    imported_emails = {clean_email(line.decode().split(',')[1]) for line in user_file_content.splitlines()}
    emails_of_users_to_be_created = []
    users_to_be_updated = []
    skipped_external_emails_counter = 0
    for imported_email in imported_emails:
        if is_external_email(imported_email):
            skipped_external_emails_counter += 1
            continue
        try:
            matching_user = find_matching_internal_user_for_email(request, imported_email)
        except UserProfile.MultipleObjectsReturned as e:
            messages.error(request, format_html(_('Multiple users match the email {}:{}'), imported_email, create_user_list_html_string_for_message(e.args[0])))
            return False
        if (not matching_user):
            emails_of_users_to_be_created.append(imported_email)
        elif (matching_user.email != imported_email):
            users_to_be_updated.append((matching_user, imported_email))
    emails_of_non_obsolete_users = (set(imported_emails) | {user.email for (user, _) in users_to_be_updated})
    (deletable_users, users_to_mark_inactive) = ([], [])
    for user in UserProfile.objects.exclude(email__in=emails_of_non_obsolete_users):
        if user.can_be_deleted_by_manager:
            deletable_users.append(user)
        elif (user.is_active and user.can_be_marked_inactive_by_manager):
            users_to_mark_inactive.append(user)
    messages.info(request, _('The uploaded text file contains {} internal and {} external users. The external users will be ignored. {} users are currently in the database. Of those, {} will be updated, {} will be deleted and {} will be marked inactive. {} new users will be created.').format((len(imported_emails) - skipped_external_emails_counter), skipped_external_emails_counter, UserProfile.objects.count(), len(users_to_be_updated), len(deletable_users), len(users_to_mark_inactive), len(emails_of_users_to_be_created)))
    if users_to_be_updated:
        messages.info(request, format_html(_('Users to be updated are:{}'), format_html_join(, '<br />{} {} ({} &gt; {})', ((user.first_name, user.last_name, user.email, email) for (user, email) in users_to_be_updated))))
    if deletable_users:
        messages.info(request, format_html(_('Users to be deleted are:{}'), create_user_list_html_string_for_message(deletable_users)))
    if users_to_mark_inactive:
        messages.info(request, format_html(_('Users to be marked inactive are:{}'), create_user_list_html_string_for_message(users_to_mark_inactive)))
    if emails_of_users_to_be_created:
        messages.info(request, format_html(_('Users to be created are:{}'), format_html_join(, '<br />{}', ((email,) for email in emails_of_users_to_be_created))))
    with transaction.atomic():
        for user in (deletable_users + users_to_mark_inactive):
            for message in remove_user_from_represented_and_ccing_users(user, (deletable_users + users_to_mark_inactive), test_run):
                messages.warning(request, message)
        if test_run:
            messages.info(request, _('No data was changed in this test run.'))
        else:
            for user in deletable_users:
                user.delete()
            for user in users_to_mark_inactive:
                user.is_active = False
                user.save()
            for (user, email) in users_to_be_updated:
                user.email = email
                user.save()
            userprofiles_to_create = []
            for email in emails_of_users_to_be_created:
                userprofiles_to_create.append(UserProfile(email=email))
            UserProfile.objects.bulk_create(userprofiles_to_create)
            messages.success(request, _('Users have been successfully updated.'))
    return True