Merged in [18616] from rjsparks@nostrum.com:
Email requesters when an interim moves into the announcement queue. Partially addresses #3016 and #3099.
- Legacy-Id: 18630
Note: SVN reference [18616] has been migrated to Git commit ff3f3bd99a
This commit is contained in:
commit
517ebfa15b
41
ietf/mailtrigger/migrations/0018_interim_approve_announce.py
Normal file
41
ietf/mailtrigger/migrations/0018_interim_approve_announce.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# Copyright The IETF Trust 2020 All Rights Reserved
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
def forward(apps,schema_editor):
|
||||||
|
MailTrigger = apps.get_model('mailtrigger', 'MailTrigger')
|
||||||
|
Recipient = apps.get_model('mailtrigger', 'Recipient')
|
||||||
|
|
||||||
|
interim_approved = MailTrigger.objects.get(slug='interim_approved')
|
||||||
|
interim_approved.desc = 'Recipients when an interim meeting is approved'
|
||||||
|
interim_approved.save()
|
||||||
|
interim_approved.to.set(Recipient.objects.filter(slug__in=('group_chairs','logged_in_person')))
|
||||||
|
|
||||||
|
interim_announce_requested = MailTrigger.objects.create(
|
||||||
|
slug='interim_announce_requested',
|
||||||
|
desc='Recipients when an interim announcement is requested',
|
||||||
|
)
|
||||||
|
interim_announce_requested.to.set(Recipient.objects.filter(slug='iesg_secretary'))
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps,schema_editor):
|
||||||
|
MailTrigger = apps.get_model('mailtrigger', 'MailTrigger')
|
||||||
|
Recipient = apps.get_model('mailtrigger', 'Recipient')
|
||||||
|
|
||||||
|
MailTrigger.objects.filter(slug='interim_announce_requested').delete()
|
||||||
|
|
||||||
|
interim_approved = MailTrigger.objects.get(slug='interim_approved')
|
||||||
|
interim_approved.desc = 'Recipients when an interim meeting is approved and an announcement needs to be sent'
|
||||||
|
interim_approved.save()
|
||||||
|
interim_approved.to.set(Recipient.objects.filter(slug='iesg_secretary'))
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mailtrigger', '0017_lc_to_yang_doctors'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(forward,reverse)
|
||||||
|
]
|
|
@ -552,13 +552,31 @@ def send_interim_approval_request(meetings):
|
||||||
context,
|
context,
|
||||||
cc=cc_list)
|
cc=cc_list)
|
||||||
|
|
||||||
|
def send_interim_approval(user, meeting):
|
||||||
|
"""Send an email to chairs and whoever initiated the action that resulted in approval that an interim is approved"""
|
||||||
|
first_session = meeting.session_set.first()
|
||||||
|
(to_email,cc_list) = gather_address_lists('interim_approved',group=first_session.group,person=user.person)
|
||||||
|
from_email = (settings.SESSION_REQUEST_FROM_EMAIL)
|
||||||
|
subject = f'{meeting.number} interim approved'
|
||||||
|
template = 'meeting/interim_approval.txt'
|
||||||
|
context = {
|
||||||
|
'meeting': meeting,
|
||||||
|
}
|
||||||
|
send_mail(None,
|
||||||
|
to_email,
|
||||||
|
from_email,
|
||||||
|
subject,
|
||||||
|
template,
|
||||||
|
context,
|
||||||
|
cc=cc_list)
|
||||||
|
|
||||||
def send_interim_announcement_request(meeting):
|
def send_interim_announcement_request(meeting):
|
||||||
"""Sends an email to the secretariat that an interim meeting is ready for
|
"""Sends an email to the secretariat that an interim meeting is ready for
|
||||||
announcement, includes the link to send the official announcement"""
|
announcement, includes the link to send the official announcement"""
|
||||||
first_session = meeting.session_set.first()
|
first_session = meeting.session_set.first()
|
||||||
group = first_session.group
|
group = first_session.group
|
||||||
requester = session_requested_by(first_session)
|
requester = session_requested_by(first_session)
|
||||||
(to_email, cc_list) = gather_address_lists('interim_approved')
|
(to_email, cc_list) = gather_address_lists('interim_announce_requested')
|
||||||
from_email = (settings.SESSION_REQUEST_FROM_EMAIL)
|
from_email = (settings.SESSION_REQUEST_FROM_EMAIL)
|
||||||
subject = '{group} - interim meeting ready for announcement'.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'
|
||||||
|
|
|
@ -2429,7 +2429,7 @@ class InterimTests(TestCase):
|
||||||
count = person.role_set.filter(name='chair',group__type__in=('wg', 'rg'), group__state__in=('active', 'proposed')).count()
|
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
|
self.assertEqual(count, len(q("#id_group option")) - 1) # -1 for options placeholder
|
||||||
|
|
||||||
def do_interim_request_single_virtual(self):
|
def do_interim_request_single_virtual(self, emails_expected):
|
||||||
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)
|
||||||
|
@ -2479,13 +2479,13 @@ 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
|
# check notices to secretariat and chairs
|
||||||
self.assertEqual(len(outbox), length_before + 1)
|
self.assertEqual(len(outbox), length_before + emails_expected)
|
||||||
return meeting
|
return meeting
|
||||||
|
|
||||||
@override_settings(VIRTUAL_INTERIMS_REQUIRE_APPROVAL = True)
|
@override_settings(VIRTUAL_INTERIMS_REQUIRE_APPROVAL = True)
|
||||||
def test_interim_request_single_virtual_settings_approval_required(self):
|
def test_interim_request_single_virtual_settings_approval_required(self):
|
||||||
meeting = self.do_interim_request_single_virtual()
|
meeting = self.do_interim_request_single_virtual(emails_expected=1)
|
||||||
self.assertEqual(meeting.session_set.last().schedulingevent_set.last().status_id,'apprw')
|
self.assertEqual(meeting.session_set.last().schedulingevent_set.last().status_id,'apprw')
|
||||||
self.assertIn('New Interim Meeting Request', outbox[-1]['Subject'])
|
self.assertIn('New Interim Meeting Request', outbox[-1]['Subject'])
|
||||||
self.assertIn('session-request@ietf.org', outbox[-1]['To'])
|
self.assertIn('session-request@ietf.org', outbox[-1]['To'])
|
||||||
|
@ -2493,7 +2493,7 @@ class InterimTests(TestCase):
|
||||||
|
|
||||||
@override_settings(VIRTUAL_INTERIMS_REQUIRE_APPROVAL = False)
|
@override_settings(VIRTUAL_INTERIMS_REQUIRE_APPROVAL = False)
|
||||||
def test_interim_request_single_virtual_settings_approval_not_required(self):
|
def test_interim_request_single_virtual_settings_approval_not_required(self):
|
||||||
meeting = self.do_interim_request_single_virtual()
|
meeting = self.do_interim_request_single_virtual(emails_expected=2)
|
||||||
self.assertEqual(meeting.session_set.last().schedulingevent_set.last().status_id,'scheda')
|
self.assertEqual(meeting.session_set.last().schedulingevent_set.last().status_id,'scheda')
|
||||||
self.assertIn('iesg-secretary@ietf.org', outbox[-1]['To'])
|
self.assertIn('iesg-secretary@ietf.org', outbox[-1]['To'])
|
||||||
self.assertIn('interim meeting ready for announcement', outbox[-1]['Subject'])
|
self.assertIn('interim meeting ready for announcement', outbox[-1]['Subject'])
|
||||||
|
@ -3746,12 +3746,16 @@ class HasMeetingsTests(TestCase):
|
||||||
'session_set-MIN_NUM_FORMS':0,
|
'session_set-MIN_NUM_FORMS':0,
|
||||||
'session_set-MAX_NUM_FORMS':1000}
|
'session_set-MAX_NUM_FORMS':1000}
|
||||||
|
|
||||||
|
empty_outbox()
|
||||||
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')
|
||||||
self.assertEqual(meeting.date,date)
|
self.assertEqual(meeting.date,date)
|
||||||
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year, group.acronym, next_num))
|
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year, group.acronym, next_num))
|
||||||
|
self.assertTrue(len(outbox)>0)
|
||||||
|
self.assertIn('interim approved',outbox[0]["Subject"])
|
||||||
|
self.assertIn(user.person.email().address,outbox[0]["To"])
|
||||||
self.client.logout()
|
self.client.logout()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ from ietf.meeting.helpers import can_edit_interim_request
|
||||||
from ietf.meeting.helpers import can_request_interim_meeting, get_announcement_initial
|
from ietf.meeting.helpers import can_request_interim_meeting, get_announcement_initial
|
||||||
from ietf.meeting.helpers import sessions_post_save, is_interim_meeting_approved
|
from ietf.meeting.helpers import sessions_post_save, is_interim_meeting_approved
|
||||||
from ietf.meeting.helpers import send_interim_cancellation_notice
|
from ietf.meeting.helpers import send_interim_cancellation_notice
|
||||||
|
from ietf.meeting.helpers import send_interim_approval
|
||||||
from ietf.meeting.helpers import send_interim_approval_request
|
from ietf.meeting.helpers import send_interim_approval_request
|
||||||
from ietf.meeting.helpers import send_interim_announcement_request
|
from ietf.meeting.helpers import send_interim_announcement_request
|
||||||
from ietf.meeting.utils import finalize, sort_accept_tuple, condition_slide_order
|
from ietf.meeting.utils import finalize, sort_accept_tuple, condition_slide_order
|
||||||
|
@ -3025,8 +3026,10 @@ def interim_request(request):
|
||||||
|
|
||||||
if requires_approval:
|
if requires_approval:
|
||||||
send_interim_approval_request(meetings=[meeting])
|
send_interim_approval_request(meetings=[meeting])
|
||||||
elif not has_role(request.user, 'Secretariat'):
|
else:
|
||||||
send_interim_announcement_request(meeting=meeting)
|
send_interim_approval(request.user, meeting=meeting)
|
||||||
|
if 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
|
||||||
|
@ -3056,8 +3059,10 @@ def interim_request(request):
|
||||||
|
|
||||||
if requires_approval:
|
if requires_approval:
|
||||||
send_interim_approval_request(meetings=series)
|
send_interim_approval_request(meetings=series)
|
||||||
elif not has_role(request.user, 'Secretariat'):
|
else:
|
||||||
send_interim_announcement_request(meeting=meeting)
|
send_interim_approval(request.user, meeting=meeting)
|
||||||
|
if 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)
|
||||||
|
|
|
@ -3760,6 +3760,17 @@
|
||||||
"model": "mailtrigger.mailtrigger",
|
"model": "mailtrigger.mailtrigger",
|
||||||
"pk": "iesg_ballot_saved"
|
"pk": "iesg_ballot_saved"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"cc": [],
|
||||||
|
"desc": "Recipients when an interim announcement is requested",
|
||||||
|
"to": [
|
||||||
|
"iesg_secretary"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"model": "mailtrigger.mailtrigger",
|
||||||
|
"pk": "interim_announce_requested"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": [
|
"cc": [
|
||||||
|
@ -3777,9 +3788,10 @@
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": [],
|
"cc": [],
|
||||||
"desc": "Recipients when an interim meeting is approved and an announcement needs to be sent",
|
"desc": "Recipients when an interim meeting is approved",
|
||||||
"to": [
|
"to": [
|
||||||
"iesg_secretary"
|
"group_chairs",
|
||||||
|
"logged_in_person"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"model": "mailtrigger.mailtrigger",
|
"model": "mailtrigger.mailtrigger",
|
||||||
|
@ -10509,6 +10521,17 @@
|
||||||
"model": "name.importantdatename",
|
"model": "name.importantdatename",
|
||||||
"pk": "01cutoff"
|
"pk": "01cutoff"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"default_offset_days": -57,
|
||||||
|
"desc": "Preliminary BOF proposals requested. To request a BOF, please see instructions on requesting a BOF at https://www.ietf.org/how/bofs/bof-procedures/",
|
||||||
|
"name": "Preliminary BOF proposals requested",
|
||||||
|
"order": 0,
|
||||||
|
"used": true
|
||||||
|
},
|
||||||
|
"model": "name.importantdatename",
|
||||||
|
"pk": "bofproposals"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"default_offset_days": -36,
|
"default_offset_days": -36,
|
||||||
|
@ -10630,6 +10653,17 @@
|
||||||
"model": "name.importantdatename",
|
"model": "name.importantdatename",
|
||||||
"pk": "ietf-108-go-ahead"
|
"pk": "ietf-108-go-ahead"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"default_offset_days": -70,
|
||||||
|
"desc": "Announcement of whether the meeting will be in-person or online.",
|
||||||
|
"name": "Online or in-person Announcement",
|
||||||
|
"order": 0,
|
||||||
|
"used": true
|
||||||
|
},
|
||||||
|
"model": "name.importantdatename",
|
||||||
|
"pk": "online-announcement"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"default_offset_days": -82,
|
"default_offset_days": -82,
|
||||||
|
@ -11897,6 +11931,26 @@
|
||||||
"model": "name.rolename",
|
"model": "name.rolename",
|
||||||
"pk": "trac-editor"
|
"pk": "trac-editor"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"desc": "Can operate the YangCatalog, change its configuration, and edit its data",
|
||||||
|
"name": "YangCatalog Administrator",
|
||||||
|
"order": 0,
|
||||||
|
"used": true
|
||||||
|
},
|
||||||
|
"model": "name.rolename",
|
||||||
|
"pk": "yc_admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"desc": "Can grant user api rights and browse the YangCatalog directory structure",
|
||||||
|
"name": "YangCatalog Operator",
|
||||||
|
"order": 0,
|
||||||
|
"used": true
|
||||||
|
},
|
||||||
|
"model": "name.rolename",
|
||||||
|
"pk": "yc_operator"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"desc": "Audio streaming support",
|
"desc": "Audio streaming support",
|
||||||
|
@ -12047,6 +12101,16 @@
|
||||||
"model": "name.sessionstatusname",
|
"model": "name.sessionstatusname",
|
||||||
"pk": "notmeet"
|
"pk": "notmeet"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fields": {
|
||||||
|
"desc": "",
|
||||||
|
"name": "Rescheduled",
|
||||||
|
"order": 0,
|
||||||
|
"used": true
|
||||||
|
},
|
||||||
|
"model": "name.sessionstatusname",
|
||||||
|
"pk": "resched"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"desc": "",
|
"desc": "",
|
||||||
|
@ -12107,16 +12171,6 @@
|
||||||
"model": "name.slidesubmissionstatusname",
|
"model": "name.slidesubmissionstatusname",
|
||||||
"pk": "rejected"
|
"pk": "rejected"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fields": {
|
|
||||||
"desc": "",
|
|
||||||
"name": "Rescheduled",
|
|
||||||
"order": 0,
|
|
||||||
"used": true
|
|
||||||
},
|
|
||||||
"model": "name.sessionstatusname",
|
|
||||||
"pk": "resched"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fields": {
|
"fields": {
|
||||||
"desc": "",
|
"desc": "",
|
||||||
|
@ -14954,7 +15008,7 @@
|
||||||
"fields": {
|
"fields": {
|
||||||
"command": "xym",
|
"command": "xym",
|
||||||
"switch": "--version",
|
"switch": "--version",
|
||||||
"time": "2020-07-23T00:12:27.508",
|
"time": "2020-10-09T00:17:03.141",
|
||||||
"used": true,
|
"used": true,
|
||||||
"version": "xym 0.4.8"
|
"version": "xym 0.4.8"
|
||||||
},
|
},
|
||||||
|
@ -14965,7 +15019,7 @@
|
||||||
"fields": {
|
"fields": {
|
||||||
"command": "pyang",
|
"command": "pyang",
|
||||||
"switch": "--version",
|
"switch": "--version",
|
||||||
"time": "2020-07-23T00:12:28.886",
|
"time": "2020-10-09T00:17:04.888",
|
||||||
"used": true,
|
"used": true,
|
||||||
"version": "pyang 2.3.2"
|
"version": "pyang 2.3.2"
|
||||||
},
|
},
|
||||||
|
@ -14976,7 +15030,7 @@
|
||||||
"fields": {
|
"fields": {
|
||||||
"command": "yanglint",
|
"command": "yanglint",
|
||||||
"switch": "--version",
|
"switch": "--version",
|
||||||
"time": "2020-07-23T00:12:29.140",
|
"time": "2020-10-09T00:17:05.228",
|
||||||
"used": true,
|
"used": true,
|
||||||
"version": "yanglint SO 1.6.7"
|
"version": "yanglint SO 1.6.7"
|
||||||
},
|
},
|
||||||
|
@ -14987,9 +15041,9 @@
|
||||||
"fields": {
|
"fields": {
|
||||||
"command": "xml2rfc",
|
"command": "xml2rfc",
|
||||||
"switch": "--version",
|
"switch": "--version",
|
||||||
"time": "2020-07-23T00:12:30.892",
|
"time": "2020-10-09T00:17:07.630",
|
||||||
"used": true,
|
"used": true,
|
||||||
"version": "xml2rfc 2.47.0"
|
"version": "xml2rfc 3.2.1"
|
||||||
},
|
},
|
||||||
"model": "utils.versioninfo",
|
"model": "utils.versioninfo",
|
||||||
"pk": 4
|
"pk": 4
|
||||||
|
|
5
ietf/templates/meeting/interim_approval.txt
Normal file
5
ietf/templates/meeting/interim_approval.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% load ams_filters %}{% load ietf_filters %}
|
||||||
|
An interim meeting for {{ group.acronym }} has been approved or does not require additional approval.
|
||||||
|
A message has been sent to the secretariat requesting the interim be announced.
|
||||||
|
|
||||||
|
{% include "meeting/interim_info.txt" %}
|
Loading…
Reference in a new issue