From 6248706959f1a7407fc9f9b890aa633a7604c0de Mon Sep 17 00:00:00 2001
From: Robert Sparks <rjsparks@nostrum.com>
Date: Thu, 12 Mar 2020 19:12:57 +0000
Subject: [PATCH] Make required AD approval of virtual interims configurable.
 Fixes #2912. Commit ready for merge.  - Legacy-Id: 17425

---
 ietf/meeting/forms.py       |  6 +++---
 ietf/meeting/helpers.py     |  2 +-
 ietf/meeting/tests_views.py | 22 +++++++++++++++++-----
 ietf/meeting/views.py       | 12 +++++++-----
 ietf/settings.py            |  1 +
 5 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/ietf/meeting/forms.py b/ietf/meeting/forms.py
index 9028a3eaa..bec32a1ef 100644
--- a/ietf/meeting/forms.py
+++ b/ietf/meeting/forms.py
@@ -1,4 +1,4 @@
-# Copyright The IETF Trust 2016-2019, All Rights Reserved
+# Copyright The IETF Trust 2016-2020, All Rights Reserved
 # -*- coding: utf-8 -*-
 
 
@@ -218,8 +218,8 @@ class InterimSessionModelForm(forms.ModelForm):
             self.user = kwargs.pop('user')
         if 'group' in kwargs:
             self.group = kwargs.pop('group')
-        if 'is_approved_or_virtual' in kwargs:
-            self.is_approved_or_virtual = kwargs.pop('is_approved_or_virtual')
+        if 'requires_approval' in kwargs:
+            self.requires_approval = kwargs.pop('requires_approval')
         super(InterimSessionModelForm, self).__init__(*args, **kwargs)
         self.is_edit = bool(self.instance.pk)
         # setup fields that aren't intrinsic to the Session object
diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py
index e5c77a10e..f07f83db0 100644
--- a/ietf/meeting/helpers.py
+++ b/ietf/meeting/helpers.py
@@ -602,7 +602,7 @@ def sessions_post_save(request, forms):
             continue
 
         if form.instance.pk is not None and not SchedulingEvent.objects.filter(session=form.instance).exists():
-            if form.is_approved_or_virtual:
+            if not form.requires_approval:
                 status_id = 'scheda'
             else:
                 status_id = 'apprw'
diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py
index e1ebd3598..ade11103c 100644
--- a/ietf/meeting/tests_views.py
+++ b/ietf/meeting/tests_views.py
@@ -23,7 +23,7 @@ from six.moves.urllib.parse import urlparse
 from django.urls import reverse as urlreverse
 from django.conf import settings
 from django.contrib.auth.models import User
-from django.test import Client
+from django.test import Client, override_settings
 from django.db.models import F
 
 import debug           # pyflakes:ignore
@@ -39,7 +39,6 @@ from ietf.meeting.models import Session, TimeSlot, Meeting, SchedTimeSessAssignm
 from ietf.meeting.test_data import make_meeting_test_data, make_interim_meeting
 from ietf.meeting.utils import finalize, condition_slide_order
 from ietf.meeting.utils import add_event_info_to_session_qs
-from ietf.meeting.utils import current_session_status
 from ietf.meeting.views import session_draft_list
 from ietf.name.models import SessionStatusName, ImportantDateName
 from ietf.utils.decorators import skip_coverage
@@ -1398,7 +1397,7 @@ class InterimTests(TestCase):
         count = person.role_set.filter(name='chair',group__type__in=('wg', 'rg'), group__state__in=('active', 'proposed')).count()
         self.assertEqual(count, len(q("#id_group option")) - 1)  # -1 for options placeholder
 
-    def test_interim_request_single_virtual(self):
+    def do_interim_request_single_virtual(self):
         make_meeting_test_data()
         group = Group.objects.get(acronym='mars')
         date = datetime.date.today() + datetime.timedelta(days=30)
@@ -1440,7 +1439,6 @@ class InterimTests(TestCase):
         session = meeting.session_set.first()
         self.assertEqual(session.remote_instructions,remote_instructions)
         self.assertEqual(session.agenda_note,agenda_note)
-        self.assertEqual(current_session_status(session).slug,'scheda')
         timeslot = session.official_timeslotassignment().timeslot
         self.assertEqual(timeslot.time,dt)
         self.assertEqual(timeslot.duration,duration)
@@ -1451,8 +1449,22 @@ class InterimTests(TestCase):
         self.assertTrue(os.path.exists(path))
         # check notice to secretariat
         self.assertEqual(len(outbox), length_before + 1)
-        self.assertIn('interim meeting ready for announcement', outbox[-1]['Subject'])
+        return meeting
+
+    @override_settings(VIRTUAL_INTERIMS_REQUIRE_APPROVAL = True)
+    def test_interim_request_single_virtual_settings_approval_required(self):
+        meeting = self.do_interim_request_single_virtual()
+        self.assertEqual(meeting.session_set.last().schedulingevent_set.last().status_id,'apprw')
+        self.assertIn('New Interim Meeting Request', outbox[-1]['Subject'])
+        self.assertIn('session-request@ietf.org', outbox[-1]['To'])
+        self.assertIn('aread@example.org', outbox[-1]['Cc'])
+
+    @override_settings(VIRTUAL_INTERIMS_REQUIRE_APPROVAL = False)
+    def test_interim_request_single_virtual_settings_approval_not_required(self):
+        meeting = self.do_interim_request_single_virtual()
+        self.assertEqual(meeting.session_set.last().schedulingevent_set.last().status_id,'scheda')
         self.assertIn('iesg-secretary@ietf.org', outbox[-1]['To'])
+        self.assertIn('interim meeting ready for announcement', outbox[-1]['Subject'])
 
     def test_interim_request_single_in_person(self):
         make_meeting_test_data()
diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py
index e4c7a6c55..45ee294c4 100644
--- a/ietf/meeting/views.py
+++ b/ietf/meeting/views.py
@@ -2017,6 +2017,8 @@ def interim_request(request):
             is_virtual = form.is_virtual()
             meeting_type = form.cleaned_data.get('meeting_type')
 
+            requires_approval = not ( is_approved or ( is_virtual and not settings.VIRTUAL_INTERIMS_REQUIRE_APPROVAL ))
+
             # pre create meeting
             if meeting_type in ('single', 'multi-day'):
                 meeting = form.save(date=get_earliest_session_date(formset))
@@ -2026,13 +2028,13 @@ def interim_request(request):
                     InterimSessionModelForm.__init__,
                     user=request.user,
                     group=group,
-                    is_approved_or_virtual=(is_approved or is_virtual))
+                    requires_approval=requires_approval)
                 formset = SessionFormset(instance=meeting, data=request.POST)
                 formset.is_valid()
                 formset.save()
                 sessions_post_save(request, formset)
 
-                if not (is_approved or is_virtual):
+                if requires_approval:
                     send_interim_approval_request(meetings=[meeting])
                 elif not has_role(request.user, 'Secretariat'):
                     send_interim_announcement_request(meeting=meeting)
@@ -2046,7 +2048,7 @@ def interim_request(request):
                     InterimSessionModelForm.__init__,
                     user=request.user,
                     group=group,
-                    is_approved_or_virtual=(is_approved or is_virtual))
+                    requires_approval=requires_approval)
                 formset = SessionFormset(instance=Meeting(), data=request.POST)
                 formset.is_valid()  # re-validate
                 for session_form in formset.forms:
@@ -2063,7 +2065,7 @@ def interim_request(request):
                     series.append(meeting)
                     sessions_post_save(request, [session_form])
 
-                if not (is_approved or is_virtual):
+                if requires_approval:
                     send_interim_approval_request(meetings=series)
                 elif not has_role(request.user, 'Secretariat'):
                     send_interim_announcement_request(meeting=meeting)
@@ -2191,7 +2193,7 @@ def interim_request_edit(request, number):
             InterimSessionModelForm.__init__,
             user=request.user,
             group=group,
-            is_approved_or_virtual=is_approved)
+            requires_approval= not is_approved)
 
         formset = SessionFormset(instance=meeting, data=request.POST)
 
diff --git a/ietf/settings.py b/ietf/settings.py
index 88c7ebaed..39cd60a53 100644
--- a/ietf/settings.py
+++ b/ietf/settings.py
@@ -764,6 +764,7 @@ IDSUBMIT_ANNOUNCE_LIST_EMAIL = 'i-d-announce@ietf.org'
 
 # Interim Meeting Tool settings
 INTERIM_ANNOUNCE_FROM_EMAIL = 'IESG Secretary <iesg-secretary@ietf.org>'
+VIRTUAL_INTERIMS_REQUIRE_APPROVAL = True
 
 # Days from meeting to day of cut off dates on submit -- cutoff_time_utc is added to this
 IDSUBMIT_DEFAULT_CUTOFF_DAY_OFFSET_00 = 13