Repository: e-valuation/EvaP

Issue:
Bulk deletion
Change bulk deletion to use a list of users that should **not** be deleted. This will then delete all users who can be deleted and are not in this list.


Discussion:

Resolving patch:
diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py
--- a/evap/evaluation/models.py
+++ b/evap/evaluation/models.py
@@ -942,9 +942,9 @@ def can_staff_delete(self):
             return False
         if self.is_contributor or self.is_grade_publisher or self.is_staff or self.is_superuser:
             return False
-        if any(not user.can_staff_delete() for user in self.represented_users.all()):
+        if any(not user.can_staff_delete for user in self.represented_users.all()):
             return False
-        if any(not user.can_staff_delete() for user in self.ccing_users.all()):
+        if any(not user.can_staff_delete for user in self.ccing_users.all()):
             return False
         return True
 
diff --git a/evap/staff/tools.py b/evap/staff/tools.py
--- a/evap/staff/tools.py
+++ b/evap/staff/tools.py
@@ -10,6 +10,8 @@
 from django.core.exceptions import SuspiciousOperation
 from django.db import transaction
 from django.conf import settings
+from django.utils.translation import ugettext_lazy as _
+from django.utils.safestring import mark_safe
 
 from evap.evaluation.models import UserProfile, Course, Contribution
 from evap.grades.models import GradeDocument
@@ -76,21 +78,21 @@ def delete_navbar_cache():
 
 def bulk_delete_users(request, username_file, test_run):
     usernames = [u.strip() for u in username_file.readlines()]
-    users = UserProfile.objects.filter(username__in=usernames)
+    users = UserProfile.objects.exclude(username__in=usernames)
     deletable_users = [u for u in users if u.can_staff_delete]
 
-    messages.info(request, 'The uploaded text file contains {} usernames. {} users have been found in the database. '
-                           '{} of those can be deleted.'
-                  .format(len(usernames), len(users), len(deletable_users)))
-    messages.info(request, 'Users to be deleted are:\n{}'
-                  .format('\n'.join([u.username for u in deletable_users])))
+    messages.info(request, _('The uploaded text file contains {} usernames. {} other users have been found in the database. '
+                           '{} of those will be deleted.'
+                  .format(len(usernames), len(users), len(deletable_users))))
+    messages.info(request, mark_safe(_('Users to be deleted are:<br />{}'
+                  .format('<br />'.join([u.username for u in deletable_users])))))
 
     if test_run:
-        messages.info(request, 'No Users were deleted in this test run.')
+        messages.info(request, _('No users were deleted in this test run.'))
     else:
         for user in deletable_users:
             user.delete()
-        messages.info(request, '{} users have been deleted'.format(len(deletable_users)))
+        messages.info(request, _('{} users have been deleted'.format(len(deletable_users))))
 
 
 @transaction.atomic


Test patch:
diff --git a/evap/staff/fixtures/test_user_bulk_delete_file.txt b/evap/staff/fixtures/test_user_bulk_delete_file.txt
--- a/evap/staff/fixtures/test_user_bulk_delete_file.txt
+++ b/evap/staff/fixtures/test_user_bulk_delete_file.txt
@@ -1,4 +1,2 @@
 testuser1
-testuser2
-contributor
 testuserdoesnotexist
diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py
--- a/evap/staff/tests/test_views.py
+++ b/evap/staff/tests/test_views.py
@@ -130,10 +130,11 @@ def test_deletes_users(self):
         # Getting redirected after.
         self.assertEqual(reply.status_code, 302)
 
-        # Assert only these two users got deleted.
-        self.assertEqual(UserProfile.objects.filter(username__in=['testuser1', 'testuser2']).count(), 0)
+        # Assert only one user got deleted.
+        self.assertTrue(UserProfile.objects.filter(username='testuser1').exists())
+        self.assertFalse(UserProfile.objects.filter(username='testuser2').exists())
         self.assertTrue(UserProfile.objects.filter(username='contributor').exists())
-        self.assertEqual(UserProfile.objects.count(), user_count_before - 2)
+        self.assertEqual(UserProfile.objects.count(), user_count_before - 1)
 
 
 # Staff - Semester Views