Repository: e-valuation/EvaP

Issue:
Allow adding rights for non-contributors
It should be possible to add people to a course who receive editing rights and/or comment visibility rights without being contributors with visible questionnaires.
Allow adding rights for non-contributors
It should be possible to add people to a course who receive editing rights and/or comment visibility rights without being contributors with visible questionnaires.


Discussion:

Resolving patch:
diff --git a/evap/results/views.py b/evap/results/views.py
--- a/evap/results/views.py
+++ b/evap/results/views.py
@@ -63,6 +63,7 @@ def course_detail(request, semester_id, course_id):
     represented_users = list(request.user.represented_users.all())
     represented_users.append(request.user)
 
+    # filter text answers
     for section in sections:
         results = []
         for result in section.results:
@@ -74,7 +75,10 @@ def course_detail(request, semester_id, course_id):
                 results.append(result)
         section.results[:] = results
 
-    # Filter empty sections and group by contributor.
+    # remove empty sections
+    sections = [section for section in sections if section.results]
+
+    # group by contributor
     course_sections = []
     contributor_sections = OrderedDict()
     for section in sections:
diff --git a/evap/staff/forms.py b/evap/staff/forms.py
--- a/evap/staff/forms.py
+++ b/evap/staff/forms.py
@@ -274,9 +274,11 @@ class ContributionForm(forms.ModelForm):
     course = forms.ModelChoiceField(Course.objects.all(), disabled=True, required=False, widget=forms.HiddenInput())
     questionnaires = forms.ModelMultipleChoiceField(
         Questionnaire.objects.filter(is_for_contributors=True, obsolete=False),
+        required=False,
         widget=CheckboxSelectMultiple,
         label=_("Questionnaires")
     )
+    does_not_contribute = forms.BooleanField(required=False, label=_("Does not contribute to course"))
 
     class Meta:
         model = Contribution
@@ -308,10 +310,17 @@ def __init__(self, *args, **kwargs):
         self.fields['questionnaires'].queryset = Questionnaire.objects.filter(is_for_contributors=True).filter(
             Q(obsolete=False) | Q(contributions__course=self.course)).distinct()
 
+        if self.instance.pk:
+            self.fields['does_not_contribute'].initial = not self.instance.questionnaires.exists()
+
         if not self.course.can_staff_edit:
             # form is used as read-only course view
             disable_all_fields(self)
 
+    def clean(self):
+        if not self.cleaned_data.get('does_not_contribute') and not self.cleaned_data.get('questionnaires'):
+            self.add_error('does_not_contribute', _("Select either this option or at least one questionnaire!"))
+
     def save(self, *args, **kwargs):
         responsibility = self.cleaned_data['responsibility']
         is_responsible = responsibility == Contribution.IS_RESPONSIBLE
diff --git a/evap/student/views.py b/evap/student/views.py
--- a/evap/student/views.py
+++ b/evap/student/views.py
@@ -115,14 +115,13 @@ def vote(request, course_id):
     return redirect('student:index')
 
 
-def helper_create_form_group(request, contribution):
-    return list(QuestionsForm(request.POST or None, contribution=contribution, questionnaire=questionnaire) for questionnaire in contribution.questionnaires.all())
-
-
 def helper_create_voting_form_groups(request, contributions):
     form_groups = OrderedDict()
     for contribution in contributions:
-        form_groups[contribution] = helper_create_form_group(request, contribution)
+        questionnaires = contribution.questionnaires.all()
+        if not questionnaires.exists():
+            continue
+        form_groups[contribution] = [QuestionsForm(request.POST or None, contribution=contribution, questionnaire=questionnaire) for questionnaire in questionnaires]
     return form_groups
 
 


Test patch:
diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py
--- a/evap/staff/tests/test_views.py
+++ b/evap/staff/tests/test_views.py
@@ -638,7 +638,8 @@ class TestCoursePreviewView(ViewTest):
     def setUpTestData(cls):
         mommy.make(UserProfile, username='staff', groups=[Group.objects.get(name='Staff')])
         semester = mommy.make(Semester, pk=1)
-        mommy.make(Course, semester=semester, pk=1)
+        course = mommy.make(Course, semester=semester, pk=1)
+        course.general_contribution.questionnaires.set([mommy.make(Questionnaire)])
 
 
 class TestCourseImportPersonsView(ViewTest):
diff --git a/evap/student/tests/test_views.py b/evap/student/tests/test_views.py
--- a/evap/student/tests/test_views.py
+++ b/evap/student/tests/test_views.py
@@ -61,6 +61,7 @@ def test_user_cannot_vote_for_themselves(self):
         student = mommy.make(UserProfile)
 
         course = mommy.make(Course, state='in_evaluation', participants=[student, contributor1])
+        course.general_contribution.questionnaires.set([mommy.make(Questionnaire)])
         questionnaire = mommy.make(Questionnaire)
         mommy.make(Question, questionnaire=questionnaire, type="G")
         mommy.make(Contribution, contributor=contributor1, course=course, questionnaires=[questionnaire])