From f30f5c39f15ec20397582e51c88ec4cfd0fd8ff2 Mon Sep 17 00:00:00 2001
From: Robert Sparks <rjsparks@nostrum.com>
Date: Thu, 13 Aug 2015 21:16:21 +0000
Subject: [PATCH] checkpoint  - Legacy-Id: 10017

---
 ietf/doc/mails.py                             |  4 ++--
 ietf/doc/tests_ballot.py                      | 20 +++++++++----------
 ietf/doc/tests_charter.py                     |  4 ++--
 ietf/doc/utils_charter.py                     | 15 --------------
 ietf/doc/views_ballot.py                      | 18 +----------------
 ietf/doc/views_charter.py                     |  8 +++++---
 ietf/doc/views_draft.py                       |  2 +-
 .../migrations/0002_auto_20150809_1314.py     | 14 ++++++++++++-
 ietf/mailtoken/models.py                      |  4 ++--
 ietf/name/fixtures/names.json                 | 19 +++++++++++++++++-
 ietf/secr/telechat/views.py                   |  2 +-
 ietf/sync/iana.py                             |  2 +-
 12 files changed, 55 insertions(+), 57 deletions(-)

diff --git a/ietf/doc/mails.py b/ietf/doc/mails.py
index 51f00454e..d7e5b31fe 100644
--- a/ietf/doc/mails.py
+++ b/ietf/doc/mails.py
@@ -16,8 +16,8 @@ from ietf.group.models import Role
 from ietf.doc.models import Document
 from ietf.mailtoken.utils import gather_addresses, gather_address_list
 
-def email_state_changed(request, doc, text):
-    to = [x.strip() for x in doc.notify.replace(';', ',').split(',')]
+def email_state_changed(request, doc, text, mailtoken_id=None):
+    to = gather_address_list(mailtoken_id or 'doc_state_edited',doc=doc)
     if not to:
         return
     
diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py
index ff42532a3..5f9737044 100644
--- a/ietf/doc/tests_ballot.py
+++ b/ietf/doc/tests_ballot.py
@@ -232,7 +232,7 @@ class BallotWriteupsTests(TestCase):
                 send_last_call_request="1"))
         draft = Document.objects.get(name=draft.name)
         self.assertEqual(draft.get_state_slug("draft-iesg"), "lc-req")
-        self.assertEqual(len(outbox), mailbox_before + 2)
+        self.assertEqual(len(outbox), mailbox_before + 1)
         self.assertTrue("Last Call" in outbox[-1]['Subject'])
         self.assertTrue(draft.name in outbox[-1]['Subject'])
 
@@ -387,7 +387,7 @@ class ApproveBallotTests(TestCase):
 
         draft = Document.objects.get(name=draft.name)
         self.assertEqual(draft.get_state_slug("draft-iesg"), "ann")
-        self.assertEqual(len(outbox), mailbox_before + 3)
+        self.assertEqual(len(outbox), mailbox_before + 2)
         self.assertTrue("Protocol Action" in outbox[-2]['Subject'])
         # the IANA copy
         self.assertTrue("Protocol Action" in outbox[-1]['Subject'])
@@ -409,7 +409,7 @@ class ApproveBallotTests(TestCase):
 
         draft = Document.objects.get(name=draft.name)
         self.assertEqual(draft.get_state_slug("draft-iesg"), "dead")
-        self.assertEqual(len(outbox), mailbox_before + 2)
+        self.assertEqual(len(outbox), mailbox_before + 1)
         self.assertTrue("NOT be published" in str(outbox[-1]))
 
 
@@ -441,11 +441,10 @@ class MakeLastCallTests(TestCase):
         draft = Document.objects.get(name=draft.name)
         self.assertEqual(draft.get_state_slug("draft-iesg"), "lc")
         self.assertEqual(draft.latest_event(LastCallDocEvent, "sent_last_call").expires.strftime("%Y-%m-%d"), expire_date)
-        self.assertEqual(len(outbox), mailbox_before + 3)
+        self.assertEqual(len(outbox), mailbox_before + 2)
 
-        self.assertTrue("Last Call" in outbox[-3]['Subject'])
-        # the IANA copy
         self.assertTrue("Last Call" in outbox[-2]['Subject'])
+        self.assertTrue("Last Call" in outbox[-1]['Subject'])
         self.assertTrue("Last Call" in draft.message_set.order_by("-time")[0].subject)
 
 class DeferUndeferTestCase(TestCase):
