def change_state(request, name, option=None): """Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary and logging the change as a comment.""" review = get_object_or_404(Document, type="conflrev", name=name) login = request.user.get_profile() if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): clean = form.cleaned_data review_state = clean['review_state'] comment = clean['comment'].rstrip() if comment: c = DocEvent(type="added_comment", doc=review, by=login) c.desc = comment c.save() if review_state != review.get_state(): save_document_in_history(review) old_description = review.friendly_state() review.set_state(review_state) new_description = review.friendly_state() log_state_changed(request, review, login, new_description, old_description) review.time = datetime.datetime.now() review.save() if review_state.slug == "iesgeval": create_ballot_if_not_open(review, login, "conflrev") ballot = review.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director") and not review.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"): # The AD putting a conflict review into iesgeval who doesn't already have a position is saying "yes" pos = BallotPositionDocEvent(doc=review, by=login) pos.ballot = ballot pos.type = "changed_ballot_position" pos.ad = login pos.pos_id = "yes" pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name()) pos.save() send_conflict_eval_email(request,review) return redirect('doc_view', name=review.name) else: s = review.get_state() init = dict(review_state=s.pk if s else None) form = ChangeStateForm(initial=init) return render_to_response('doc/change_state.html', dict(form=form, doc=review, login=login, help_url=reverse('help_conflict_review_states'), ), context_instance=RequestContext(request))
def test_approve(self): doc = Document.objects.get(name='status-change-imaginary-mid-review') url = urlreverse('status_change_approve', kwargs=dict(name=doc.name)) login_testing_unauthorized(self, "secretary", url) # Some additional setup doc.relateddocument_set.create( target=DocAlias.objects.get(name='rfc9999'), relationship_id='tois') doc.relateddocument_set.create( target=DocAlias.objects.get(name='rfc9998'), relationship_id='tohist') create_ballot_if_not_open(doc, Person.objects.get(name="Sec Retary"), "statchg") doc.set_state(State.objects.get(slug='appr-pend', type='statchg')) doc.save() # get r = self.client.get(url) self.assertEquals(r.status_code, 200) q = PyQuery(r.content) self.assertEquals(len(q('form.approve')), 1) # There should be two messages to edit self.assertEquals(q('input#id_form-TOTAL_FORMS').val(), '2') self.assertTrue('(rfc9999) to Internet Standard' in ''.join( wrap(r.content, 2**16))) self.assertTrue( '(rfc9998) to Historic' in ''.join(wrap(r.content, 2**16))) # submit messages_before = len(outbox) msg0 = default_approval_text(doc, doc.relateddocument_set.all()[0]) msg1 = default_approval_text(doc, doc.relateddocument_set.all()[1]) r = self.client.post( url, { 'form-0-announcement_text': msg0, 'form-1-announcement_text': msg1, 'form-TOTAL_FORMS': '2', 'form-INITIAL_FORMS': '2', 'form-MAX_NUM_FORMS': '' }) self.assertEquals(r.status_code, 302) doc = Document.objects.get(name='status-change-imaginary-mid-review') self.assertEquals(doc.get_state_slug(), 'appr-sent') self.assertFalse(doc.ballot_open("statchg")) self.assertEquals(len(outbox), messages_before + 2) self.assertTrue('Action:' in outbox[-1]['Subject']) self.assertTrue('(rfc9999) to Internet Standard' in ''.join( wrap(unicode(outbox[-1]) + unicode(outbox[-2]), 2**16))) self.assertTrue('(rfc9998) to Historic' in ''.join( wrap(unicode(outbox[-1]) + unicode(outbox[-2]), 2**16))) self.assertTrue( doc.latest_event(DocEvent, type="added_comment").desc.startswith( 'The following approval message was sent'))
def change_state(request, name, option=None): """Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary and logging the change as a comment.""" review = get_object_or_404(Document, type="conflrev", name=name) login = request.user.person if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): clean = form.cleaned_data new_state = clean['review_state'] comment = clean['comment'].rstrip() if comment: c = DocEvent(type="added_comment", doc=review, rev=review.rev, by=login) c.desc = comment c.save() prev_state = review.get_state() if new_state != prev_state: events = [] review.set_state(new_state) events.append(add_state_change_event(review, login, prev_state, new_state)) review.save_with_history(events) if new_state.slug == "iesgeval": create_ballot_if_not_open(review, login, "conflrev") ballot = review.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director") and not review.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"): # The AD putting a conflict review into iesgeval who doesn't already have a position is saying "yes" pos = BallotPositionDocEvent(doc=review, rev=review.rev, by=login) pos.ballot = ballot pos.type = "changed_ballot_position" pos.ad = login pos.pos_id = "yes" pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name()) pos.save() # Consider mailing that position to 'ballot_saved' send_conflict_eval_email(request,review) return redirect('ietf.doc.views_doc.document_main', name=review.name) else: s = review.get_state() init = dict(review_state=s.pk if s else None) form = ChangeStateForm(initial=init) return render(request, 'doc/change_state.html', dict(form=form, doc=review, login=login, help_url=reverse('ietf.doc.views_help.state_help', kwargs=dict(type="conflict-review")), ))
def clear_ballot(request, name): """Clear all positions and discusses on every open ballot for a document.""" doc = get_object_or_404(Document, name=name) if request.method == 'POST': by = request.user.person for t in BallotType.objects.filter(doc_type=doc.type_id): close_ballot(doc, by, t.slug) create_ballot_if_not_open(doc, by, t.slug) if doc.get_state('draft-iesg').slug == 'defer': do_undefer_ballot(request, doc) return redirect("ietf.doc.views_doc.document_main", name=doc.name) return render(request, 'doc/ballot/clear_ballot.html', dict(doc=doc, back_url=doc.get_absolute_url()))
def approve_test_helper(self, approve_type): doc = Document.objects.get( name='conflict-review-imaginary-irtf-submission') url = urlreverse('conflict_review_approve', kwargs=dict(name=doc.name)) login_testing_unauthorized(self, "secretary", url) # Some additional setup create_ballot_if_not_open(doc, Person.objects.get(name="Sec Retary"), "conflrev") doc.set_state( State.objects.get(used=True, slug=approve_type + '-pend', type='conflrev')) doc.save() # get r = self.client.get(url) self.assertEquals(r.status_code, 200) q = PyQuery(r.content) self.assertEquals(len(q('form.approve')), 1) if approve_type == 'appr-noprob': self.assertTrue( 'IESG has no problem' in ''.join(wrap(r.content, 2**16))) else: self.assertTrue( 'NOT be published' in ''.join(wrap(r.content, 2**16))) # submit messages_before = len(outbox) r = self.client.post( url, dict(announcement_text=default_approval_text(doc))) self.assertEquals(r.status_code, 302) doc = Document.objects.get( name='conflict-review-imaginary-irtf-submission') self.assertEquals(doc.get_state_slug(), approve_type + '-sent') self.assertFalse(doc.ballot_open("conflrev")) self.assertEquals(len(outbox), messages_before + 1) self.assertTrue( 'Results of IETF-conflict review' in outbox[-1]['Subject']) if approve_type == 'appr-noprob': self.assertTrue('IESG has no problem' in ''.join( wrap(unicode(outbox[-1]), 2**16))) else: self.assertTrue('NOT be published' in ''.join( wrap(unicode(outbox[-1]), 2**16)))
def clear_ballot(request, name): """Clear all positions and discusses on every open ballot for a document.""" doc = get_object_or_404(Document, name=name) if request.method == 'POST': by = request.user.person for t in BallotType.objects.filter(doc_type=doc.type_id): close_ballot(doc, by, t.slug) create_ballot_if_not_open(doc, by, t.slug) if doc.get_state('draft-iesg').slug == 'defer': do_undefer_ballot(request,doc) return redirect("doc_view", name=doc.name) return render_to_response('doc/ballot/clear_ballot.html', dict(doc=doc, back_url=doc.get_absolute_url()), context_instance=RequestContext(request))
def test_approve(self): doc = Document.objects.get(name='status-change-imaginary-mid-review') url = urlreverse('status_change_approve',kwargs=dict(name=doc.name)) login_testing_unauthorized(self, "secretary", url) # Some additional setup doc.relateddocument_set.create(target=DocAlias.objects.get(name='rfc9999'),relationship_id='tois') doc.relateddocument_set.create(target=DocAlias.objects.get(name='rfc9998'),relationship_id='tohist') create_ballot_if_not_open(doc,Person.objects.get(name="Sec Retary"),"statchg") doc.set_state(State.objects.get(slug='appr-pend',type='statchg')) doc.save() # get r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) self.assertEqual(len(q('[type=submit]:contains("Send announcement")')), 1) # There should be two messages to edit self.assertEqual(q('input#id_form-TOTAL_FORMS').val(),'2') self.assertTrue( '(rfc9999) to Internet Standard' in ''.join(wrap(r.content,2**16))) self.assertTrue( '(rfc9998) to Historic' in ''.join(wrap(r.content,2**16))) # submit messages_before = len(outbox) msg0=default_approval_text(doc,doc.relateddocument_set.all()[0]) msg1=default_approval_text(doc,doc.relateddocument_set.all()[1]) r = self.client.post(url,{'form-0-announcement_text':msg0,'form-1-announcement_text':msg1,'form-TOTAL_FORMS':'2','form-INITIAL_FORMS':'2','form-MAX_NUM_FORMS':''}) self.assertEqual(r.status_code, 302) doc = Document.objects.get(name='status-change-imaginary-mid-review') self.assertEqual(doc.get_state_slug(),'appr-sent') self.assertFalse(doc.ballot_open("statchg")) self.assertEqual(len(outbox), messages_before + 2) self.assertTrue('Action:' in outbox[-1]['Subject']) self.assertTrue('ietf-announce' in outbox[-1]['To']) self.assertTrue('rfc-editor' in outbox[-1]['Cc']) self.assertTrue('(rfc9998) to Historic' in ''.join(wrap(unicode(outbox[-1])+unicode(outbox[-2]),2**16))) self.assertTrue('(rfc9999) to Internet Standard' in ''.join(wrap(unicode(outbox[-1])+unicode(outbox[-2]),2**16))) self.assertTrue(doc.latest_event(DocEvent,type="added_comment").desc.startswith('The following approval message was sent'))
def approve_test_helper(self,approve_type): doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission') url = urlreverse('conflict_review_approve',kwargs=dict(name=doc.name)) login_testing_unauthorized(self, "secretary", url) # Some additional setup create_ballot_if_not_open(doc,Person.objects.get(name="Sec Retary"),"conflrev") doc.set_state(State.objects.get(used=True, slug=approve_type+'-pend',type='conflrev')) doc.save() # get r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) self.assertEqual(len(q('[type=submit]:contains("Send announcement")')), 1) if approve_type == 'appr-noprob': self.assertTrue( 'IESG has no problem' in ''.join(wrap(r.content,2**16))) else: self.assertTrue( 'NOT be published' in ''.join(wrap(r.content,2**16))) # submit empty_outbox() r = self.client.post(url,dict(announcement_text=default_approval_text(doc))) self.assertEqual(r.status_code, 302) doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission') self.assertEqual(doc.get_state_slug(),approve_type+'-sent') self.assertFalse(doc.ballot_open("conflrev")) self.assertEqual(len(outbox), 1) self.assertTrue('Results of IETF-conflict review' in outbox[0]['Subject']) self.assertTrue('irtf-chair' in outbox[0]['To']) self.assertTrue('ietf-announce@' in outbox[0]['Cc']) self.assertTrue('iana@' in outbox[0]['Cc']) if approve_type == 'appr-noprob': self.assertTrue( 'IESG has no problem' in ''.join(wrap(unicode(outbox[0]),2**16))) else: self.assertTrue( 'NOT be published' in ''.join(wrap(unicode(outbox[0]),2**16)))
def ballot_writeupnotes(request, name): """Editing of ballot write-up and notes""" doc = get_object_or_404(Document, docalias__name=name) login = request.user.person existing = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text") if not existing: existing = generate_ballot_writeup(request, doc) form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text)) if request.method == 'POST' and "save_ballot_writeup" in request.POST or "issue_ballot" in request.POST: form = BallotWriteupForm(request.POST) if form.is_valid(): t = form.cleaned_data["ballot_writeup"] if t != existing.text: e = WriteupDocEvent(doc=doc, rev=doc.rev, by=login) e.by = login e.type = "changed_ballot_writeup_text" e.desc = "Ballot writeup was changed" e.text = t e.save() elif existing.pk == None: existing.save() if "issue_ballot" in request.POST: create_ballot_if_not_open(doc, login, "approve") ballot = doc.latest_event(BallotDocEvent, type="created_ballot") if has_role( request.user, "Area Director") and not doc.latest_event( BallotPositionDocEvent, ad=login, ballot=ballot): # sending the ballot counts as a yes pos = BallotPositionDocEvent(doc=doc, rev=doc.rev, by=login) pos.ballot = ballot pos.type = "changed_ballot_position" pos.ad = login pos.pos_id = "yes" pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % ( pos.pos.name, pos.ad.plain_name()) pos.save() # Consider mailing this position to 'ballot_saved' approval = doc.latest_event( WriteupDocEvent, type="changed_ballot_approval_text") if not approval: approval = generate_approval_mail(request, doc) approval.save() msg = generate_issue_ballot_mail(request, doc, ballot) addrs = gather_address_lists('ballot_issued', doc=doc).as_strings() override = {'To': addrs.to} if addrs.cc: override['CC'] = addrs.cc send_mail_preformatted(request, msg, override=override) addrs = gather_address_lists('ballot_issued_iana', doc=doc).as_strings() override = { "To": "IANA <%s>" % settings.IANA_EVAL_EMAIL, "Bcc": None, "Reply-To": None } if addrs.cc: override['CC'] = addrs.cc send_mail_preformatted(request, msg, extra=extra_automation_headers(doc), override={ "To": "IANA <%s>" % settings.IANA_EVAL_EMAIL, "CC": None, "Bcc": None, "Reply-To": None }) e = DocEvent(doc=doc, rev=doc.rev, by=login) e.by = login e.type = "sent_ballot_announcement" e.desc = "Ballot has been issued" e.save() return render(request, 'doc/ballot/ballot_issued.html', dict(doc=doc, back_url=doc.get_absolute_url())) need_intended_status = "" if not doc.intended_std_level: need_intended_status = doc.file_tag() return render( request, 'doc/ballot/writeupnotes.html', dict( doc=doc, back_url=doc.get_absolute_url(), ballot_issued=bool( doc.latest_event(type="sent_ballot_announcement")), ballot_writeup_form=form, need_intended_status=need_intended_status, ))
def change_state(request, name, option=None): """Change state of an status-change document, notifying parties as necessary and logging the change as a comment.""" status_change = get_object_or_404(Document, type="statchg", name=name) login = request.user.person if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): clean = form.cleaned_data new_state = clean['new_state'] comment = clean['comment'].rstrip() if comment: c = DocEvent(type="added_comment", doc=status_change, by=login) c.desc = comment c.save() prev_state = status_change.get_state() if new_state != prev_state: save_document_in_history(status_change) status_change.set_state(new_state) e = add_state_change_event(status_change, login, prev_state, new_state) status_change.time = e.time status_change.save() if new_state.slug == "iesgeval": create_ballot_if_not_open(status_change, login, "statchg", e.time) ballot = status_change.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director") and not status_change.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"): # The AD putting a status change into iesgeval who doesn't already have a position is saying "yes" pos = BallotPositionDocEvent(doc=status_change, by=login) pos.ballot = ballot pos.type = "changed_ballot_position" pos.ad = login pos.pos_id = "yes" pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name()) pos.save() send_status_change_eval_email(request,status_change) if new_state.slug == "lc-req": request_last_call(request, status_change) return render_to_response('doc/draft/last_call_requested.html', dict(doc=status_change, url = status_change.get_absolute_url(), ), context_instance=RequestContext(request)) return redirect('doc_view', name=status_change.name) else: s = status_change.get_state() init = dict(new_state=s.pk if s else None, type='statchg', label='Status Change Evaluation State', ) form = ChangeStateForm(initial=init) return render_to_response('doc/change_state.html', dict(form=form, doc=status_change, login=login, help_url=reverse('state_help', kwargs=dict(type="status-change")), ), context_instance=RequestContext(request))
def ballot_writeupnotes(request, name): """Editing of ballot write-up and notes""" doc = get_object_or_404(Document, docalias__name=name) login = request.user.person existing = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text") if not existing: existing = generate_ballot_writeup(request, doc) form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text)) if request.method == 'POST' and "save_ballot_writeup" in request.POST or "issue_ballot" in request.POST: form = BallotWriteupForm(request.POST) if form.is_valid(): t = form.cleaned_data["ballot_writeup"] if t != existing.text: e = WriteupDocEvent(doc=doc, by=login) e.by = login e.type = "changed_ballot_writeup_text" e.desc = "Ballot writeup was changed" e.text = t e.save() if "issue_ballot" in request.POST: create_ballot_if_not_open(doc, login, "approve") ballot = doc.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director") and not doc.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot): # sending the ballot counts as a yes pos = BallotPositionDocEvent(doc=doc, by=login) pos.ballot = ballot pos.type = "changed_ballot_position" pos.ad = login pos.pos_id = "yes" pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name()) pos.save() approval = doc.latest_event(WriteupDocEvent, type="changed_ballot_approval_text") if not approval: approval = generate_approval_mail(request, doc) msg = generate_issue_ballot_mail(request, doc, ballot) send_mail_preformatted(request, msg) send_mail_preformatted(request, msg, extra=extra_automation_headers(doc), override={ "To": "IANA <%s>"%settings.IANA_EVAL_EMAIL, "CC": None, "Bcc": None , "Reply-To": None}) e = DocEvent(doc=doc, by=login) e.by = login e.type = "sent_ballot_announcement" e.desc = "Ballot has been issued" e.save() return render_to_response('doc/ballot/ballot_issued.html', dict(doc=doc, back_url=doc.get_absolute_url()), context_instance=RequestContext(request)) need_intended_status = "" if not doc.intended_std_level: need_intended_status = doc.file_tag() return render_to_response('doc/ballot/writeupnotes.html', dict(doc=doc, back_url=doc.get_absolute_url(), ballot_issued=bool(doc.latest_event(type="sent_ballot_announcement")), ballot_writeup_form=form, need_intended_status=need_intended_status, ), context_instance=RequestContext(request))
def change_state(request, name, option=None): """Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary and logging the change as a comment.""" review = get_object_or_404(Document, type="conflrev", name=name) login = request.user.get_profile() if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): clean = form.cleaned_data review_state = clean['review_state'] comment = clean['comment'].rstrip() if comment: c = DocEvent(type="added_comment", doc=review, by=login) c.desc = comment c.save() if review_state != review.get_state(): save_document_in_history(review) old_description = review.friendly_state() review.set_state(review_state) new_description = review.friendly_state() log_state_changed(request, review, login, new_description, old_description) review.time = datetime.datetime.now() review.save() if review_state.slug == "iesgeval": create_ballot_if_not_open(review, login, "conflrev") ballot = review.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director") and not review.latest_event( BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"): # The AD putting a conflict review into iesgeval who doesn't already have a position is saying "yes" pos = BallotPositionDocEvent(doc=review, by=login) pos.ballot = ballot pos.type = "changed_ballot_position" pos.ad = login pos.pos_id = "yes" pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % ( pos.pos.name, pos.ad.plain_name()) pos.save() send_conflict_eval_email(request, review) return redirect('doc_view', name=review.name) else: s = review.get_state() init = dict(review_state=s.pk if s else None) form = ChangeStateForm(initial=init) return render_to_response( 'doc/change_state.html', dict( form=form, doc=review, login=login, help_url=reverse('help_conflict_review_states'), ), context_instance=RequestContext(request))
def change_state(request, name, option=None): """Change state of an status-change document, notifying parties as necessary and logging the change as a comment.""" status_change = get_object_or_404(Document, type="statchg", name=name) login = request.user.person if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): clean = form.cleaned_data new_state = clean['new_state'] comment = clean['comment'].rstrip() if comment: c = DocEvent(type="added_comment", doc=status_change, rev=status_change.rev, by=login) c.desc = comment c.save() prev_state = status_change.get_state() if new_state != prev_state: status_change.set_state(new_state) events = [] events.append( add_state_change_event(status_change, login, prev_state, new_state)) status_change.save_with_history(events) if new_state.slug == "iesgeval": create_ballot_if_not_open(status_change, login, "statchg", status_change.time) ballot = status_change.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director" ) and not status_change.latest_event( BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"): # The AD putting a status change into iesgeval who doesn't already have a position is saying "yes" pos = BallotPositionDocEvent(doc=status_change, rev=status_change.rev, by=login) pos.ballot = ballot pos.type = "changed_ballot_position" pos.ad = login pos.pos_id = "yes" pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % ( pos.pos.name, pos.ad.plain_name()) pos.save() send_status_change_eval_email(request, status_change) if new_state.slug == "lc-req": request_last_call(request, status_change) return render( request, 'doc/draft/last_call_requested.html', dict( doc=status_change, url=status_change.get_absolute_url(), )) return redirect('ietf.doc.views_doc.document_main', name=status_change.name) else: s = status_change.get_state() init = dict( new_state=s.pk if s else None, type='statchg', label='Status Change Evaluation State', ) form = ChangeStateForm(initial=init) return render( request, 'doc/change_state.html', dict( form=form, doc=status_change, login=login, help_url=reverse('ietf.doc.views_help.state_help', kwargs=dict(type="status-change")), ))
def change_state(request, name, option=None): """Change state of charter, notifying parties as necessary and logging the change as a comment.""" charter = get_object_or_404(Document, type="charter", name=name) group = charter.group if not can_manage_group_type(request.user, group.type_id): return HttpResponseForbidden("You don't have permission to access this view") chartering_type = get_chartering_type(charter) initial_review = charter.latest_event(InitialReviewDocEvent, type="initial_review") if charter.get_state_slug() != "infrev" or (initial_review and initial_review.expires < datetime.datetime.now()) or chartering_type == "rechartering": initial_review = None login = request.user.person if request.method == 'POST': form = ChangeStateForm(request.POST, group=group) if form.is_valid(): clean = form.cleaned_data charter_rev = charter.rev if option in ("initcharter", "recharter"): if group.type_id == "wg": charter_state = State.objects.get(used=True, type="charter", slug="infrev") else: charter_state = clean['charter_state'] # make sure we have the latest revision set, if we # abandoned a charter before, we could have reset the # revision to latest approved prev_revs = charter.history_set.order_by('-rev')[:1] if prev_revs and prev_revs[0].rev > charter_rev: charter_rev = prev_revs[0].rev if "-" not in charter_rev: charter_rev = charter_rev + "-00" elif option == "abandon": oldstate = group.state if oldstate.slug in ("proposed", "bof", "unknown"): charter_state = State.objects.get(used=True, type="charter", slug="notrev") #TODO : set an abandoned state and leave some comments here group.state = GroupStateName.objects.get(slug='abandon') group.save() e = ChangeStateGroupEvent(group=group, type="changed_state") e.time = group.time e.by = login e.state_id = group.state.slug e.desc = "Group state changed to %s from %s" % (group.state, oldstate) e.save() else: charter_state = State.objects.get(used=True, type="charter", slug="approved") charter_rev = approved_revision(charter.rev) else: charter_state = clean['charter_state'] comment = clean['comment'].rstrip() message = clean['message'] if charter_state != charter.get_state(): # Charter state changed save_document_in_history(charter) prev_state = charter.get_state() new_state = charter_state charter.set_state(new_state) charter.rev = charter_rev if option != "abandon": add_state_change_event(charter, login, prev_state, new_state) else: # kill hanging ballots close_open_ballots(charter, login) # Special log for abandoned efforts e = DocEvent(type="changed_document", doc=charter, by=login) e.desc = "IESG has abandoned the chartering effort" e.save() if comment: c = DocEvent(type="added_comment", doc=charter, by=login) c.desc = comment c.save() charter.time = datetime.datetime.now() charter.save() if charter_state.slug == 'intrev': email_charter_internal_review(request,charter) if message or charter_state.slug == "intrev" or charter_state.slug == "extrev": email_admin_re_charter(request, group, "Charter state changed to %s" % charter_state.name, message,'charter_state_edit_admin_needed') # 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"): create_ballot_if_not_open(charter, login, "r-wo-ext") else: create_ballot_if_not_open(charter, login, "r-extrev") default_review_text(group, charter, login) default_action_text(group, charter, login) elif charter_state.slug == "iesgrev": create_ballot_if_not_open(charter, login, "approve") elif charter_state.slug == "approved": change_group_state_after_charter_approval(group, login) fix_charter_revision_after_approval(charter, login) if charter_state.slug == "infrev" and clean["initial_time"] and clean["initial_time"] != 0: e = InitialReviewDocEvent(type="initial_review", by=login, doc=charter) e.expires = datetime.datetime.now() + datetime.timedelta(weeks=clean["initial_time"]) e.desc = "Initial review time expires %s" % e.expires.strftime("%Y-%m-%d") e.save() return redirect('doc_view', name=charter.name) else: hide = ['initial_time'] s = charter.get_state() init = dict(charter_state=s.pk if s and option != "recharter" else None) if option == "abandon": hide = ['initial_time', 'charter_state'] if group.type_id == "wg": if option == "recharter": hide = ['initial_time', 'charter_state', 'message'] init = dict() elif option == "initcharter": hide = ['charter_state'] init = dict(initial_time=1, message='%s has initiated chartering of the proposed %s:\n "%s" (%s).' % (login.plain_name(), group.type.name, group.name, group.acronym)) elif option == "abandon": hide = ['initial_time', 'charter_state'] init = dict(message='%s has abandoned the chartering effort on the %s:\n "%s" (%s).' % (login.plain_name(), group.type.name, group.name, group.acronym)) form = ChangeStateForm(hide=hide, initial=init, group=group) prev_charter_state = None charter_hists = DocHistory.objects.filter(doc=charter).exclude(states__type="charter", states__slug=charter.get_state_slug()).order_by("-time")[:1] if charter_hists: prev_charter_state = charter_hists[0].get_state() title = { "initcharter": "Initiate chartering of %s %s" % (group.acronym, group.type.name), "recharter": "Recharter %s %s" % (group.acronym, group.type.name), "abandon": "Abandon effort on %s %s" % (group.acronym, group.type.name), }.get(option) if not title: title = "Change chartering state of %s %s" % (group.acronym, group.type.name) def state_pk(slug): return State.objects.get(used=True, type="charter", slug=slug).pk info_msg = {} if group.type_id == "wg": info_msg[state_pk("infrev")] = 'The proposed charter for %s "%s" (%s) has been set to Informal IESG review by %s.' % (group.type.name, group.name, group.acronym, login.plain_name()) info_msg[state_pk("intrev")] = 'The proposed charter for %s "%s" (%s) has been set to Internal review by %s.\nPlease place it on the next IESG telechat if it has not already been placed.' % (group.type.name, group.name, group.acronym, login.plain_name()) info_msg[state_pk("extrev")] = 'The proposed charter for %s "%s" (%s) has been set to External review by %s.\nPlease send out the external review announcement to the appropriate lists.\n\nSend the announcement to other SDOs: Yes\nAdditional recipients of the announcement: ' % (group.type.name, group.name, group.acronym, login.plain_name()) states_for_ballot_wo_extern = State.objects.none() if group.type_id == "wg": states_for_ballot_wo_extern = State.objects.filter(used=True, type="charter", slug="intrev").values_list("pk", flat=True) return render_to_response('doc/charter/change_state.html', dict(form=form, doc=group.charter, login=login, option=option, prev_charter_state=prev_charter_state, title=title, initial_review=initial_review, chartering_type=chartering_type, info_msg=json.dumps(info_msg), states_for_ballot_wo_extern=json.dumps(list(states_for_ballot_wo_extern)), ), context_instance=RequestContext(request))
def change_state(request, name, option=None): """Change state of charter, notifying parties as necessary and logging the change as a comment.""" charter = get_object_or_404(Document, type="charter", name=name) group = charter.group if not can_manage_group_type(request.user, group): return HttpResponseForbidden( "You don't have permission to access this view") chartering_type = get_chartering_type(charter) initial_review = charter.latest_event(InitialReviewDocEvent, type="initial_review") if charter.get_state_slug() != "infrev" or ( initial_review and initial_review.expires < datetime.datetime.now()) or chartering_type == "rechartering": initial_review = None by = request.user.person if request.method == 'POST': form = ChangeStateForm(request.POST, group=group) if form.is_valid(): clean = form.cleaned_data charter_rev = charter.rev if option in ("initcharter", "recharter"): if group.type_id == "wg": charter_state = State.objects.get(used=True, type="charter", slug="infrev") else: charter_state = clean['charter_state'] # make sure we have the latest revision set, if we # abandoned a charter before, we could have reset the # revision to latest approved prev_revs = charter.history_set.order_by('-rev')[:1] if prev_revs and prev_revs[0].rev > charter_rev: charter_rev = prev_revs[0].rev if "-" not in charter_rev: charter_rev = charter_rev + "-00" elif option == "abandon": oldstate = group.state if oldstate.slug in ("proposed", "bof", "unknown"): charter_state = State.objects.get(used=True, type="charter", slug="notrev") #TODO : set an abandoned state and leave some comments here group.state = GroupStateName.objects.get(slug='abandon') group.save() e = ChangeStateGroupEvent(group=group, type="changed_state") e.time = group.time e.by = by e.state_id = group.state.slug e.desc = "Group state changed to \"%s\" from \"%s\"" % ( group.state, oldstate) e.save() else: charter_state = State.objects.get(used=True, type="charter", slug="approved") charter_rev = approved_revision(charter.rev) else: charter_state = clean['charter_state'] comment = clean['comment'].rstrip() message = clean['message'] if charter_state != charter.get_state(): events = [] prev_state = charter.get_state() new_state = charter_state charter.set_state(new_state) charter.rev = charter_rev if option != "abandon": e = add_state_change_event(charter, by, prev_state, new_state) if e: events.append(e) else: # kill hanging ballots close_open_ballots(charter, by) # Special log for abandoned efforts e = DocEvent(type="changed_document", doc=charter, rev=charter.rev, by=by) e.desc = "Chartering effort abandoned" e.save() events.append(e) if comment: events.append( DocEvent.objects.create(type="added_comment", doc=charter, rev=charter.rev, by=by, desc=comment)) charter.save_with_history(events) if charter_state.slug == 'intrev': email_charter_internal_review(request, charter) if message or charter_state.slug == "intrev" or charter_state.slug == "extrev": email_admin_re_charter( request, group, "Charter state changed to \"%s\"" % charter_state.name, message, 'charter_state_edit_admin_needed') # 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"): create_ballot_if_not_open(charter, by, "r-wo-ext") else: create_ballot_if_not_open(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") elif charter_state.slug == "approved": change_group_state_after_charter_approval(group, by) fix_charter_revision_after_approval(charter, by) if charter_state.slug == "infrev" and clean[ "initial_time"] and clean["initial_time"] != 0: e = InitialReviewDocEvent(type="initial_review", by=by, doc=charter, rev=charter.rev) e.expires = datetime.datetime.now() + datetime.timedelta( weeks=clean["initial_time"]) e.desc = "Initial review time expires %s" % e.expires.strftime( "%Y-%m-%d") e.save() return redirect('ietf.doc.views_doc.document_main', name=charter.name) else: hide = ['initial_time'] s = charter.get_state() init = dict( charter_state=s.pk if s and option != "recharter" else None) if option == "abandon": hide = ['initial_time', 'charter_state'] if group.type_id == "wg": if option == "recharter": hide = ['initial_time', 'charter_state', 'message'] init = dict() elif option == "initcharter": hide = ['charter_state'] init = dict( initial_time=1, message= '%s has initiated chartering of the proposed %s:\n "%s" (%s).' % (by.plain_name(), group.type.name, group.name, group.acronym)) elif option == "abandon": hide = ['initial_time', 'charter_state'] init = dict( message= '%s has abandoned the chartering effort on the %s:\n "%s" (%s).' % (by.plain_name(), group.type.name, group.name, group.acronym)) form = ChangeStateForm(hide=hide, initial=init, group=group) prev_charter_state = None charter_hists = DocHistory.objects.filter(doc=charter).exclude( states__type="charter", states__slug=charter.get_state_slug()).order_by("-time")[:1] if charter_hists: prev_charter_state = charter_hists[0].get_state() title = { "initcharter": "Initiate chartering of %s %s" % (group.acronym, group.type.name), "recharter": "Recharter %s %s" % (group.acronym, group.type.name), "abandon": "Abandon effort on %s %s" % (group.acronym, group.type.name), }.get(option) if not title: title = "Change chartering state of %s %s" % (group.acronym, group.type.name) def state_pk(slug): return State.objects.get(used=True, type="charter", slug=slug).pk info_msg = {} if group.type_id == "wg": info_msg[state_pk( "infrev" )] = 'The proposed charter for %s "%s" (%s) has been set to Informal IESG review by %s.' % ( group.type.name, group.name, group.acronym, by.plain_name()) info_msg[state_pk( "intrev" )] = 'The proposed charter for %s "%s" (%s) has been set to Internal review by %s.\nPlease place it on the next IESG telechat if it has not already been placed.' % ( group.type.name, group.name, group.acronym, by.plain_name()) info_msg[state_pk( "extrev" )] = 'The proposed charter for %s "%s" (%s) has been set to External review by %s.\nPlease send out the external review announcement to the appropriate lists.\n\nSend the announcement to other SDOs: Yes\nAdditional recipients of the announcement: ' % ( group.type.name, group.name, group.acronym, by.plain_name()) states_for_ballot_wo_extern = State.objects.none() if group.type_id == "wg": states_for_ballot_wo_extern = State.objects.filter( used=True, type="charter", slug="intrev").values_list("pk", flat=True) return render( request, 'doc/charter/change_state.html', dict( form=form, doc=group.charter, option=option, prev_charter_state=prev_charter_state, title=title, initial_review=initial_review, chartering_type=chartering_type, info_msg=json.dumps(info_msg), states_for_ballot_wo_extern=json.dumps( list(states_for_ballot_wo_extern)), ))