Repository: apluslms/a-plus

Issue:
deviations: columns Granter and Grant time are missing info
Kun monta saman henkilön poikkeamaa on "taiteltu plussan taakse", ei Granter- ja Grant time -sarakkeissa lue mitään edes siinä tapauksessa, että aika ja myöntäjä olisivat kaikilla piilotetuilla riveillä samat. 
Jos tiedot ovat kaikille saman plussan takana olevilla identtiset, voisivat ne näkyä.
(e.g. https://plus.cs.aalto.fi/o1/2021/teachers/deadline-deviations/)

--------------------------------------

In English
> It is extremely common that a student gets a deadline extension for multiple exercises at once. In such cases, the DL extensions table folds the exercises into one entry so that the view doesn’t get cluttered. That’s great, but it would be nice if the metadata — who granted the extension? when? — was shown for the folded items as well (assuming it’s one person and a single time, which should almost always be the case). This does not currently happen. The columns on the right are blank here:

https://github.com/apluslms/a-plus/issues/1121#issue-1517628848


Discussion:

Resolving patch:
diff --git a/deviations/viewbase.py b/deviations/viewbase.py
--- a/deviations/viewbase.py
+++ b/deviations/viewbase.py
@@ -218,6 +218,7 @@ def form_valid(self, form: forms.BaseForm) -> HttpResponse:
         return super().form_valid(form)
 
 
+# pylint: disable-next=too-many-locals
 def get_deviation_groups(
         all_deviations: models.QuerySet[SubmissionRuleDeviation],
         ) -> Iterable[Tuple[List[SubmissionRuleDeviation], bool, Optional[str]]]:
@@ -270,16 +271,23 @@ def get_deviation_groups(
     for (_submitter, module), deviations_iter in deviation_groups:
         deviations = list(deviations_iter)
         can_group = True
+        show_granter = True
         if len(deviations) < 2:
             # Group must have at least 2 deviations.
             can_group = False
         else:
             group_exercises = set()
             # Check that the same deviation has been granted for all exercises.
+            first_granter = deviations[0].granter.id
             for deviation in deviations:
                 if not deviation.is_groupable(deviations[0]):
                     can_group = False
-                    break
+                    if not show_granter:
+                        break
+                if deviation.granter.id != first_granter:
+                    show_granter = False
+                    if not can_group:
+                        break
                 group_exercises.add(deviation.exercise.id)
             else:
                 if len(group_exercises) != exercise_count_by_module[module.id]:
@@ -288,7 +296,7 @@ def get_deviation_groups(
                     # are some exercises that don't have a deviation.
                     can_group = False
         group_id = f"{deviations[0].submitter.id}.{module.id}" if can_group else None
-        yield (deviations, can_group, group_id)
+        yield (deviations, can_group, group_id, show_granter)
 
 
 def get_exercises(form_data: Dict[str, Any]) -> models.QuerySet[BaseExercise]:


Test patch:
diff --git a/deviations/tests.py b/deviations/tests.py
--- a/deviations/tests.py
+++ b/deviations/tests.py
@@ -319,11 +319,11 @@ def test_get_deviation_groups(self):
         # The deviations of user 1 can't be grouped because of different extra minutes
         # The deviations of user 2 can't be grouped because there is only one deviation
         groups = list(get_deviation_groups(DeadlineRuleDeviation.objects.all()))
-        deviations, can_group, group_id = groups[0]
+        deviations, can_group, group_id, _ = groups[0]
         self.assertEqual(len(deviations), 2)
         self.assertFalse(can_group)
         self.assertIsNone(group_id)
-        deviations, can_group, group_id = groups[1]
+        deviations, can_group, group_id, _ = groups[1]
         self.assertEqual(len(deviations), 1)
         self.assertFalse(can_group)
         self.assertIsNone(group_id)
@@ -337,7 +337,7 @@ def test_get_deviation_groups(self):
 
         # The deviations of user 1 can now be grouped
         groups = list(get_deviation_groups(DeadlineRuleDeviation.objects.all()))
-        deviations, can_group, group_id = groups[0]
+        deviations, can_group, group_id, _ = groups[0]
         self.assertEqual(len(deviations), 2)
         self.assertTrue(can_group)
         self.assertEqual(group_id, f'{self.user.id}.{self.course_module.id}')
@@ -353,7 +353,7 @@ def test_get_deviation_groups(self):
 
         # The deviations of user 1 can no longer be grouped because there is an exercise without a deviation
         groups = list(get_deviation_groups(DeadlineRuleDeviation.objects.all()))
-        deviations, can_group, group_id = groups[0]
+        deviations, can_group, group_id, _ = groups[0]
         self.assertEqual(len(deviations), 2)
         self.assertFalse(can_group)
         self.assertIsNone(group_id)