Notify IRSG when an IRSG ballot is created. Fixes #2978. Commit ready for merge.
- Legacy-Id: 18162
This commit is contained in:
parent
24140fac50
commit
6e97a89786
|
@ -13,6 +13,7 @@ from django.urls import reverse as urlreverse
|
|||
from django.utils.encoding import force_text
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
from ietf.doc.templatetags.mail_filters import std_level_prompt
|
||||
|
||||
from ietf.utils.mail import send_mail, send_mail_text
|
||||
from ietf.ipr.utils import iprs_from_docs, related_docs
|
||||
|
@ -401,7 +402,7 @@ def generate_issue_ballot_mail(request, doc, ballot):
|
|||
last_call_expires = e.expires if e else None
|
||||
last_call_has_expired = last_call_expires and last_call_expires < datetime.datetime.now()
|
||||
|
||||
return render_to_string("doc/mail/issue_ballot_mail.txt",
|
||||
return render_to_string("doc/mail/issue_iesg_ballot_mail.txt",
|
||||
dict(doc=doc,
|
||||
doc_url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
|
||||
last_call_expires=last_call_expires,
|
||||
|
@ -413,6 +414,58 @@ def generate_issue_ballot_mail(request, doc, ballot):
|
|||
)
|
||||
)
|
||||
|
||||
def _send_irsg_ballot_email(request, doc, ballot, subject, template):
|
||||
"""Send email notification when IRSG ballot is issued"""
|
||||
(to, cc) = gather_address_lists('irsg_ballot_issued', doc=doc)
|
||||
sender = 'IESG Secretary <iesg-secretary@ietf.org>'
|
||||
|
||||
ballot_expired = ballot.duedate < datetime.datetime.now()
|
||||
active_ballot = doc.active_ballot()
|
||||
if active_ballot is None:
|
||||
needed_bps = ''
|
||||
else:
|
||||
needed_bps = needed_ballot_positions(
|
||||
doc,
|
||||
list(active_ballot.active_balloter_positions().values())
|
||||
)
|
||||
|
||||
return send_mail(
|
||||
request=request,
|
||||
frm=sender,
|
||||
to=to,
|
||||
cc=cc,
|
||||
subject=subject,
|
||||
extra={'Reply-To': [sender]},
|
||||
template=template,
|
||||
context=dict(
|
||||
doc=doc,
|
||||
doc_url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
|
||||
ballot_duedate=ballot.duedate,
|
||||
ballot_expired=ballot_expired,
|
||||
needed_ballot_positions=needed_bps,
|
||||
))
|
||||
|
||||
|
||||
def email_irsg_ballot_issued(request, doc, ballot):
|
||||
"""Send email notification when IRSG ballot is issued"""
|
||||
return _send_irsg_ballot_email(
|
||||
request,
|
||||
doc,
|
||||
ballot,
|
||||
'IRSG ballot issued: %s to %s'%(doc.file_tag(), std_level_prompt(doc)),
|
||||
'doc/mail/issue_irsg_ballot_mail.txt',
|
||||
)
|
||||
|
||||
def email_irsg_ballot_closed(request, doc, ballot):
|
||||
"""Send email notification when IRSG ballot is closed"""
|
||||
return _send_irsg_ballot_email(
|
||||
request,
|
||||
doc,
|
||||
ballot,
|
||||
'IRSG ballot closed: %s to %s'%(doc.file_tag(), std_level_prompt(doc)),
|
||||
"doc/mail/close_irsg_ballot_mail.txt",
|
||||
)
|
||||
|
||||
def email_iana(request, doc, to, msg, cc=None):
|
||||
# fix up message and send it with extra info on doc in headers
|
||||
import email
|
||||
|
|
|
@ -334,10 +334,22 @@ class BaseManipulationTests():
|
|||
self.assertEqual(r.status_code, 302)
|
||||
self.assertIsNone(draft.ballot_open('irsg-approve'))
|
||||
|
||||
# No notifications should have been generated yet
|
||||
self.assertEqual(len(outbox), 0)
|
||||
|
||||
r = self.client.post(url,{'irsg_button':'Yes', 'duedate':due })
|
||||
self.assertEqual(r.status_code,302)
|
||||
self.assertIsNotNone(draft.ballot_open('irsg-approve'))
|
||||
self.assertEqual(len(outbox),0)
|
||||
|
||||
# Should have sent a notification about the new ballot
|
||||
self.assertEqual(len(outbox), 1)
|
||||
msg = outbox[0]
|
||||
self.assertIn('IRSG ballot issued', msg['Subject'])
|
||||
self.assertIn('iesg-secretary@ietf.org', msg['From'])
|
||||
# Notifications are also sent to various doc-related addresses, not tested here
|
||||
self.assertIn('irsg@irtf.org', msg['To'])
|
||||
self.assertIn('irtf-chair@irtf.org', msg['CC'])
|
||||
self.assertIn(str(due), get_payload_text(msg)) # ensure duedate is included
|
||||
|
||||
def test_take_and_email_position(self):
|
||||
draft = RgDraftFactory()
|
||||
|
@ -379,11 +391,21 @@ class BaseManipulationTests():
|
|||
self.assertEqual(r.status_code, 302)
|
||||
self.assertIsNotNone(draft.ballot_open('irsg-approve'))
|
||||
|
||||
# Should not have generated a notification yet
|
||||
self.assertEqual(len(outbox), 0)
|
||||
|
||||
r = self.client.post(url,dict(irsg_button='Yes'))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.assertIsNone(draft.ballot_open('irsg-approve'))
|
||||
|
||||
self.assertEqual(len(outbox), 0)
|
||||
# Closing the ballot should have generated a notification
|
||||
self.assertEqual(len(outbox), 1)
|
||||
msg = outbox[0]
|
||||
self.assertIn('IRSG ballot closed', msg['Subject'])
|
||||
self.assertIn('iesg-secretary@ietf.org', msg['From'])
|
||||
# Notifications are also sent to various doc-related addresses, not tested here
|
||||
self.assertIn('irsg@irtf.org', msg['To'])
|
||||
self.assertIn('irtf-chair@irtf.org', msg['CC'])
|
||||
|
||||
def test_view_outstanding_ballots(self):
|
||||
draft = RgDraftFactory()
|
||||
|
|
|
@ -235,7 +235,7 @@ def default_review_text(group, charter, by):
|
|||
|
||||
def generate_issue_ballot_mail(request, doc, ballot):
|
||||
|
||||
addrs=gather_address_lists('ballot_issued',doc=doc).as_strings()
|
||||
addrs=gather_address_lists('iesg_ballot_issued',doc=doc).as_strings()
|
||||
|
||||
return render_to_string("doc/charter/issue_ballot_mail.txt",
|
||||
dict(doc=doc,
|
||||
|
|
|
@ -26,7 +26,7 @@ from ietf.doc.utils import ( add_state_change_event, close_ballot, close_open_ba
|
|||
from ietf.doc.mails import ( email_ballot_deferred, email_ballot_undeferred,
|
||||
extra_automation_headers, generate_last_call_announcement,
|
||||
generate_issue_ballot_mail, generate_ballot_writeup, generate_ballot_rfceditornote,
|
||||
generate_approval_mail )
|
||||
generate_approval_mail, email_irsg_ballot_closed, email_irsg_ballot_issued )
|
||||
from ietf.doc.lastcall import request_last_call
|
||||
from ietf.iesg.models import TelechatDate
|
||||
from ietf.ietfauth.utils import has_role, role_required, is_authorized_in_doc_stream
|
||||
|
@ -635,7 +635,7 @@ def ballot_writeupnotes(request, name):
|
|||
|
||||
msg = generate_issue_ballot_mail(request, doc, ballot)
|
||||
|
||||
addrs = gather_address_lists('ballot_issued',doc=doc).as_strings()
|
||||
addrs = gather_address_lists('iesg_ballot_issued',doc=doc).as_strings()
|
||||
override = {'To':addrs.to}
|
||||
if addrs.cc:
|
||||
override['CC'] = addrs.cc
|
||||
|
@ -1095,6 +1095,8 @@ def issue_irsg_ballot(request, name):
|
|||
prev_tags = []
|
||||
new_tags = []
|
||||
|
||||
email_irsg_ballot_issued(request, doc, ballot=e) # Send notification email
|
||||
|
||||
if doc.type_id == 'draft':
|
||||
new_state = State.objects.get(used=True, type="draft-stream-irtf", slug='irsgpoll')
|
||||
|
||||
|
@ -1130,7 +1132,10 @@ def close_irsg_ballot(request, name):
|
|||
if request.method == 'POST':
|
||||
button = request.POST.get("irsg_button")
|
||||
if button == 'Yes':
|
||||
close_ballot(doc, by, "irsg-approve")
|
||||
ballot = close_ballot(doc, by, "irsg-approve")
|
||||
email_irsg_ballot_closed(request,
|
||||
doc=doc,
|
||||
ballot=IRSGBallotDocEvent.objects.get(pk=ballot.pk))
|
||||
|
||||
return HttpResponseRedirect(doc.get_absolute_url())
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ def send_conflict_eval_email(request,review):
|
|||
doc_url = settings.IDTRACKER_BASE_URL+review.get_absolute_url(),
|
||||
)
|
||||
)
|
||||
addrs = gather_address_lists('ballot_issued',doc=review).as_strings()
|
||||
addrs = gather_address_lists('iesg_ballot_issued',doc=review).as_strings()
|
||||
override = {'To':addrs.to}
|
||||
if addrs.cc:
|
||||
override['Cc']=addrs.cc
|
||||
|
|
|
@ -129,7 +129,7 @@ def send_status_change_eval_email(request,doc):
|
|||
doc_url = settings.IDTRACKER_BASE_URL+doc.get_absolute_url(),
|
||||
)
|
||||
)
|
||||
addrs = gather_address_lists('ballot_issued',doc=doc)
|
||||
addrs = gather_address_lists('iesg_ballot_issued',doc=doc)
|
||||
override = {'To':addrs.to }
|
||||
if addrs.cc:
|
||||
override['Cc'] = addrs.cc
|
||||
|
|
57
ietf/mailtrigger/migrations/0014_add_irsg_ballot_issued.py
Normal file
57
ietf/mailtrigger/migrations/0014_add_irsg_ballot_issued.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
# Copyright The IETF Trust 2019-2020, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def replace_mailtrigger(MailTrigger, old_slug, new_slug):
|
||||
"""Replace a MailTrigger with an equivalent using a different slug"""
|
||||
# Per 0013_add_irsg_ballot_saved.py, can't just modify the existing because that
|
||||
# will lose the many-to-many relations.
|
||||
orig_mailtrigger = MailTrigger.objects.get(slug=old_slug)
|
||||
new_mailtrigger = MailTrigger.objects.create(slug=new_slug)
|
||||
new_mailtrigger.to.set(orig_mailtrigger.to.all())
|
||||
new_mailtrigger.cc.set(orig_mailtrigger.cc.all())
|
||||
new_mailtrigger.desc = orig_mailtrigger.desc
|
||||
new_mailtrigger.save()
|
||||
orig_mailtrigger.delete() # get rid of the obsolete MailTrigger
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
"""Forward migration: create irsg_ballot_issued and rename ballot_issued to iesg_ballot_issued"""
|
||||
# Load historical models
|
||||
MailTrigger = apps.get_model('mailtrigger', 'MailTrigger')
|
||||
Recipient = apps.get_model('mailtrigger', 'Recipient')
|
||||
|
||||
# Create the new MailTrigger
|
||||
irsg_ballot_issued = MailTrigger.objects.create(
|
||||
slug='irsg_ballot_issued',
|
||||
desc='Recipients when a new IRSG ballot is issued',
|
||||
)
|
||||
irsg_ballot_issued.to.set(Recipient.objects.filter(slug='irsg'))
|
||||
irsg_ballot_issued.cc.set(Recipient.objects.filter(slug__in=[
|
||||
'doc_stream_manager', 'doc_affecteddoc_authors', 'doc_affecteddoc_group_chairs',
|
||||
'doc_affecteddoc_notify', 'doc_authors', 'doc_group_chairs', 'doc_group_mail_list',
|
||||
'doc_notify', 'doc_shepherd'
|
||||
]))
|
||||
|
||||
# Replace existing 'ballot_issued' object with an 'iesg_ballot_issued'
|
||||
replace_mailtrigger(MailTrigger, 'ballot_issued', 'iesg_ballot_issued')
|
||||
|
||||
|
||||
def reverse(apps, shema_editor):
|
||||
"""Reverse migration: rename iesg_ballot_issued to ballot_issued and remove irsg_ballot_issued"""
|
||||
MailTrigger = apps.get_model('mailtrigger', 'MailTrigger')
|
||||
MailTrigger.objects.filter(slug='irsg_ballot_issued').delete()
|
||||
replace_mailtrigger(MailTrigger, 'iesg_ballot_issued', 'ballot_issued')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('mailtrigger', '0013_add_irsg_ballot_saved'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse),
|
||||
]
|
|
@ -3264,18 +3264,6 @@
|
|||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "ballot_ednote_changed_late"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [],
|
||||
"desc": "Recipients when a ballot is issued",
|
||||
"to": [
|
||||
"iesg",
|
||||
"iesg_secretary"
|
||||
]
|
||||
},
|
||||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "ballot_issued"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [],
|
||||
|
@ -3686,6 +3674,18 @@
|
|||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "group_personnel_change"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [],
|
||||
"desc": "Recipients when a ballot is issued",
|
||||
"to": [
|
||||
"iesg",
|
||||
"iesg_secretary"
|
||||
]
|
||||
},
|
||||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "iesg_ballot_issued"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [
|
||||
|
@ -3798,6 +3798,27 @@
|
|||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "ipr_posting_confirmation"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [
|
||||
"doc_affecteddoc_authors",
|
||||
"doc_affecteddoc_group_chairs",
|
||||
"doc_affecteddoc_notify",
|
||||
"doc_authors",
|
||||
"doc_group_chairs",
|
||||
"doc_group_mail_list",
|
||||
"doc_notify",
|
||||
"doc_shepherd",
|
||||
"doc_stream_manager"
|
||||
],
|
||||
"desc": "Recipients when a new IRSG ballot is issued",
|
||||
"to": [
|
||||
"irsg"
|
||||
]
|
||||
},
|
||||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "irsg_ballot_issued"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [
|
||||
|
|
3
ietf/templates/doc/mail/close_irsg_ballot_mail.txt
Normal file
3
ietf/templates/doc/mail/close_irsg_ballot_mail.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %} {% filter wordwrap:78 %}The IRSG ballot for {{ doc.file_tag }} has been closed. The evaluation for this document can be found at {{ doc_url }}{% endfilter %}
|
||||
|
||||
{% endautoescape%}
|
7
ietf/templates/doc/mail/issue_irsg_ballot_mail.txt
Normal file
7
ietf/templates/doc/mail/issue_irsg_ballot_mail.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}{% filter wordwrap:78 %}Evaluation for {{ doc.file_tag }} can be found at {{ doc_url }}
|
||||
|
||||
Ballot expire{% if ballot_expired %}d{% else %}s{% endif %} on: {{ ballot_duedate }}
|
||||
{% endfilter %}
|
||||
{% filter wordwrap:78 %}{{ needed_ballot_positions }}{% endfilter %}
|
||||
|
||||
{% endautoescape%}
|
Loading…
Reference in a new issue