Repository: e-valuation/EvaP

Issue:
Copy participants from other course
It should be possible to not only import participants to a course from an excel sheet, but also to copy the participants from another course.



Discussion:
what's the use case for this?

e.g. courses for participants in bachelor projects. they participate in multiple preparation seminars that are not part of the enrollment data. after manually adding them all to one course it would be nice to just be able to copy them instead of adding them one by one again.

Actually, copying a whole course would probably be even better. Or maybe not. It depends.
Adding the participants is definitely the most work, so copying them might actually be enough, because all the other stuff might be different.


Resolving patch:
diff --git a/evap/staff/forms.py b/evap/staff/forms.py
--- a/evap/staff/forms.py
+++ b/evap/staff/forms.py
@@ -31,7 +31,26 @@ class ImportForm(forms.Form):
 
 
 class UserImportForm(forms.Form):
-    excel_file = forms.FileField(label=_("Excel file"))
+    excel_file = forms.FileField(label=_("Import from Excel file"), required=False)
+    course = forms.ModelChoiceField(Course.objects.all(), empty_label='<empty>', required=False, label=_("Copy from Course"))
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        # Here we split the courses by semester and create supergroups for them. We also make sure to include an empty option.
+        choices = [('', '<empty>')]
+        for semester in Semester.objects.all():
+            course_choices = [(course.pk, course.name) for course in Course.objects.filter(semester=semester)]
+            if course_choices:
+                choices += [(semester.name, course_choices)]
+
+        self.fields['course'].choices = choices
+
+    def clean(self):
+        if self.cleaned_data['course'] and self.cleaned_data['excel_file']:
+            raise ValidationError('Please select only one of course or Excel file.')
+        if not self.cleaned_data['course'] and not self.cleaned_data['excel_file']:
+            raise ValidationError('Please select either course or Excel File.')
 
 
 class UserBulkDeleteForm(forms.Form):
diff --git a/evap/staff/views.py b/evap/staff/views.py
--- a/evap/staff/views.py
+++ b/evap/staff/views.py
@@ -635,11 +635,20 @@ def course_participant_import(request, semester_id, course_id):
 
         # Extract data from form.
         excel_file = form.cleaned_data['excel_file']
+        import_course = form.cleaned_data['course']
 
         test_run = operation == 'test'
 
-        # Parse table.
-        imported_users = UserImporter.process(request, excel_file, test_run)
+        # Import user from either excel file or other course
+        imported_users = []
+        if excel_file:
+            imported_users = UserImporter.process(request, excel_file, test_run)
+        else:
+            imported_users = import_course.participants.all()
+
+        # Print message for test run.
+        if test_run and imported_users:
+            messages.success(request, "%d Participants would be added to course %s" % (len(imported_users), course.name))
 
         # Test run, or an error occurred while parsing -> stay and display error.
         if test_run or not imported_users:


Test patch: