feat: Update IRTF state when entering/exiting IETF conflict review (#6424)

* feat: Update IRTF state when entering/exiting IETF conflict review (#3469)

* fix: Update IRTF state in approve_conflict_review() as well

* chore: Add "new_state != prev_state" guard
This commit is contained in:
Paul Selkirk 2023-10-09 16:01:35 -04:00 committed by GitHub
parent 5e0d1bef0f
commit f19d1047c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 4 deletions

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2012-2020, All Rights Reserved
# Copyright The IETF Trust 2012-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -13,8 +13,8 @@ from django.urls import reverse as urlreverse
import debug # pyflakes:ignore
from ietf.doc.factories import IndividualDraftFactory, ConflictReviewFactory
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, BallotPositionDocEvent, TelechatDocEvent, State
from ietf.doc.factories import IndividualDraftFactory, ConflictReviewFactory, RgDraftFactory
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, BallotPositionDocEvent, TelechatDocEvent, State, DocTagName
from ietf.doc.utils import create_ballot_if_not_open
from ietf.doc.views_conflict_review import default_approval_text
from ietf.group.models import Person
@ -450,3 +450,65 @@ class ConflictReviewSubmitTests(TestCase):
def setUp(self):
super().setUp()
ConflictReviewFactory(name='conflict-review-imaginary-irtf-submission',review_of=IndividualDraftFactory(name='draft-imaginary-irtf-submission',stream_id='irtf'),notify='notifyme@example.net')
class ConflictReviewIrtfStateTests(TestCase):
def start_review(self, role, kwargs=None):
doc = RgDraftFactory()
url = urlreverse('ietf.doc.views_conflict_review.start_review', kwargs=dict(name=doc.name))
login_testing_unauthorized(self, role, url)
r = self.client.post(url, kwargs)
self.assertEqual(r.status_code, 302)
self.assertEqual(doc.get_state('draft-stream-irtf').slug, 'iesg-rev')
def test_start_review_as_secretary(self):
ad_strpk = str(Person.objects.get(name='Areað Irector').pk)
state_strpk = str(State.objects.get(used=True, slug='needshep', type__slug='conflrev').pk)
self.start_review('secretary', kwargs=dict(ad=ad_strpk, create_in_state=state_strpk))
def test_start_review_as_stream_owner(self):
self.start_review('irtf-chair')
def close_review(self, close_type, role):
doc = RgDraftFactory()
review = ConflictReviewFactory(review_of=doc)
url = urlreverse('ietf.doc.views_conflict_review.change_state', kwargs=dict(name=review.name))
login_testing_unauthorized(self, role, url)
strpk = str(State.objects.get(used=True, slug=close_type, type__slug='conflrev').pk)
r = self.client.post(url, dict(review_state=strpk))
self.assertEqual(r.status_code, 302)
self.assertEqual(doc.get_state('draft-stream-irtf').slug, 'chair-w')
self.assertIn(DocTagName.objects.get(pk='iesg-com'), doc.tags.all())
def test_close_review_reqnopub_as_secretary(self):
self.close_review('appr-reqnopub-sent', 'secretary')
def test_close_review_noprob_as_secretary(self):
self.close_review('appr-noprob-sent', 'secretary')
def test_close_review_withdraw_as_secretary(self):
self.close_review('withdraw', 'secretary')
def test_close_review_dead_as_secretary(self):
self.close_review('dead', 'secretary')
def test_close_review_withdraw_as_ad(self):
self.close_review('withdraw', 'ad')
def test_close_review_dead_as_ad(self):
self.close_review('dead', 'ad')
def test_approve_review(self):
doc = RgDraftFactory()
review = ConflictReviewFactory(review_of=doc)
review.set_state(State.objects.get(used=True, slug='appr-noprob-pend', type='conflrev'))
url = urlreverse('ietf.doc.views_conflict_review.approve_conflict_review', kwargs=dict(name=review.name))
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url, dict(announcement_text=default_approval_text(review)))
self.assertEqual(r.status_code, 302)
self.assertEqual(doc.get_state('draft-stream-irtf').slug, 'chair-w')
self.assertIn(DocTagName.objects.get(pk='iesg-com'), doc.tags.all())

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2012-2020, All Rights Reserved
# Copyright The IETF Trust 2012-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -25,6 +25,7 @@ from ietf.doc.forms import AdForm
from ietf.group.models import Role, Group
from ietf.iesg.models import TelechatDate
from ietf.ietfauth.utils import has_role, role_required, is_authorized_in_doc_stream
from ietf.name.models import DocTagName
from ietf.person.models import Person
from ietf.utils import log
from ietf.utils.mail import send_mail_preformatted
@ -90,6 +91,10 @@ def change_state(request, name, option=None):
review,
ok_to_publish)
if new_state.slug in ["appr-reqnopub-sent", "appr-noprob-sent", "withdraw", "dead"]:
doc = review.related_that_doc("conflrev")[0].document
if doc.stream_id == "irtf":
close_review_irtf_state(doc, login)
return redirect('ietf.doc.views_doc.document_main', name=review.name)
else:
@ -355,6 +360,10 @@ def approve_conflict_review(request, name):
c.desc = "The following approval message was sent\n"+form.cleaned_data['announcement_text']
c.save()
doc = review.related_that_doc("conflrev")[0].document
if doc.stream_id == "irtf":
close_review_irtf_state(doc, login)
return HttpResponseRedirect(review.get_absolute_url())
else:
@ -488,6 +497,9 @@ def start_review_as_secretariat(request, name):
send_conflict_review_started_email(request, conflict_review)
if doc_to_review.stream_id == 'irtf':
start_review_irtf_state(doc_to_review, login)
return HttpResponseRedirect(conflict_review.get_absolute_url())
else:
notify_addresses = build_notify_addresses(doc_to_review)
@ -522,6 +534,9 @@ def start_review_as_stream_owner(request, name):
send_conflict_review_started_email(request, conflict_review)
if doc_to_review.stream_id == 'irtf':
start_review_irtf_state(doc_to_review, login)
return HttpResponseRedirect(conflict_review.get_absolute_url())
else:
notify_addresses = build_notify_addresses(doc_to_review)
@ -536,3 +551,26 @@ def start_review_as_stream_owner(request, name):
'doc_to_review': doc_to_review,
},
)
def start_review_irtf_state(doc, by):
prev_state = doc.get_state('draft-stream-irtf')
new_state = State.objects.get(type_id='draft-stream-irtf', slug='iesg-rev')
if new_state != prev_state:
doc.set_state(new_state)
events = []
events.append(add_state_change_event(doc, by, prev_state, new_state))
doc.save_with_history(events)
def close_review_irtf_state(doc, by):
prev_state = doc.get_state("draft-stream-irtf")
new_state = State.objects.get(type_id="draft-stream-irtf", slug="chair-w")
prev_tags = set(doc.tags.all())
new_tags = set(DocTagName.objects.filter(pk="iesg-com"))
if new_state != prev_state:
doc.set_state(new_state)
doc.tags.clear()
doc.tags.set(new_tags)
events = [add_state_change_event(doc, by, prev_state, new_state, prev_tags, new_tags)]
doc.save_with_history(events)