@transaction.atomic
def merge_users(main_user, other_user, preview=False):
    'Merges other_user into main_user'
    merged_user = {}
    merged_user['is_active'] = (main_user.is_active or other_user.is_active)
    merged_user['title'] = (main_user.title or other_user.title or '')
    merged_user['first_name'] = (main_user.first_name or other_user.first_name or '')
    merged_user['last_name'] = (main_user.last_name or other_user.last_name or '')
    merged_user['email'] = (main_user.email or other_user.email or None)
    merged_user['groups'] = Group.objects.filter(user__in=[main_user, other_user]).distinct()
    merged_user['is_superuser'] = (main_user.is_superuser or other_user.is_superuser)
    merged_user['is_proxy_user'] = (main_user.is_proxy_user or other_user.is_proxy_user)
    merged_user['delegates'] = UserProfile.objects.filter(represented_users__in=[main_user, other_user]).distinct()
    merged_user['represented_users'] = UserProfile.objects.filter(delegates__in=[main_user, other_user]).distinct()
    merged_user['cc_users'] = UserProfile.objects.filter(ccing_users__in=[main_user, other_user]).distinct()
    merged_user['ccing_users'] = UserProfile.objects.filter(cc_users__in=[main_user, other_user]).distinct()
    errors = []
    warnings = []
    courses_main_user_is_responsible_for = main_user.get_sorted_courses_responsible_for()
    if any(((course in courses_main_user_is_responsible_for) for course in other_user.get_sorted_courses_responsible_for())):
        errors.append('courses_responsible_for')
    if any(((contribution.evaluation in [contribution.evaluation for contribution in main_user.get_sorted_contributions()]) for contribution in other_user.get_sorted_contributions())):
        errors.append('contributions')
    if any(((evaluation in main_user.get_sorted_evaluations_participating_in()) for evaluation in other_user.get_sorted_evaluations_participating_in())):
        errors.append('evaluations_participating_in')
    if any(((evaluation in main_user.get_sorted_evaluations_voted_for()) for evaluation in other_user.get_sorted_evaluations_voted_for())):
        errors.append('evaluations_voted_for')
    if (main_user.reward_point_grantings.all().exists() and other_user.reward_point_grantings.all().exists()):
        warnings.append('rewards')
    merged_user['courses_responsible_for'] = Course.objects.filter(responsibles__in=[main_user, other_user]).order_by('semester__created_at', 'name_de')
    merged_user['contributions'] = Contribution.objects.filter(contributor__in=[main_user, other_user]).order_by('evaluation__course__semester__created_at', 'evaluation__name_de')
    merged_user['evaluations_participating_in'] = Evaluation.objects.filter(participants__in=[main_user, other_user]).order_by('course__semester__created_at', 'name_de')
    merged_user['evaluations_voted_for'] = Evaluation.objects.filter(voters__in=[main_user, other_user]).order_by('course__semester__created_at', 'name_de')
    merged_user['reward_point_grantings'] = (main_user.reward_point_grantings.all() or other_user.reward_point_grantings.all())
    merged_user['reward_point_redemptions'] = (main_user.reward_point_redemptions.all() or other_user.reward_point_redemptions.all())
    if (preview or errors):
        return (merged_user, errors, warnings)
    for course in Course.objects.filter(responsibles__in=[other_user]):
        responsibles = list(course.responsibles.all())
        responsibles.remove(other_user)
        responsibles.append(main_user)
        course.responsibles.set(responsibles)
    GradeDocument.objects.filter(last_modified_user=other_user).update(last_modified_user=main_user)
    other_user.email = ''
    other_user.save()
    for (key, value) in merged_user.items():
        attr = getattr(main_user, key)
        if hasattr(attr, 'set'):
            attr.set(value)
        else:
            setattr(main_user, key, value)
    main_user.save()
    other_user.reward_point_grantings.all().delete()
    other_user.reward_point_redemptions.all().delete()
    LogEntry.objects.filter(user=other_user).update(user=main_user)
    evaluations = Evaluation.objects.filter(contributions__contributor=main_user, state__in=STATES_WITH_RESULTS_CACHING).distinct()
    for evaluation in evaluations:
        cache_results(evaluation)
    other_user.delete()
    return (merged_user, errors, warnings)
