Repository: adfinis/timed-backend

Issue:
editing rejected report results in weird mail
# Issue
At first I had a Report actually rejected and got this mail:
```
Some of your reports have been rejected by a reviewer. Please get in contact
with them to clarify the reports. Most likely, you will just need to move
the reports to the correct project / task.

Reviewer: <Actualy Reviewer>


Date: mm/dd/yyyy
Duration: 7:00 (h:mm)
Task: x > y > z
Comment: <comment>
---
```
Then after i edited the Report i got this mail:
```
Some of your reports have been rejected by a reviewer. Please get in contact
with them to clarify the reports. Most likely, you will just need to move
the reports to the correct project / task.

Reviewer: <Myself>


Date: mm/dd/yyyy
Duration: 7:00 (h:mm)
Task: x > y > z
Comment: <edited comment>
---
```
After every edit i got another mail, where I am marked as the reviewer.




Discussion:

Resolving patch:
diff --git a/timed/tracking/serializers.py b/timed/tracking/serializers.py
--- a/timed/tracking/serializers.py
+++ b/timed/tracking/serializers.py
@@ -131,7 +131,9 @@ def validate_rejected(self, value):
         """Only reviewers are allowed to change rejected field."""
         if self.instance is not None:
             user = self.context["request"].user
-            if not user.is_reviewer and (self.instance.rejected != value):
+            if (
+                not user.is_reviewer or self.instance.user == user
+            ) and self.instance.rejected != value:
                 raise ValidationError(_("Only reviewers may reject reports."))
 
         return value
diff --git a/timed/tracking/views.py b/timed/tracking/views.py
--- a/timed/tracking/views.py
+++ b/timed/tracking/views.py
@@ -165,16 +165,18 @@ def update(self, request, *args, **kwargs):
         serializer = self.get_serializer(instance, data=request.data, partial=partial)
         serializer.is_valid(raise_exception=True)
 
-        fields = {
-            key: value
-            for key, value in serializer.validated_data.items()
-            # value equal None means do not touch
-            if value is not None
-        }
-        if fields and request.user != instance.user:
-            tasks.notify_user_changed_report(instance, fields, request.user)
-        if fields.get("rejected"):
-            tasks.notify_user_rejected_report(instance, request.user)
+        if request.user != instance.user:
+            # send a notification only when the user is updating someone else's report
+            fields = {
+                key: value
+                for key, value in serializer.validated_data.items()
+                # value equal None means do not touch
+                if value is not None
+            }
+            if fields:
+                tasks.notify_user_changed_report(instance, fields, request.user)
+            if fields.get("rejected"):
+                tasks.notify_user_rejected_report(instance, request.user)
 
         return super().update(request, *args, **kwargs)
 


Test patch:
diff --git a/timed/tracking/tests/test_report.py b/timed/tracking/tests/test_report.py
--- a/timed/tracking/tests/test_report.py
+++ b/timed/tracking/tests/test_report.py
@@ -1698,7 +1698,7 @@ def test_report_list_no_employment(
 @pytest.mark.parametrize(
     "report_owner, reviewer, expected, mail_count, status_code",
     [
-        (True, True, True, 1, status.HTTP_200_OK),
+        (True, True, False, 0, status.HTTP_400_BAD_REQUEST),
         (False, True, True, 1, status.HTTP_200_OK),
         (True, False, False, 0, status.HTTP_400_BAD_REQUEST),
         (False, False, False, 0, status.HTTP_403_FORBIDDEN),
@@ -1744,6 +1744,29 @@ def test_report_reject(
         assert mail.to[0] == user2.email if not report_owner else user
 
 
+def test_report_update_rejected_owner(
+    internal_employee_client, report_factory, mailoutbox
+):
+    user = internal_employee_client.user
+    report = report_factory.create(user=user, rejected=True)
+
+    data = {
+        "data": {
+            "type": "reports",
+            "id": report.id,
+            "attributes": {
+                "comment": "foobar",
+                "rejected": True,
+            },
+        }
+    }
+
+    url = reverse("report-detail", args=[report.id])
+    response = internal_employee_client.patch(url, data)
+    assert response.status_code == status.HTTP_200_OK
+    assert len(mailoutbox) == 0
+
+
 def test_report_reject_multiple_notify(
     internal_employee_client,
     task,