Merged in [11792] from rcross@amsl.com:

Requests for virtual interim meeting should go directly Scheduled - Waiting for announcement state and an email notification sent to the secretariat.  Fixes issue #1994.
 - Legacy-Id: 11822
Note: SVN reference [11792] has been migrated to Git commit a13b751e1a
This commit is contained in:
Henrik Levkowetz 2016-08-18 15:03:55 +00:00
parent 250af833aa
commit 52c5c0daa0
6 changed files with 34 additions and 19 deletions

View file

@ -28,17 +28,16 @@ export PYTHONPATH="$PWD/.."
echo "Validating..." echo "Validating..."
./manage.py validate ./manage.py validate
echo "Dump tables"
./manage.py sql $apps > tables.sql
export PYTHONPATH=`dirname $PWD` export PYTHONPATH=`dirname $PWD`
module=${PWD##*/} module=${PWD##*/}
export DJANGO_SETTINGS_MODULE=$module.settings export DJANGO_SETTINGS_MODULE=$module.settings
export graph export graph
export title export title
echo "Generate model graph" echo "Generate model graph"
graph="models-with-names-and-events" graph="models-with-names-and-events"
title="New IETF Database schema" title="New IETF Database schema"
modelviz.py --exclude="$proxy,$legacy" --title "$title" $apps > $graph.dot && dot -Tpng $graph.dot > $graph.png ${0%/*}/../ietf/manage.py graph_models --exclude="$proxy,$legacy" --title "$title" $apps > $graph.dot && dot -Tpng $graph.dot > $graph.png
echo "Generate new model without names" echo "Generate new model without names"
graph="models-with-names" graph="models-with-names"

View file

@ -180,6 +180,12 @@ class InterimMeetingModelForm(forms.ModelForm):
return self.cleaned_data return self.cleaned_data
def is_virtual(self):
if not self.is_bound or self.data.get('in_person'):
return False
else:
return True
def set_group_options(self): def set_group_options(self):
'''Set group options based on user accessing the form''' '''Set group options based on user accessing the form'''
if has_role(self.user, "Secretariat"): if has_role(self.user, "Secretariat"):
@ -242,8 +248,8 @@ class InterimSessionModelForm(forms.ModelForm):
self.user = kwargs.pop('user') self.user = kwargs.pop('user')
if 'group' in kwargs: if 'group' in kwargs:
self.group = kwargs.pop('group') self.group = kwargs.pop('group')
if 'is_approved' in kwargs: if 'is_approved_or_virtual' in kwargs:
self.is_approved = kwargs.pop('is_approved') self.is_approved_or_virtual = kwargs.pop('is_approved_or_virtual')
super(InterimSessionModelForm, self).__init__(*args, **kwargs) super(InterimSessionModelForm, self).__init__(*args, **kwargs)
self.is_edit = bool(self.instance.pk) self.is_edit = bool(self.instance.pk)
# setup fields that aren't intrinsic to the Session object # setup fields that aren't intrinsic to the Session object
@ -267,7 +273,7 @@ class InterimSessionModelForm(forms.ModelForm):
"""NOTE: as the baseform of an inlineformset self.save(commit=True) """NOTE: as the baseform of an inlineformset self.save(commit=True)
never gets called""" never gets called"""
session = super(InterimSessionModelForm, self).save(commit=kwargs.get('commit', True)) session = super(InterimSessionModelForm, self).save(commit=kwargs.get('commit', True))
if self.is_approved: if self.is_approved_or_virtual:
session.status_id = 'scheda' session.status_id = 'scheda'
else: else:
session.status_id = 'apprw' session.status_id = 'apprw'

View file

@ -563,13 +563,13 @@ def send_interim_approval_request(meetings):
cc=cc_list) cc=cc_list)
def send_interim_announcement_request(meeting): def send_interim_announcement_request(meeting):
"""Sends an email to the secretariat that approval has been granted for an """Sends an email to the secretariat that an interim meeting is ready for
interim meeting which includes the link to send the official announcement""" announcement, includes the link to send the official announcement"""
group = meeting.session_set.first().group group = meeting.session_set.first().group
requester = meeting.session_set.first().requested_by requester = meeting.session_set.first().requested_by
(to_email, cc_list) = gather_address_lists('interim_approved') (to_email, cc_list) = gather_address_lists('interim_approved')
from_email = ('"IETF Meeting Session Request Tool"','session_request_developers@ietf.org') from_email = ('"IETF Meeting Session Request Tool"','session_request_developers@ietf.org')
subject = '{group} - Interim Meeting Approved'.format(group=group.acronym) subject = '{group} - interim meeting ready for announcement'.format(group=group.acronym)
template = 'meeting/interim_announcement_request.txt' template = 'meeting/interim_announcement_request.txt'
announce_url = settings.IDTRACKER_BASE_URL + reverse('ietf.meeting.views.interim_request_details', kwargs={'number': meeting.number}) announce_url = settings.IDTRACKER_BASE_URL + reverse('ietf.meeting.views.interim_request_details', kwargs={'number': meeting.number})
context = locals() context = locals()

View file

@ -599,7 +599,7 @@ class InterimTests(TestCase):
for session in meeting.session_set.all(): for session in meeting.session_set.all():
self.assertEqual(session.status.slug, 'scheda') self.assertEqual(session.status.slug, 'scheda')
self.assertEqual(len(outbox), length_before + 1) self.assertEqual(len(outbox), length_before + 1)
self.assertTrue('Approved' in outbox[-1]['Subject']) self.assertTrue('ready for announcement' in outbox[-1]['Subject'])
def test_interim_approve_by_secretariat(self): def test_interim_approve_by_secretariat(self):
make_meeting_test_data() make_meeting_test_data()
@ -682,7 +682,7 @@ class InterimTests(TestCase):
len(q("#id_group option")) - 1) # -1 for options placeholder len(q("#id_group option")) - 1) # -1 for options placeholder
def test_interim_request_single(self): def test_interim_request_single_virtual(self):
make_meeting_test_data() make_meeting_test_data()
group = Group.objects.get(acronym='mars') group = Group.objects.get(acronym='mars')
date = datetime.date.today() + datetime.timedelta(days=30) date = datetime.date.today() + datetime.timedelta(days=30)
@ -692,7 +692,8 @@ class InterimTests(TestCase):
remote_instructions = 'Use webex' remote_instructions = 'Use webex'
agenda = 'Intro. Slides. Discuss.' agenda = 'Intro. Slides. Discuss.'
agenda_note = 'On second level' agenda_note = 'On second level'
self.client.login(username="secretary", password="secretary+password") length_before = len(outbox)
self.client.login(username="marschairman", password="marschairman+password")
data = {'group':group.pk, data = {'group':group.pk,
'meeting_type':'single', 'meeting_type':'single',
'city':'', 'city':'',
@ -710,7 +711,6 @@ class InterimTests(TestCase):
'session_set-MAX_NUM_FORMS':1000} 'session_set-MAX_NUM_FORMS':1000}
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data) r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming')) self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming'))
meeting = Meeting.objects.order_by('id').last() meeting = Meeting.objects.order_by('id').last()
self.assertEqual(meeting.type_id,'interim') self.assertEqual(meeting.type_id,'interim')
@ -722,6 +722,7 @@ class InterimTests(TestCase):
session = meeting.session_set.first() session = meeting.session_set.first()
self.assertEqual(session.remote_instructions,remote_instructions) self.assertEqual(session.remote_instructions,remote_instructions)
self.assertEqual(session.agenda_note,agenda_note) self.assertEqual(session.agenda_note,agenda_note)
self.assertEqual(session.status.slug,'scheda')
timeslot = session.official_timeslotassignment().timeslot timeslot = session.official_timeslotassignment().timeslot
self.assertEqual(timeslot.time,dt) self.assertEqual(timeslot.time,dt)
self.assertEqual(timeslot.duration,duration) self.assertEqual(timeslot.duration,duration)
@ -730,6 +731,10 @@ class InterimTests(TestCase):
doc = session.materials.first() doc = session.materials.first()
path = os.path.join(doc.get_file_path(),doc.filename_with_rev()) path = os.path.join(doc.get_file_path(),doc.filename_with_rev())
self.assertTrue(os.path.exists(path)) self.assertTrue(os.path.exists(path))
# check notice to secretariat
self.assertEqual(len(outbox), length_before + 1)
self.assertTrue('interim meeting ready for announcement' in outbox[-1]['Subject'])
self.assertTrue('iesg-secretary@ietf.org' in outbox[-1]['To'])
def test_interim_request_single_in_person(self): def test_interim_request_single_in_person(self):
make_meeting_test_data() make_meeting_test_data()

View file

@ -1319,6 +1319,7 @@ def interim_request(request):
if form.is_valid() and formset.is_valid(): if form.is_valid() and formset.is_valid():
group = form.cleaned_data.get('group') group = form.cleaned_data.get('group')
is_approved = form.cleaned_data.get('approved', False) is_approved = form.cleaned_data.get('approved', False)
is_virtual = form.is_virtual()
meeting_type = form.cleaned_data.get('meeting_type') meeting_type = form.cleaned_data.get('meeting_type')
# pre create meeting # pre create meeting
@ -1330,14 +1331,16 @@ def interim_request(request):
InterimSessionModelForm, InterimSessionModelForm,
user=request.user, user=request.user,
group=group, group=group,
is_approved=is_approved)) is_approved_or_virtual=(is_approved or is_virtual)))
formset = SessionFormset(instance=meeting, data=request.POST) formset = SessionFormset(instance=meeting, data=request.POST)
formset.is_valid() formset.is_valid()
formset.save() formset.save()
sessions_post_save(formset) sessions_post_save(formset)
if not is_approved: if not (is_approved or is_virtual):
send_interim_approval_request(meetings=[meeting]) send_interim_approval_request(meetings=[meeting])
elif not has_role(request.user, 'Secretariat'):
send_interim_announcement_request(meeting=meeting)
# series require special handling, each session gets it's own # series require special handling, each session gets it's own
# meeting object we won't see this on edit because series are # meeting object we won't see this on edit because series are
@ -1348,7 +1351,7 @@ def interim_request(request):
InterimSessionModelForm, InterimSessionModelForm,
user=request.user, user=request.user,
group=group, group=group,
is_approved=is_approved)) is_approved_or_virtual=(is_approved or is_virtual)))
formset = SessionFormset(instance=Meeting(), data=request.POST) formset = SessionFormset(instance=Meeting(), data=request.POST)
formset.is_valid() # re-validate formset.is_valid() # re-validate
for session_form in formset.forms: for session_form in formset.forms:
@ -1365,8 +1368,10 @@ def interim_request(request):
series.append(meeting) series.append(meeting)
sessions_post_save([session_form]) sessions_post_save([session_form])
if not is_approved: if not (is_approved or is_virtual):
send_interim_approval_request(meetings=series) send_interim_approval_request(meetings=series)
elif not has_role(request.user, 'Secretariat'):
send_interim_announcement_request(meeting=meeting)
messages.success(request, 'Interim meeting request submitted') messages.success(request, 'Interim meeting request submitted')
return redirect(upcoming) return redirect(upcoming)
@ -1465,7 +1470,7 @@ def interim_request_edit(request, number):
InterimSessionModelForm, InterimSessionModelForm,
user=request.user, user=request.user,
group=group, group=group,
is_approved=is_approved)) is_approved_or_virtual=is_approved))
formset = SessionFormset(instance=meeting, formset = SessionFormset(instance=meeting,
data=request.POST) data=request.POST)
if form.is_valid() and formset.is_valid(): if form.is_valid() and formset.is_valid():

View file

@ -1,5 +1,5 @@
{% load ams_filters %}{% load ietf_filters %} {% load ams_filters %}{% load ietf_filters %}
An interim meeting for {{ group.acronym }} has just been approved. An interim meeting for {{ group.acronym }} has been approved or does not require approval and is ready for announcement.
Use this link to officially announce the meeting: Use this link to officially announce the meeting:
{{ announce_url }} {{ announce_url }}