Merges other_user into main_user
@transaction.atomic
def merge_users(main_user, other_user, preview=False):
    
    merged_user = {}
    merged_user['is_active'] = (main_user.is_active or other_user.is_active)
    merged_user['title'] = (main_user.title or other_user.title or )
    merged_user['first_name'] = (main_user.first_name or other_user.first_name or )
    merged_user['last_name'] = (main_user.last_name or other_user.last_name or )
    merged_user['email'] = (main_user.email or other_user.email or None)
    merged_user['groups'] = Group.objects.filter(user__in=[main_user, other_user]).distinct()
    merged_user['is_superuser'] = (main_user.is_superuser or other_user.is_superuser)
    merged_user['is_proxy_user'] = (main_user.is_proxy_user or other_user.is_proxy_user)
    merged_user['delegates'] = UserProfile.objects.filter(represented_users__in=[main_user, other_user]).distinct()
    merged_user['represented_users'] = UserProfile.objects.filter(delegates__in=[main_user, other_user]).distinct()
    merged_user['cc_users'] = UserProfile.objects.filter(ccing_users__in=[main_user, other_user]).distinct()
    merged_user['ccing_users'] = UserProfile.objects.filter(cc_users__in=[main_user, other_user]).distinct()
    errors = []
    warnings = []
    courses_main_user_is_responsible_for = main_user.get_sorted_courses_responsible_for()
    if any(((course in courses_main_user_is_responsible_for) for course in other_user.get_sorted_courses_responsible_for())):
        errors.append('courses_responsible_for')
    if any(((contribution.evaluation in [contribution.evaluation for contribution in main_user.get_sorted_contributions()]) for contribution in other_user.get_sorted_contributions())):
        errors.append('contributions')
    if any(((evaluation in main_user.get_sorted_evaluations_participating_in()) for evaluation in other_user.get_sorted_evaluations_participating_in())):
        errors.append('evaluations_participating_in')
    if any(((evaluation in main_user.get_sorted_evaluations_voted_for()) for evaluation in other_user.get_sorted_evaluations_voted_for())):
        errors.append('evaluations_voted_for')
    if (main_user.reward_point_grantings.all().exists() and other_user.reward_point_grantings.all().exists()):
        warnings.append('rewards')
    merged_user['courses_responsible_for'] = Course.objects.filter(responsibles__in=[main_user, other_user]).order_by('semester__created_at', 'name_de')
    merged_user['contributions'] = Contribution.objects.filter(contributor__in=[main_user, other_user]).order_by('evaluation__course__semester__created_at', 'evaluation__name_de')
    merged_user['evaluations_participating_in'] = Evaluation.objects.filter(participants__in=[main_user, other_user]).order_by('course__semester__created_at', 'name_de')
    merged_user['evaluations_voted_for'] = Evaluation.objects.filter(voters__in=[main_user, other_user]).order_by('course__semester__created_at', 'name_de')
    merged_user['reward_point_grantings'] = (main_user.reward_point_grantings.all() or other_user.reward_point_grantings.all())
    merged_user['reward_point_redemptions'] = (main_user.reward_point_redemptions.all() or other_user.reward_point_redemptions.all())
    if (preview or errors):
        return (merged_user, errors, warnings)
    for course in Course.objects.filter(responsibles__in=[other_user]):
        responsibles = list(course.responsibles.all())
        responsibles.remove(other_user)
        responsibles.append(main_user)
        course.responsibles.set(responsibles)
    GradeDocument.objects.filter(last_modified_user=other_user).update(last_modified_user=main_user)
    other_user.email = 
    other_user.save()
    for (key, value) in merged_user.items():
        attr = getattr(main_user, key)
        if hasattr(attr, 'set'):
            attr.set(value)
        else:
            setattr(main_user, key, value)
    main_user.save()
    other_user.reward_point_grantings.all().delete()
    other_user.reward_point_redemptions.all().delete()
    LogEntry.objects.filter(user=other_user).update(user=main_user)
    evaluations = Evaluation.objects.filter(contributions__contributor=main_user, state__in=STATES_WITH_RESULTS_CACHING).distinct()
    for evaluation in evaluations:
        cache_results(evaluation)
    other_user.delete()
    return (merged_user, errors, warnings)