@@ -491,8 +490,8 @@ class DeferUndeferTestCase(TestCase):
         if doc.type_id in defer_states:
            self.assertEqual(doc.get_state(defer_states[doc.type_id][0]).slug,defer_states[doc.type_id][1])
         self.assertTrue(doc.active_defer_event())
-        self.assertEqual(len(outbox), mailbox_before + 3)
-        self.assertTrue("State Update" in outbox[-3]['Subject'])
+        self.assertEqual(len(outbox), mailbox_before + 2)
+        #self.assertTrue("State Update" in outbox[-3]['Subject'])
         self.assertTrue("Telechat update" in outbox[-2]['Subject'])
         self.assertTrue("Deferred" in outbox[-1]['Subject'])
         self.assertTrue(doc.file_tag() in outbox[-1]['Subject'])
@@ -546,9 +545,8 @@ class DeferUndeferTestCase(TestCase):
         if doc.type_id in undefer_states:
            self.assertEqual(doc.get_state(undefer_states[doc.type_id][0]).slug,undefer_states[doc.type_id][1])
         self.assertFalse(doc.active_defer_event())
-        self.assertEqual(len(outbox), mailbox_before + 3)
-        self.assertTrue("Telechat update" in outbox[-3]['Subject'])
-        self.assertTrue("State Update" in outbox[-2]['Subject'])
+        self.assertEqual(len(outbox), mailbox_before + 2)
+        self.assertTrue("Telechat update" in outbox[-2]['Subject'])
         self.assertTrue("Undeferred" in outbox[-1]['Subject'])
         self.assertTrue(doc.file_tag() in outbox[-1]['Subject'])
 
diff --git a/ietf/doc/tests_charter.py b/ietf/doc/tests_charter.py
index c756cd05a..2876b7dcd 100644
--- a/ietf/doc/tests_charter.py
+++ b/ietf/doc/tests_charter.py
@@ -96,8 +96,8 @@ class EditCharterTests(TestCase):
             if slug in ("intrev", "iesgrev"):
                 self.assertTrue(find_event("created_ballot"))
 
-            self.assertEqual(len(outbox), mailbox_before + 1)
-            self.assertTrue("state changed" in outbox[-1]['Subject'].lower())
+            self.assertEqual(len(outbox), mailbox_before + 2)
+            self.assertTrue("state changed" in outbox[-2]['Subject'].lower())
                     
     def test_edit_telechat_date(self):
         make_test_data()
diff --git a/ietf/doc/utils_charter.py b/ietf/doc/utils_charter.py
index c5ff3457a..b92cde3e4 100644
--- a/ietf/doc/utils_charter.py
+++ b/ietf/doc/utils_charter.py
@@ -1,13 +1,11 @@
 import re, datetime, os
 
 from django.template.loader import render_to_string
-from django.utils.html import strip_tags
 from django.conf import settings
 
 from ietf.doc.models import NewRevisionDocEvent, WriteupDocEvent, BallotPositionDocEvent
 from ietf.person.models import Person
 from ietf.utils.history import find_history_active_at
-from ietf.utils.mail import send_mail_text
 from ietf.mailtoken.utils import gather_addresses
 
 def charter_name_for_group(group):
@@ -84,19 +82,6 @@ def historic_milestones_for_charter(charter, rev):
 
     return res
     
-def email_state_changed(request, doc, text):
-    to = [e.strip() for e in doc.notify.replace(';', ',').split(',')]
-    if not to:
-        return
-    
-    text = strip_tags(text)
-    text += "\n\n"
-    text += "URL: %s" % (settings.IDTRACKER_BASE_URL + doc.get_absolute_url())
-
-    send_mail_text(request, to, None,
-                   "State changed: %s-%s" % (doc.canonical_name(), doc.rev),
-                   text)
-
 def generate_ballot_writeup(request, doc):
     e = WriteupDocEvent()
     e.type = "changed_ballot_writeup_text"
diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py
index 5127bb373..55a10d7e4 100644
--- a/ietf/doc/views_ballot.py
+++ b/ietf/doc/views_ballot.py
@@ -18,7 +18,7 @@ from ietf.doc.models import ( Document, State, DocEvent, BallotDocEvent, BallotP
 from ietf.doc.utils import ( add_state_change_event, close_ballot, close_open_ballots,
     create_ballot_if_not_open, update_telechat )
 from ietf.doc.mails import ( email_ballot_deferred, email_ballot_undeferred, 
-    email_state_changed, extra_automation_headers, generate_last_call_announcement, 
+    extra_automation_headers, generate_last_call_announcement, 
     generate_issue_ballot_mail, generate_ballot_writeup, generate_approval_mail )
 from ietf.doc.lastcall import request_last_call
 from ietf.iesg.models import TelechatDate
@@ -69,8 +69,6 @@ def do_undefer_ballot(request, doc):
     doc.save()
 
     update_telechat(request, doc, login, telechat_date)
-    if e:
-        email_state_changed(request, doc, e.desc)
     email_ballot_undeferred(request, doc, login.plain_name(), telechat_date)
     
 def position_to_ballot_choice(position):
@@ -367,9 +365,6 @@ def defer_ballot(request, name):
         doc.time = (e and e.time) or datetime.datetime.now()
         doc.save()
 
-        if e:
-            email_state_changed(request, doc, e.desc)
-
         update_telechat(request, doc, login, telechat_date)
         email_ballot_deferred(request, doc, login.plain_name(), telechat_date)
 
@@ -462,9 +457,6 @@ def lastcalltext(request, name):
                     doc.time = (e and e.time) or datetime.datetime.now()
                     doc.save()
 
-                    if e:
-                        email_state_changed(request, doc, e.desc)
-
                     request_last_call(request, doc)
                     
                     return render_to_response('doc/draft/last_call_requested.html',
@@ -699,15 +691,11 @@ def approve_ballot(request, name):
 
         e.save()
         
-        change_description = e.desc + " and state has been changed to %s" % doc.get_state("draft-iesg").name
-        
         e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=[])
 
         doc.time = (e and e.time) or datetime.datetime.now()
         doc.save()
 
-        email_state_changed(request, doc, change_description)
-
         # send announcement
 
         send_mail_preformatted(request, announcement)
@@ -785,10 +773,6 @@ def make_last_call(request, name):
             doc.time = (e and e.time) or datetime.datetime.now()
             doc.save()
 
-            change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, new_state.name)
-
-            email_state_changed(request, doc, change_description)
-            
             e = LastCallDocEvent(doc=doc, by=login)
             e.type = "sent_last_call"
             e.desc = "The following Last Call announcement was sent out:<br><br>"
diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py
index fe6380481..8fc8fa106 100644
--- a/ietf/doc/views_charter.py
+++ b/ietf/doc/views_charter.py
@@ -18,8 +18,9 @@ from ietf.doc.models import ( Document, DocHistory, State, DocEvent, BallotDocEv
 from ietf.doc.utils import ( add_state_change_event, close_open_ballots,
     create_ballot_if_not_open, get_chartering_type )
 from ietf.doc.utils_charter import ( historic_milestones_for_charter,
-    approved_revision, default_review_text, default_action_text, email_state_changed,
+    approved_revision, default_review_text, default_action_text,
     generate_ballot_writeup, generate_issue_ballot_mail, next_approved_revision, next_revision )
+from ietf.doc.mails import email_state_changed
 from ietf.group.models import ChangeStateGroupEvent, MilestoneGroupEvent
 from ietf.group.utils import save_group_in_history, save_milestone_in_history, can_manage_group_type
 from ietf.ietfauth.utils import has_role, role_required
@@ -142,7 +143,8 @@ def change_state(request, name, option=None):
                 if message or charter_state.slug == "intrev" or charter_state.slug == "extrev":
                     email_iesg_secretary_re_charter(request, group, "Charter state changed to %s" % charter_state.name, message)
 
-                email_state_changed(request, charter, "State changed to %s." % charter_state)
+                # TODO - do we need a seperate set of recipients for state changes to charters vrs other kind of documents
+                email_state_changed(request, charter, "State changed to %s." % charter_state, 'doc_state_edited')
 
                 if charter_state.slug == "intrev" and group.type_id == "wg":
                     if request.POST.get("ballot_wo_extern"):
@@ -266,7 +268,7 @@ def change_title(request, name, option=None):
                 charter.save()
                 if message:
                     email_iesg_secretary_re_charter(request, group, "Charter title changed to %s" % new_title, message)
-                email_state_changed(request, charter, "Title changed to %s." % new_title)
+                email_state_changed(request, charter, "Title changed to %s." % new_title,'doc_state_edited')
             return redirect('doc_view', name=charter.name)
     else:
         form = ChangeTitleForm(charter=charter)
diff --git a/ietf/doc/views_draft.py b/ietf/doc/views_draft.py
index 30e28c8aa..36155714b 100644
--- a/ietf/doc/views_draft.py
+++ b/ietf/doc/views_draft.py
@@ -110,7 +110,7 @@ def change_state(request, name):
                 doc.time = e.time
                 doc.save()
 
-                email_state_changed(request, doc, msg)
+                email_state_changed(request, doc, msg,'doc_state_edited')
 
 
                 if prev_state and prev_state.slug in ("ann", "rfcqueue") and new_state.slug not in ("rfcqueue", "pub"):
diff --git a/ietf/mailtoken/migrations/0002_auto_20150809_1314.py b/ietf/mailtoken/migrations/0002_auto_20150809_1314.py
index 58cc019c3..0c656cb67 100644
--- a/ietf/mailtoken/migrations/0002_auto_20150809_1314.py
+++ b/ietf/mailtoken/migrations/0002_auto_20150809_1314.py
@@ -328,7 +328,19 @@ def make_mailtokens(apps):
                                ])
 
     mt_factory(slug='doc_state_edited',
-               desc="Recipients when a document's state is manutally edited",
+               desc="Recipients when a document's state is manually edited",
+               recipient_slugs=['doc_notify',
+                                'doc_ad',
+                                'doc_authors',
+                                'doc_shepherd',
+                                'doc_group_chairs',
+                                'doc_affecteddoc_authors',
+                                'doc_affecteddoc_group_chairs',
+                                'doc_affecteddoc_notify',
+                               ])
+
+    mt_factory(slug='doc_iana_state_changed',
+               desc="Recipients when IANA state information for a document changes ",
                recipient_slugs=['doc_notify',
                                 'doc_ad',
                                 'doc_authors',
diff --git a/ietf/mailtoken/models.py b/ietf/mailtoken/models.py
index ef1e6c73d..659a63430 100644
--- a/ietf/mailtoken/models.py
+++ b/ietf/mailtoken/models.py
@@ -85,11 +85,11 @@ class Recipient(models.Model):
                 addrs.extend(Recipient.objects.get(slug='doc_notify').gather(**{'doc':reldoc.document}))
         return addrs
 
-    def gather_conflict_review_stream_owner(self, **kwargs):
+    def gather_conflict_review_stream_manager(self, **kwargs):
         addrs = []
         if 'doc' in kwargs:
             for reldoc in kwargs['doc'].related_that_doc(['conflrev']):
-                addrs.extend(Recipient.objects.get(slug='doc_stream_owner').gather(**{'doc':reldoc.document}))
+                addrs.extend(Recipient.objects.get(slug='doc_stream_manager').gather(**{'doc':reldoc.document}))
         return addrs
 
     def gather_conflict_review_steering_group(self,**kwargs):
diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json
index bec077271..4b72f2fc7 100644
--- a/ietf/name/fixtures/names.json
+++ b/ietf/name/fixtures/names.json
@@ -4757,7 +4757,24 @@
    "doc_notify",
    "doc_shepherd"
   ],
-  "desc": "Recipients when a document's state is manutally edited"
+  "desc": "Recipients when IANA state information for a document changes "
+ },
+ "model": "mailtoken.mailtoken",
+ "pk": "doc_iana_state_changed"
+},
+{
+ "fields": {
+  "recipients": [
+   "doc_ad",
+   "doc_affecteddoc_authors",
+   "doc_affecteddoc_group_chairs",
+   "doc_affecteddoc_notify",
+   "doc_authors",
+   "doc_group_chairs",
+   "doc_notify",
+   "doc_shepherd"
+  ],
+  "desc": "Recipients when a document's state is manually edited"
  },
  "model": "mailtoken.mailtoken",
  "pk": "doc_state_edited"
diff --git a/ietf/secr/telechat/views.py b/ietf/secr/telechat/views.py
index eef55a74d..e32199a8e 100644
--- a/ietf/secr/telechat/views.py
+++ b/ietf/secr/telechat/views.py
@@ -261,7 +261,7 @@ def doc_detail(request, date, name):
                     doc.time = (e and e.time) or datetime.datetime.now()
                     doc.save()
 
-                    email_state_changed(request, doc, e.desc)
+                    email_state_changed(request, doc, e.desc, 'doc_state_edited')
     
                     if new_state.slug == "lc-req":
                         request_last_call(request, doc)
diff --git a/ietf/sync/iana.py b/ietf/sync/iana.py
index 9fad942b9..b611aedb4 100644
--- a/ietf/sync/iana.py
+++ b/ietf/sync/iana.py
@@ -205,7 +205,7 @@ def update_history_with_changes(changes, send_email=True):
                     doc.set_state(state)
 
                     if send_email and (state != prev_state):
-                        email_state_changed(None, doc, "IANA %s state changed to %s" % (kind, state.name))
+                        email_state_changed(None, doc, "IANA %s state changed to %s" % (kind, state.name),'doc_iana_state_changed')
 
                 if doc.time < timestamp:
                     doc.time = timestamp