From 1492d2f5e761de2d7d43e0ca44d7a83edc690a3b Mon Sep 17 00:00:00 2001
From: Dominik Seeger <dominik.seeger@stud.uni-goettingen.de>
Date: Tue, 9 Jul 2019 18:32:24 +0200
Subject: [PATCH 1/5] added dedicated field for reviewer validation

---
 core/migrations/0018_auto_20190709_1526.py | 23 ++++++++++++++++++++++
 core/models/feedback.py                    |  3 +++
 core/views/feedback.py                     | 15 +++++++++-----
 3 files changed, 36 insertions(+), 5 deletions(-)
 create mode 100644 core/migrations/0018_auto_20190709_1526.py

diff --git a/core/migrations/0018_auto_20190709_1526.py b/core/migrations/0018_auto_20190709_1526.py
new file mode 100644
index 00000000..468d2442
--- /dev/null
+++ b/core/migrations/0018_auto_20190709_1526.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2 on 2019-07-09 15:26
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0017_auto_20190604_1631'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='feedback',
+            name='final_by_reviewer',
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AlterField(
+            model_name='feedbacklabel',
+            name='name',
+            field=models.CharField(max_length=50, unique=True),
+        ),
+    ]
diff --git a/core/models/feedback.py b/core/models/feedback.py
index 15eea22c..742f9428 100644
--- a/core/models/feedback.py
+++ b/core/models/feedback.py
@@ -25,10 +25,13 @@ class Feedback(models.Model):
         points a student receives for his submission.
     origin : IntegerField
         Of whom was this feedback originally created. She below for the choices
