Repository: e-valuation/EvaP

Issue:
Remove degrees and course types from contributor export header
In the contributor results export file, the header includes "Evaluation", the contributor's name, and all existing degrees and course types.
Instead, only "Evaluation" and the name should be exported.

Exports other than the contributor export should not be modified.


Discussion:
@janno42 With the default testdata, both users `evap` and `contributor` currently only get an empty excel file when pressing the "Export results" button on the contributor index page (which is the button I think this issue is about, right?). This hindered progress with this issue, as it makes it hard to understand the issue (as there is no data row with these headers).

Do we want to update test data to include some results for the user `evap` by default?

@Tillbtn @finger813 Executing the following lines in `./manage.py shell_plus` already made some data show up for me, maybe that's enough for you for now:
```
from model_bakery import baker
e = Evaluation.objects.filter(name_de="Softwarearchitektur").first()
u = UserProfile.objects.filter(email="evap@institution.example.com").first()
c = baker.make(Contribution, evaluation=e, contributor=u)
```
It looks like it isn't necessary that there are any actual results for the contributor.
You can login as `responsible@institution.example.com` to have useful test data.
@richardebeling Adding some data for `contributor` is something we can do in addition.

Resolving patch:
diff --git a/evap/contributor/views.py b/evap/contributor/views.py
--- a/evap/contributor/views.py
+++ b/evap/contributor/views.py
@@ -288,6 +288,7 @@ def export_contributor_results(contributor):
         include_not_enough_voters=True,
         include_unpublished=False,
         contributor=contributor,
+        verbose_heading=False,
     )
     return response
 
diff --git a/evap/results/exporters.py b/evap/results/exporters.py
--- a/evap/results/exporters.py
+++ b/evap/results/exporters.py
@@ -160,18 +160,22 @@ def filter_evaluations(semesters, evaluation_states, degrees, course_types, cont
         return evaluations_with_results, used_questionnaires, course_results_exist
 
     def write_headings_and_evaluation_info(
-        self, evaluations_with_results, semesters, contributor, degrees, course_types
+        self, evaluations_with_results, semesters, contributor, degrees, course_types, verbose_heading
     ):
-        export_name = "Evaluation"
+        export_name = _("Evaluation")
         if contributor:
             export_name += f"\n{contributor.full_name}"
         elif len(semesters) == 1:
             export_name += f"\n{semesters[0].name}"
-        degree_names = [degree.name for degree in Degree.objects.filter(pk__in=degrees)]
-        course_type_names = [course_type.name for course_type in CourseType.objects.filter(pk__in=course_types)]
-        self.write_cell(
-            _("{}\n\n{}\n\n{}").format(export_name, ", ".join(degree_names), ", ".join(course_type_names)), "headline"
-        )
+        if verbose_heading:
+            degree_names = [degree.name for degree in Degree.objects.filter(pk__in=degrees)]
+            course_type_names = [course_type.name for course_type in CourseType.objects.filter(pk__in=course_types)]
+            self.write_cell(
+                f"{export_name}\n\n{', '.join(degree_names)}\n\n{', '.join(course_type_names)}",
+                "headline",
+            )
+        else:
+            self.write_cell(export_name, "headline")
 
         for evaluation, __ in evaluations_with_results:
             title = evaluation.full_name
@@ -285,7 +289,13 @@ def write_questionnaire(self, questionnaire, evaluations_with_results, contribut
 
     # pylint: disable=arguments-differ
     def export_impl(
-        self, semesters, selection_list, include_not_enough_voters=False, include_unpublished=False, contributor=None
+        self,
+        semesters,
+        selection_list,
+        include_not_enough_voters=False,
+        include_unpublished=False,
+        contributor=None,
+        verbose_heading=True,
     ):
         # We want to throw early here, since workbook.save() will throw an IndexError otherwise.
         assert len(selection_list) > 0
@@ -309,7 +319,7 @@ def export_impl(
             )
 
             self.write_headings_and_evaluation_info(
-                evaluations_with_results, semesters, contributor, degrees, course_types
+                evaluations_with_results, semesters, contributor, degrees, course_types, verbose_heading
             )
 
             for questionnaire in used_questionnaires:


Test patch:
diff --git a/evap/contributor/tests/test_views.py b/evap/contributor/tests/test_views.py
--- a/evap/contributor/tests/test_views.py
+++ b/evap/contributor/tests/test_views.py
@@ -1,4 +1,6 @@
+import xlrd
 from django.core import mail
+from django.urls import reverse
 from django_webtest import WebTest
 from model_bakery import baker
 
@@ -284,3 +286,17 @@ def test_display_request_buttons(self):
         page = self.app.get(self.url, user=self.responsible)
         self.assertEqual(page.body.decode().count("Request changes"), 0)
         self.assertEqual(page.body.decode().count("Request creation of new account"), 2)
+
+
+class TestContributorResultsExportView(WebTest):
+    @classmethod
+    def setUpTestData(cls):
+        result = create_evaluation_with_responsible_and_editor()
+        cls.url = reverse("contributor:export")
+        cls.user = result["responsible"]
+
+    def test_concise_header(self):
+        response = self.app.get(self.url, user=self.user)
+
+        workbook = xlrd.open_workbook(file_contents=response.content)
+        self.assertEqual(workbook.sheets()[0].row_values(0)[0], f"Evaluation\n{self.user.full_name}")