Repository: e-valuation/EvaP

Issue:
Due evaluations ordering
The reminder message about due evaluations (management command `send_reminders`) sorts them by the number of remaining days. A second ordering level should be added, ordering evaluations with the same number of remaining days by their full name.


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
@@ -1,5 +1,4 @@
 import logging
-import operator
 import secrets
 import uuid
 from collections import defaultdict, namedtuple
@@ -1711,15 +1710,13 @@ def get_sorted_evaluations_voted_for(self):
         return self.evaluations_voted_for.order_by("course__semester__created_at", "name_de")
 
     def get_sorted_due_evaluations(self):
-        due_evaluations = dict()
-        for evaluation in Evaluation.objects.filter(participants=self, state=Evaluation.State.IN_EVALUATION).exclude(
-            voters=self
-        ):
-            due_evaluations[evaluation] = (evaluation.vote_end_date - date.today()).days
-
-        # Sort evaluations by number of days left for evaluation and bring them to following format:
-        # [(evaluation, due_in_days), ...]
-        return sorted(due_evaluations.items(), key=operator.itemgetter(1))
+        evaluations_and_days_left = (
+            (evaluation, evaluation.days_left_for_evaluation)
+            for evaluation in Evaluation.objects.filter(
+                participants=self, state=Evaluation.State.IN_EVALUATION
+            ).exclude(voters=self)
+        )
+        return sorted(evaluations_and_days_left, key=lambda tup: (tup[1], tup[0].full_name))
 
 
 def validate_template(value):


Test patch:
diff --git a/evap/evaluation/tests/test_models.py b/evap/evaluation/tests/test_models.py
--- a/evap/evaluation/tests/test_models.py
+++ b/evap/evaluation/tests/test_models.py
@@ -627,6 +627,39 @@ def test_email_domain_replacement(self):
         user = baker.make(UserProfile, email="test@example.com")
         self.assertEqual(user.email, "test@institution.com")
 
+    def test_get_sorted_due_evaluations(self):
+        student = baker.make(UserProfile, email="student@example.com")
+        course = baker.make(Course)
+        evaluation1 = baker.make(
+            Evaluation,
+            course=course,
+            name_en="C",
+            name_de="C",
+            vote_end_date=date.today(),
+            state=Evaluation.State.IN_EVALUATION,
+            participants=[student],
+        )
+        evaluation2 = baker.make(
+            Evaluation,
+            course=course,
+            name_en="B",
+            name_de="B",
+            vote_end_date=date.today(),
+            state=Evaluation.State.IN_EVALUATION,
+            participants=[student],
+        )
+        evaluation3 = baker.make(
+            Evaluation,
+            course=course,
+            name_en="A",
+            name_de="A",
+            vote_end_date=date.today() + timedelta(days=1),
+            state=Evaluation.State.IN_EVALUATION,
+            participants=[student],
+        )
+        sorted_evaluations = student.get_sorted_due_evaluations()
+        self.assertEqual(sorted_evaluations, [(evaluation2, 0), (evaluation1, 0), (evaluation3, 1)])
+
 
 class ParticipationArchivingTests(TestCase):
     @classmethod