Repository: carpentries/amy

Issue:
open training should be an option for assigning training requests to ttt events
Related to https://github.com/swcarpentry/amy/issues/1055

When matching training requests to a ttt event from the training request page, there is no check box to mark them as open training applicants. 

![screen shot 2018-10-02 at 2 28 07 pm](https://user-images.githubusercontent.com/19176319/46378088-67251680-c64f-11e8-93fe-19dbbff5b4c3.png)

This functionality **does** negatively affect usability as @sheraaron's workflow involves going to the request page and assigning people to trainings in bulk.

@karenword @maneesha 


Discussion:

Resolving patch:
diff --git a/workshops/forms.py b/workshops/forms.py
--- a/workshops/forms.py
+++ b/workshops/forms.py
@@ -1850,11 +1850,18 @@ class BulkMatchTrainingRequestForm(forms.Form):
         widget=ModelSelect2(url='membership-lookup'),
     )
 
+    seat_open_training = forms.BooleanField(
+        label='Open training seat',
+        required=False,
+        help_text="Some TTT events allow for open training; check this field "
+                  "to count this person into open applications.",
+    )
+
     helper = BootstrapHelper(add_submit_button=False,
                              form_tag=False,
                              add_cancel_button=False)
     helper.layout = Layout(
-        'event', 'seat_membership',
+        'event', 'seat_membership', 'seat_open_training',
     )
     helper.add_input(
         Submit(
@@ -1873,12 +1880,29 @@ class BulkMatchTrainingRequestForm(forms.Form):
     def clean(self):
         super().clean()
 
+        event = self.cleaned_data['event']
+        member_site = self.cleaned_data['seat_membership']
+        open_training = self.cleaned_data['seat_open_training']
+
         if any(r.person is None for r in self.cleaned_data.get('requests', [])):
             raise ValidationError('Some of the requests are not matched '
                                   'to a trainee yet. Before matching them to '
                                   'a training, you need to accept them '
                                   'and match with a trainee.')
 
+        if member_site and open_training:
+            raise ValidationError(
+                "Cannot simultaneously match as open training and use "
+                "a Membership instructor training seat."
+            )
+
+        if open_training and not event.open_TTT_applications:
+            raise ValidationError({
+                'seat_open_training': ValidationError(
+                    'Selected TTT event does not allow for open training seats.'
+                ),
+            })
+
 
 class MatchTrainingRequestForm(forms.Form):
     """Form used to match a training request to a Person."""
diff --git a/workshops/views.py b/workshops/views.py
--- a/workshops/views.py
+++ b/workshops/views.py
@@ -3144,6 +3144,7 @@ def all_trainingrequests(request):
 
         if match_form.is_valid():
             member_site = match_form.cleaned_data['seat_membership']
+            open_seat = match_form.cleaned_data['seat_open_training']
 
             # Perform bulk match
             for r in match_form.cleaned_data['requests']:
@@ -3156,7 +3157,9 @@ def all_trainingrequests(request):
                     person=r.person,
                     role=Role.objects.get(name='learner'),
                     event=match_form.cleaned_data['event'],
-                    seat_membership=member_site)
+                    seat_membership=member_site,
+                    seat_open_training=open_seat,
+                )
 
             requests_count = len(match_form.cleaned_data['requests'])
             today = datetime.date.today()


Test patch: