Repository: e-valuation/EvaP

Issue:
Suggest user merge if email address already exists
As a manager, when changing a user's email address to an existing email address of another user, an error is shown in the user form.
In addition, a warning message should be shown on top of the page, suggesting to merge the two users with a link to the merge page (where the user currently edited will be the main user).


Discussion:
We should probably wait for #1780 to see what we can reuse then :)
The two issues are mostly independent, so no need to wait.

Resolving patch:
diff --git a/evap/staff/forms.py b/evap/staff/forms.py
--- a/evap/staff/forms.py
+++ b/evap/staff/forms.py
@@ -957,6 +957,7 @@ class Meta:
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
+        self.user_with_same_email = None
         evaluations_in_active_semester = Evaluation.objects.filter(course__semester=Semester.active_semester())
         excludes = [x.id for x in evaluations_in_active_semester if x.is_single_result]
         evaluations_in_active_semester = evaluations_in_active_semester.exclude(id__in=excludes)
@@ -998,7 +999,8 @@ def clean_email(self):
         if self.instance and self.instance.pk:
             user_with_same_email = user_with_same_email.exclude(pk=self.instance.pk)
 
-        if user_with_same_email.exists():
+        if user_with_same_email:
+            self.user_with_same_email = user_with_same_email.first()
             raise forms.ValidationError(_("A user with the email '%s' already exists") % email)
         return email
 
diff --git a/evap/staff/views.py b/evap/staff/views.py
--- a/evap/staff/views.py
+++ b/evap/staff/views.py
@@ -2211,6 +2211,7 @@ def notify_reward_points(grantings, **_kwargs):
             "evaluations_contributing_to": evaluations_contributing_to,
             "has_due_evaluations": bool(user.get_sorted_due_evaluations()),
             "user_id": user_id,
+            "user_with_same_email": form.user_with_same_email,
         },
     )
 


Test patch:
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
@@ -272,12 +272,22 @@ def setUpTestData(cls):
         cls.testuser = baker.make(UserProfile)
         cls.url = f"/staff/user/{cls.testuser.pk}/edit"
 
-    def test_questionnaire_edit(self):
+    def test_user_edit(self):
         page = self.app.get(self.url, user=self.manager, status=200)
         form = page.forms["user-form"]
-        form["email"] = "lfo9e7bmxp1xi@institution.example.com"
+        form["email"] = "test@institution.example.com"
         form.submit()
-        self.assertTrue(UserProfile.objects.filter(email="lfo9e7bmxp1xi@institution.example.com").exists())
+        self.assertTrue(UserProfile.objects.filter(email="test@institution.example.com").exists())
+
+    def test_user_edit_duplicate_email(self):
+        second_user = baker.make(UserProfile, email="test@institution.example.com")
+        page = self.app.get(self.url, user=self.manager, status=200)
+        form = page.forms["user-form"]
+        form["email"] = second_user.email
+        page = form.submit()
+        self.assertContains(
+            page, "A user with this email address already exists. You probably want to merge the users."
+        )
 
     @patch("evap.staff.forms.remove_user_from_represented_and_ccing_users")
     def test_inactive_edit(self, mock_remove):