From de6121c6c174ff1be1b974c9a58da7a0aec45e4e Mon Sep 17 00:00:00 2001 From: Russ Housley Date: Thu, 28 Dec 2017 20:09:56 +0000 Subject: [PATCH] Close any previous ballots when a charter goes to Internal Review or Extrernal Review. Fixes #2421. - Legacy-Id: 14467 --- ietf/doc/tests_charter.py | 69 ++++++++++++++++++++++++++++++++++++++- ietf/doc/utils.py | 10 ++++++ ietf/doc/views_charter.py | 8 ++--- 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/ietf/doc/tests_charter.py b/ietf/doc/tests_charter.py index 3d50872bb..0cd3aa77e 100644 --- a/ietf/doc/tests_charter.py +++ b/ietf/doc/tests_charter.py @@ -153,7 +153,74 @@ class EditCharterTests(TestCase): r = self.client.post(url, dict(charter_state=str(State.objects.get(used=True,type="charter",slug="intrev").pk), message="test")) self.assertEqual(r.status_code, 302) self.assertTrue("A new charter" in outbox[-3].get_payload()) - + + def test_already_open_charter_ballot(self): + # make sure the right thing happens to the charter ballots as the Secretariat + # does the unusual state sequence of: intrev --> extrev --> intrev + make_test_data() + + group = Group.objects.get(acronym="ames") + charter = group.charter + + url = urlreverse('ietf.doc.views_charter.change_state', kwargs=dict(name=charter.name)) + login_testing_unauthorized(self, "secretary", url) + by = Person.objects.get(user__username="secretary") + + # get the charter state change page + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + + # put the charter in "intrev" state + s = State.objects.get(used=True, type="charter", slug="intrev") + r = self.client.post(url, dict(charter_state=str(s.pk), message="test message")) + self.assertEqual(r.status_code, 302) + self.assertEqual(charter.get_state_slug(), "intrev") + self.assertTrue(charter.ballot_open("r-extrev")) + + events_before = charter.docevent_set.count() + + # get the charter state change page again + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + + # put the charter in "extrev" state without closing the previous ballot + s = State.objects.get(used=True, type="charter", slug="extrev") + r = self.client.post(url, dict(charter_state=str(s.pk), message="test message")) + self.assertEqual(r.status_code, 302) + charter = Document.objects.get(name="charter-ietf-%s" % group.acronym) + self.assertEqual(charter.get_state_slug(), "extrev") + self.assertTrue(charter.ballot_open("approve")) + + # make sure there is a closed_ballot event and a create_ballot event + events_now = charter.docevent_set.count() + self.assertTrue(events_now > events_before) + + def find_event(t): + return [e for e in charter.docevent_set.all()[:events_now - events_before] if e.type == t] + + self.assertTrue(find_event("closed_ballot")) + self.assertTrue(find_event("created_ballot")) + + events_before = events_now + + # get the charter state change page for a third time + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + + # put the charter back in "intrev" state without closing the previous ballot + s = State.objects.get(used=True, type="charter", slug="intrev") + r = self.client.post(url, dict(charter_state=str(s.pk), message="test message")) + self.assertEqual(r.status_code, 302) + charter = Document.objects.get(name="charter-ietf-%s" % group.acronym) + self.assertEqual(charter.get_state_slug(), "intrev") + self.assertTrue(charter.ballot_open("r-extrev")) + + # make sure there is a closed_ballot event and a create_ballot event + events_now = charter.docevent_set.count() + self.assertTrue(events_now > events_before) + self.assertTrue(find_event("closed_ballot")) + self.assertTrue(find_event("created_ballot")) + def test_edit_telechat_date(self): make_test_data() diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index 42edb66a6..8e3079a5f 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -174,6 +174,16 @@ def needed_ballot_positions(doc, active_positions): return " ".join(answer) +def create_ballot(doc, by, ballot_slug, time=None): + close_open_ballots(doc, by) + if time: + e = BallotDocEvent(type="created_ballot", by=by, doc=doc, rev=doc.rev, time=time) + else: + e = BallotDocEvent(type="created_ballot", by=by, doc=doc, rev=doc.rev) + e.ballot_type = BallotType.objects.get(doc_type=doc.type, slug=ballot_slug) + e.desc = u'Created "%s" ballot' % e.ballot_type.name + e.save() + def create_ballot_if_not_open(doc, by, ballot_slug, time=None): if not doc.ballot_open(ballot_slug): if time: diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py index d05e872b8..5e6e768f0 100644 --- a/ietf/doc/views_charter.py +++ b/ietf/doc/views_charter.py @@ -15,7 +15,7 @@ from ietf.doc.models import ( Document, DocAlias, DocHistory, State, DocEvent, BallotDocEvent, BallotPositionDocEvent, InitialReviewDocEvent, NewRevisionDocEvent, WriteupDocEvent ) from ietf.doc.utils import ( add_state_change_event, close_open_ballots, - create_ballot_if_not_open, get_chartering_type ) + create_ballot, 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, generate_ballot_writeup, generate_issue_ballot_mail, next_revision, @@ -152,16 +152,16 @@ def change_state(request, name, option=None): if charter_state.slug == "intrev" and group.type_id == "wg": if request.POST.get("ballot_wo_extern"): - create_ballot_if_not_open(charter, by, "r-wo-ext") + create_ballot(charter, by, "r-wo-ext") else: - create_ballot_if_not_open(charter, by, "r-extrev") + create_ballot(charter, by, "r-extrev") (e1, e2) = default_review_text(group, charter, by) e1.save() e2.save() e = default_action_text(group, charter, by) e.save() elif charter_state.slug in ["extrev","iesgrev"]: - create_ballot_if_not_open(charter, by, "approve") + create_ballot(charter, by, "approve") elif charter_state.slug == "approved": change_group_state_after_charter_approval(group, by) fix_charter_revision_after_approval(charter, by)