+    final_by_reviewer: BooleanField
+        Whether or not this feedback was set to final by a reviewer once
     """
     score = models.DecimalField(max_digits=5, decimal_places=2, default=0)
     created = models.DateTimeField(auto_now_add=True)
     is_final = models.BooleanField(default=False)
+    final_by_reviewer = models.BooleanField(default=False)
 
     of_submission = models.OneToOneField(
         Submission,
diff --git a/core/views/feedback.py b/core/views/feedback.py
index 27211eb7..113e1cc8 100644
--- a/core/views/feedback.py
+++ b/core/views/feedback.py
@@ -28,12 +28,13 @@ class FeedbackApiView(
     lookup_url_kwarg = 'submission_pk'
 
     def _tutor_attempts_to_change_final_feedback_of_reviewer(self, serializer):
-        feedback_is_final = serializer.instance.is_final
+        feedback_final_by_reviewer = serializer.instance.final_by_reviewer
         user_is_tutor = self.request.user.role == models.UserAccount.TUTOR
-        authors = serializer.instance.of_submission.meta.feedback_authors
-        set_by_reviewer = authors.filter(
-            role=models.UserAccount.REVIEWER).exists()
-        return feedback_is_final and set_by_reviewer and user_is_tutor
+        return feedback_final_by_reviewer and user_is_tutor
+
+    def _set_final_by_reviewer(self, serializer):
+        feedback_final_by_reviewer = serializer.validated_data.get('is_final', True)
+        serializer.save(final_by_reviewer=feedback_final_by_reviewer)
 
     def _get_implicit_assignment_for_user(self, submission):
         """ Check for tutor if it exists. Not relevant for reviewer """
@@ -96,6 +97,8 @@ class FeedbackApiView(
                 {'For tutors it is not allowed to create feedback final.'},
                 status=status.HTTP_403_FORBIDDEN)
 
+        self._set_final_by_reviewer(serializer)
+
         self.perform_create(serializer)
         return Response(serializer.data,
                         status=status.HTTP_201_CREATED)
@@ -116,6 +119,8 @@ class FeedbackApiView(
             raise PermissionDenied(
                 detail='Cannot set the first feedback final.')
 
+        self._set_final_by_reviewer(serializer)
+
         serializer.save()
         return Response(serializer.data)
 
-- 
GitLab


From d45a5898882f22f24305b82deffe1b0ba0950334 Mon Sep 17 00:00:00 2001
From: Dominik Seeger <dominik.seeger@gmx.net>
Date: Tue, 6 Aug 2019 15:23:28 +0200
Subject: [PATCH 2/5] put the final by reviewer logic in the serializer

---
 core/serializers/feedback.py | 11 ++++++++++-
 core/views/feedback.py       |  8 --------
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/core/serializers/feedback.py b/core/serializers/feedback.py
index 92416e1e..5a6749ec 100644
--- a/core/serializers/feedback.py
+++ b/core/serializers/feedback.py
@@ -7,7 +7,7 @@ from rest_framework import serializers
 from rest_framework.utils import html
 
 from core import models
-from core.models import Feedback
+from core.models import Feedback, UserAccount
 from util.factories import GradyUserFactory
 
 from .generic import DynamicFieldsModelSerializer
@@ -121,8 +121,12 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
         submission = validated_data.pop('of_submission')
         feedback_lines = validated_data.pop('feedback_lines', [])
         labels = validated_data.pop('labels', [])
+        user = UserAccount.objects.get(username=str(self.context['request'].user))
         feedback = Feedback.objects.create(of_submission=submission,
                                            **validated_data)
+        if user.role == UserAccount.REVIEWER:
+            feedback.final_by_reviewer = self.context['request'].data['is_final']
+
         for label in labels:
             feedback.labels.add(label)
 
@@ -141,6 +145,11 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
 
     @transaction.atomic
     def update(self, feedback, validated_data):
+        user = UserAccount.objects.get(username=str(self.context['request'].user))
+
+        if user.role == UserAccount.REVIEWER:
+            feedback.final_by_reviewer = self.context['request'].data['is_final']
+
         for comment in validated_data.pop('feedback_lines', []):
             labels = comment.pop('labels', [])
             comment_instance, _ = models.FeedbackComment.objects.update_or_create(
diff --git a/core/views/feedback.py b/core/views/feedback.py
index 113e1cc8..e7ccfb22 100644
--- a/core/views/feedback.py
+++ b/core/views/feedback.py
@@ -32,10 +32,6 @@ class FeedbackApiView(
         user_is_tutor = self.request.user.role == models.UserAccount.TUTOR
         return feedback_final_by_reviewer and user_is_tutor
 
-    def _set_final_by_reviewer(self, serializer):
-        feedback_final_by_reviewer = serializer.validated_data.get('is_final', True)
-        serializer.save(final_by_reviewer=feedback_final_by_reviewer)
-
     def _get_implicit_assignment_for_user(self, submission):
         """ Check for tutor if it exists. Not relevant for reviewer """
         try:
@@ -97,8 +93,6 @@ class FeedbackApiView(
                 {'For tutors it is not allowed to create feedback final.'},
                 status=status.HTTP_403_FORBIDDEN)
 
-        self._set_final_by_reviewer(serializer)
-
         self.perform_create(serializer)
         return Response(serializer.data,
                         status=status.HTTP_201_CREATED)
@@ -119,8 +113,6 @@ class FeedbackApiView(
             raise PermissionDenied(
                 detail='Cannot set the first feedback final.')
 
-        self._set_final_by_reviewer(serializer)
-
         serializer.save()
         return Response(serializer.data)
 
-- 
GitLab


From a18c5292b8d61163db2f73f83d2da7f4476c0d70 Mon Sep 17 00:00:00 2001
From: "dominik.seeger" <dominik.seeger@stud.uni-goettingen.de>
Date: Fri, 9 Aug 2019 13:03:04 +0200
Subject: [PATCH 3/5] Apply suggestion to core/serializers/feedback.py

---
 core/serializers/feedback.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/serializers/feedback.py b/core/serializers/feedback.py
index 5a6749ec..d8316e66 100644
--- a/core/serializers/feedback.py
+++ b/core/serializers/feedback.py
@@ -145,7 +145,7 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
 
     @transaction.atomic
     def update(self, feedback, validated_data):
-        user = UserAccount.objects.get(username=str(self.context['request'].user))
+user = self.context['request'].user
 
         if user.role == UserAccount.REVIEWER:
             feedback.final_by_reviewer = self.context['request'].data['is_final']
-- 
GitLab


From 4f78a5550eb2d5c54c05853319282e4b62c09dab Mon Sep 17 00:00:00 2001
From: "dominik.seeger" <dominik.seeger@stud.uni-goettingen.de>
Date: Fri, 9 Aug 2019 13:03:25 +0200
Subject: [PATCH 4/5] Apply suggestion to core/serializers/feedback.py

---
 core/serializers/feedback.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/serializers/feedback.py b/core/serializers/feedback.py
index d8316e66..32ed137f 100644
--- a/core/serializers/feedback.py
+++ b/core/serializers/feedback.py
@@ -121,7 +121,7 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
         submission = validated_data.pop('of_submission')
         feedback_lines = validated_data.pop('feedback_lines', [])
         labels = validated_data.pop('labels', [])
-        user = UserAccount.objects.get(username=str(self.context['request'].user))
+        user = self.context['request'].user
         feedback = Feedback.objects.create(of_submission=submission,
                                            **validated_data)
         if user.role == UserAccount.REVIEWER:
-- 
GitLab


From 6191b7855bec05a648eef90e3ab7e19d03388e09 Mon Sep 17 00:00:00 2001
From: Dominik Seeger <dominik.seeger@gmx.net>
Date: Wed, 14 Aug 2019 12:21:47 +0200
Subject: [PATCH 5/5] fixed indentation

---
 core/serializers/feedback.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/serializers/feedback.py b/core/serializers/feedback.py
index 32ed137f..da0d45e5 100644
--- a/core/serializers/feedback.py
+++ b/core/serializers/feedback.py
@@ -145,7 +145,7 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
 
     @transaction.atomic
     def update(self, feedback, validated_data):
-user = self.context['request'].user
+        user = self.context['request'].user
 
         if user.role == UserAccount.REVIEWER:
             feedback.final_by_reviewer = self.context['request'].data['is_final']
-- 
GitLab