Finish charter milestones support so they're merged in after approval

of the charter, also replace references to WGs in wgcharter with a
more generic counterpart so will be easier to add support for RGs if
someone ever gets that far (will still need testing and probably some
minor adjustments though).
 - Legacy-Id: 4534
This commit is contained in:
Ole Laursen 2012-06-27 16:24:04 +00:00
parent 8929413a71
commit 319a202900
12 changed files with 194 additions and 132 deletions

View file

@ -12,7 +12,7 @@ def save_group_in_history(group):
# save RoleHistory
for role in group.role_set.all():
rh = RoleHistory(name=role.name, group=grouphist, email=role.email, person=role.person)
rh = RoleHistory(name=role.name, group=h, email=role.email, person=role.person)
rh.save()
copy_many_to_many_for_history(h, group)

View file

@ -1,8 +1,8 @@
{% load ietf_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: IETF-Announce <ietf-announce@ietf.org>{% if wg.list_email %}
Cc: {{ wg.acronym }} WG <{{ wg.list_email }}> {% endif %}
Subject: WG Action: {{ action_type }} {{ wg.name }} ({{ wg.acronym }})
To: IETF-Announce <ietf-announce@ietf.org>{% if group.list_email %}
Cc: {{ group.acronym }} {{ group.type.name }} <{{ group.list_email }}> {% endif %}
Subject: WG Action: {{ action_type }} {{ group.name }} ({{ group.acronym }})
{% filter wordwrap:73 %}{% ifequal action_type "Formed" %}A new IETF working group has been formed in the {{ wg.parent.name }}.{% endifequal %}{% ifequal action_type "Rechartered" %}The {{ wg.name }} ({{ wg.acronym }}) working group in the {{ wg.parent.name }} of the IETF has been rechartered.{% endifequal %} For additional information please contact the Area Directors or the WG Chair{{ chairs|pluralize}}.
{% filter wordwrap:73 %}{% ifequal action_type "Formed" %}A new IETF working group has been formed in the {{ group.parent.name }}.{% endifequal %}{% ifequal action_type "Rechartered" %}The {{ group.name }} ({{ group.acronym }}) working group in the {{ group.parent.name }} of the IETF has been rechartered.{% endifequal %} For additional information please contact the Area Directors or the {{ group.type.name }} Chair{{ chairs|pluralize}}.
{% include "wgcharter/wg_info.txt" %}{% endfilter %}{% endautoescape %}
{% include "wgcharter/group_info.txt" %}{% endfilter %}{% endautoescape %}

View file

@ -1,6 +1,6 @@
{% load ietf_filters %}{% autoescape off %}
{{ text|fill:70 }}
WG: {{ wg_url }}
{{ group.type.name}}: {{ group_url }}
Charter: {{ charter_url }}
{% endautoescape %}

View file

@ -0,0 +1,28 @@
{{ group.name }} ({{ group.acronym }})
------------------------------------------------
Current Status: {{ group.state.name }} {{ group.type.name }}
{% if chairs %}Chairs:
{% for r in chairs %} {{ r.person.plain_name }} <{{r.email.address}}>
{% endfor %}
{% endif %}{% if secr %}Secretaries:
{% for r in secr %} {{ r.person.plain_name }} <{{r.email.address}}>
{% endfor %}
{% endif %}{% if techadv %}Technical advisors:
{% for r in techadv %} {{ r.person.plain_name }} <{{r.email.address}}>
{% endfor %}
{% endif %}{% if group.ad %}Assigned Area Director:
{{ group.ad.plain_name }} <{{ ad_email }}>
{% endif %}{% if group.list_email %}Mailing list
Address: {{ group.list_email }}
To Subscribe: {{ group.list_subscribe }}
Archive: {{ group.list_archive }}
{% endif %}
Charter:
{{ charter_text }}
Milestones:
{% for milestone in milestones %} {% if milestone.resolved %}{{ milestone.resolved }} {% else %}{{ milestone.due|date:"M Y" }}{% endif %} - {{ milestone.desc|safe }}
{% endfor %}

View file

@ -1,8 +1,8 @@
{% load ietf_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: IETF-Announce <ietf-announce@ietf.org>{% if wg.list_email %}
Cc: {{ wg.acronym }} WG <{{ wg.list_email }}> {% endif %}
Subject: WG Review: {{ wg.name }} ({{ wg.acronym }})
To: IETF-Announce <ietf-announce@ietf.org>{% if group.list_email %}
Cc: {{ group.acronym }} {{ group.type.name }} <{{ group.list_email }}> {% endif %}
Subject: WG Review: {{ group.name }} ({{ group.acronym }})
{% filter wordwrap:73 %}{% ifequal review_type "new" %}A new IETF working group has been proposed in the {{ wg.parent.name }}.{% endifequal %}{% ifequal review_type "recharter" %}The {{ wg.name }} ({{wg.acronym}}) working group in the {{ wg.parent.name }} of the IETF is undergoing rechartering.{% endifequal %} The IESG has not made any determination yet. The following draft charter was submitted, and is provided for informational purposes only. Please send your comments to the IESG mailing list (iesg at ietf.org) by {{ review_date }}.
{% filter wordwrap:73 %}{% ifequal review_type "new" %}A new IETF working group has been proposed in the {{ group.parent.name }}.{% endifequal %}{% ifequal review_type "recharter" %}The {{ group.name }} ({{group.acronym}}) working group in the {{ group.parent.name }} of the IETF is undergoing rechartering.{% endifequal %} The IESG has not made any determination yet. The following draft charter was submitted, and is provided for informational purposes only. Please send your comments to the IESG mailing list (iesg at ietf.org) by {{ review_date }}.
{% include "wgcharter/wg_info.txt" %}{% endfilter %}{% endautoescape %}
{% include "wgcharter/group_info.txt" %}{% endfilter %}{% endautoescape %}

View file

@ -1,13 +0,0 @@
{% comment %}
Copyright The IETF Trust 2011, All Rights Reserved
{% endcomment %}
{% load ietf_filters %}
<tr class="{{ forloop.counter|divisibleby:2|yesno:"oddrow,evenrow" }}">
<td class="acronym">
<a href="{% url wg_view name=wg.acronym %}">{{ wg.acronym|safe }}</a>
</td>
<td class="title">{{ wg.name }}</td>
{% include "wgcharter/date_column.html" %}
{% include "wgcharter/status_columns.html" %}
</tr>

View file

@ -8,13 +8,13 @@ form #id_content {
{% endblock %}
{% block title %}
Charter submission for {{ wg.acronym }}
Charter submission for {{ group.acronym }} {{ group.type.name }}
{% endblock %}
{% block content %}
<h1>Charter submission for {{ wg.acronym }}</h1>
<h1>Charter submission for {{ group.acronym }} {{ group.type.name }}</h1>
<p>The text will be submitted as <strong>charter-ietf-{{ wg.acronym }}-{{ next_rev }}</strong></p>
<p>The text will be submitted as <strong>charter-ietf-{{ group.acronym }}-{{ next_rev }}</strong></p>
<form class="edit-info" action="" enctype="multipart/form-data" method="POST">
<table>
{% for field in form.visible_fields %}
@ -30,7 +30,7 @@ Charter submission for {{ wg.acronym }}
<tr>
<td></td>
<td class="actions">
<a href="{% url doc_view name=wg.charter.name %}">Back</a>
<a href="{% url doc_view name=group.charter.name %}">Back</a>
<input type="submit" value="Submit"/>
</td>
</tr>

View file

@ -1,28 +0,0 @@
{{ wg.name }} ({{ wg.acronym }})
------------------------------------------------
Current Status: {{ wg.state.name }} Working Group
{% if chairs %}Chairs:
{% for r in chairs %} {{ r.person.plain_name }} <{{r.email.address}}>
{% endfor %}
{% endif %}{% if secr %}Secretaries:
{% for r in secr %} {{ r.person.plain_name }} <{{r.email.address}}>
{% endfor %}
{% endif %}{% if techadv %}Technical advisors:
{% for r in techadv %} {{ r.person.plain_name }} <{{r.email.address}}>
{% endfor %}
{% endif %}{% if wg.ad %}Assigned Area Director:
{{ wg.ad.plain_name }} <{{ ad_email }}>
{% endif %}{% if wg.list_email %}Mailing list
Address: {{ wg.list_email }}
To Subscribe: {{ wg.list_subscribe }}
Archive: {{ wg.list_archive }}
{% endif %}
Charter of Working Group:
{{ charter_text }}
Milestones:
{% for milestone in milestones %} {% if milestone.done %}Done {% else %}{{ milestone.expected_due_date|date:"M Y" }}{% endif %} - {{ milestone.desc|safe }}
{% endfor %}

View file

@ -13,7 +13,7 @@ from ietf.doc.models import WriteupDocEvent, DocAlias, BallotPositionDocEvent
from ietf.person.models import Person
from ietf.wgcharter.utils import *
def email_secretariat(request, wg, type, text):
def email_secretariat(request, group, type, text):
to = ["iesg-secretary@ietf.org"]
types = {}
@ -24,16 +24,16 @@ def email_secretariat(request, wg, type, text):
types['state-extrev'] = "State changed to External review"
types['state-iesgrev'] = "State changed to IESG review"
types['state-approved'] = "Charter approved"
types['conclude'] = "Request closing of WG"
types['conclude'] = "Request closing of group"
subject = u"Regarding WG %s: %s" % (wg.acronym, types[type])
subject = u"Regarding %s %s: %s" % (group.type.name, group.acronym, types[type])
text = strip_tags(text)
send_mail(request, to, None, subject,
"wgcharter/email_secretariat.txt",
dict(text=text,
wg_url=settings.IDTRACKER_BASE_URL + urlreverse('wg_charter', kwargs=dict(acronym=wg.acronym)),
charter_url=settings.IDTRACKER_BASE_URL + urlreverse('doc_view', kwargs=dict(name=wg.charter.name)),
group_url=settings.IDTRACKER_BASE_URL + urlreverse('wg_charter', kwargs=dict(acronym=group.acronym)),
charter_url=settings.IDTRACKER_BASE_URL + urlreverse('doc_view', kwargs=dict(name=group.charter.name)),
)
)
@ -62,8 +62,8 @@ def generate_ballot_writeup(request, doc):
return e
def default_action_text(wg, charter, user):
if next_approved_revision(wg.charter.rev) == "01":
def default_action_text(group, charter, user):
if next_approved_revision(group.charter.rev) == "01":
action = "Formed"
else:
action = "Rechartered"
@ -71,38 +71,38 @@ def default_action_text(wg, charter, user):
e = WriteupDocEvent(doc=charter, by=user)
e.by = user
e.type = "changed_action_announcement"
e.desc = "WG action text was changed"
e.desc = "%s action text was changed" % group.type.name
e.text = render_to_string("wgcharter/action_text.txt",
dict(wg=wg,
dict(group=group,
charter_url=settings.IDTRACKER_BASE_URL + charter.get_absolute_url(),
charter_text=read_charter_text(charter),
chairs=wg.role_set.filter(name="chair"),
secr=wg.role_set.filter(name="secr"),
techadv=wg.role_set.filter(name="techadv"),
milestones=wg.groupmilestone_set.all(),
ad_email=wg.ad.role_email("ad") if wg.ad else None,
chairs=group.role_set.filter(name="chair"),
secr=group.role_set.filter(name="secr"),
techadv=group.role_set.filter(name="techadv"),
milestones=group.groupmilestone_set.filter(state="charter"),
ad_email=group.ad.role_email("ad") if group.ad else None,
action_type=action,
))
e.save()
return e
def default_review_text(wg, charter, user):
def default_review_text(group, charter, user):
e = WriteupDocEvent(doc=charter, by=user)
e.by = user
e.type = "changed_review_announcement"
e.desc = "WG review text was changed"
e.desc = "%s review text was changed" % group.type.name
e.text = render_to_string("wgcharter/review_text.txt",
dict(wg=wg,
dict(group=group,
charter_url=settings.IDTRACKER_BASE_URL + charter.get_absolute_url(),
charter_text=read_charter_text(charter),
chairs=wg.role_set.filter(name="chair"),
secr=wg.role_set.filter(name="secr"),
techadv=wg.role_set.filter(name="techadv"),
milestones=wg.groupmilestone_set.all(),
ad_email=wg.ad.role_email("ad") if wg.ad else None,
chairs=group.role_set.filter(name="chair"),
secr=group.role_set.filter(name="secr"),
techadv=group.role_set.filter(name="techadv"),
milestones=group.groupmilestone_set.filter(state="charter"),
ad_email=group.ad.role_email("ad") if group.ad else None,
review_date=(datetime.date.today() + datetime.timedelta(weeks=1)).isoformat(),
review_type="new" if wg.state_id == "proposed" else "recharter",
review_type="new" if group.state_id == "proposed" else "recharter",
)
)
e.save()

View file

@ -174,7 +174,7 @@ class EditCharterTestCase(django.test.TestCase):
self.assertEquals(f.read(),
"Windows line\nMac line\nUnix line\n" + utf_8_snippet)
class CharterApproveBallotTestCase(django.test.TestCase):
class ApproveCharterTestCase(django.test.TestCase):
fixtures = ['names']
def setUp(self):
@ -209,6 +209,28 @@ class CharterApproveBallotTestCase(django.test.TestCase):
charter.set_state(State.objects.get(type="charter", slug="iesgrev"))
due_date = datetime.date.today() + datetime.timedelta(days=180)
m1 = GroupMilestone.objects.create(group=group,
state_id="active",
desc="Has been copied",
due=due_date,
resolved="")
m2 = GroupMilestone.objects.create(group=group,
state_id="active",
desc="To be deleted",
due=due_date,
resolved="")
m3 = GroupMilestone.objects.create(group=group,
state_id="charter",
desc="Has been copied",
due=due_date,
resolved="")
m4 = GroupMilestone.objects.create(group=group,
state_id="charter",
desc="New charter milestone",
due=due_date,
resolved="")
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
@ -232,3 +254,8 @@ class CharterApproveBallotTestCase(django.test.TestCase):
self.assertEquals(len(outbox), mailbox_before + 2)
self.assertTrue("WG Action" in outbox[-1]['Subject'])
self.assertTrue("Charter approved" in outbox[-2]['Subject'])
self.assertEquals(group.groupmilestone_set.filter(state="charter").count(), 0)
self.assertEquals(group.groupmilestone_set.filter(state="active").count(), 2)
self.assertEquals(group.groupmilestone_set.filter(state="active", desc=m1.desc).count(), 1)
self.assertEquals(group.groupmilestone_set.filter(state="active", desc=m4.desc).count(), 1)

View file

@ -22,7 +22,7 @@ from ietf.doc.utils import *
from ietf.name.models import *
from ietf.person.models import *
from ietf.group.models import *
from ietf.group.utils import save_group_in_history
from ietf.group.utils import save_group_in_history, save_milestone_in_history
from ietf.wgcharter.mails import *
from ietf.wgcharter.utils import *
@ -42,10 +42,10 @@ class ChangeStateForm(forms.Form):
@role_required("Area Director", "Secretariat")
def change_state(request, name, option=None):
"""Change state of WG and charter, notifying parties as necessary
and logging the change as a comment."""
"""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)
wg = charter.group
group = charter.group
chartering_type = get_chartering_type(charter)
@ -73,7 +73,7 @@ def change_state(request, name, option=None):
if "-" not in charter_rev:
charter_rev = charter_rev + "-00"
elif option == "abandon":
if wg.state_id == "proposed":
if group.state_id == "proposed":
charter_state = State.objects.get(type="charter", slug="notrev")
else:
charter_state = State.objects.get(type="charter", slug="approved")
@ -112,7 +112,7 @@ def change_state(request, name, option=None):
charter.save()
if message:
email_secretariat(request, wg, "state-%s" % charter_state.slug, message)
email_secretariat(request, group, "state-%s" % charter_state.slug, message)
email_state_changed(request, charter, "State changed to %s." % charter_state)
@ -121,8 +121,8 @@ def change_state(request, name, option=None):
create_ballot_if_not_open(charter, login, "r-wo-ext")
else:
create_ballot_if_not_open(charter, login, "r-extrev")
default_review_text(wg, charter, login)
default_action_text(wg, charter, login)
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")
@ -139,10 +139,10 @@ def change_state(request, name, option=None):
init = dict()
elif option == "initcharter":
hide = ['charter_state']
init = dict(initial_time=1, message='%s has initiated chartering of the proposed WG:\n "%s" (%s).' % (login.plain_name(), wg.name, wg.acronym))
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 WG:\n "%s" (%s).' % (login.plain_name(), wg.name, wg.acronym))
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))
else:
hide = ['initial_time']
s = charter.get_state()
@ -155,27 +155,27 @@ def change_state(request, name, option=None):
prev_charter_state = charter_hists[0].get_state()
title = {
"initcharter": "Initiate chartering of WG %s" % wg.acronym,
"recharter": "Recharter WG %s" % wg.acronym,
"abandon": "Abandon effort on WG %s" % wg.acronym,
"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 state of WG %s" % wg.acronym
title = "Change state of %s %s" % (group.acronym, group.type.name)
def state_pk(slug):
return State.objects.get(type="charter", slug=slug).pk
messages = {
state_pk("infrev"): 'The WG "%s" (%s) has been set to Informal IESG review by %s.' % (wg.name, wg.acronym, login.plain_name()),
state_pk("intrev"): 'The WG "%s" (%s) has been set to Internal review by %s.\nPlease place it on the next IESG telechat and inform the IAB.' % (wg.name, wg.acronym, login.plain_name()),
state_pk("extrev"): 'The WG "%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: ' % (wg.name, wg.acronym, login.plain_name()),
state_pk("infrev"): 'The %s "%s" (%s) has been set to Informal IESG review by %s.' % (group.type.name, group.name, group.acronym, login.plain_name()),
state_pk("intrev"): 'The %s "%s" (%s) has been set to Internal review by %s.\nPlease place it on the next IESG telechat and inform the IAB.' % (group.type.name, group.name, group.acronym, login.plain_name()),
state_pk("extrev"): 'The %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.filter(type="charter", slug="intrev").values_list("pk", flat=True)
return render_to_response('wgcharter/change_state.html',
dict(form=form,
doc=wg.charter,
doc=group.charter,
login=login,
option=option,
prev_charter_state=prev_charter_state,
@ -278,8 +278,8 @@ class UploadForm(forms.Form):
def clean_txt(self):
return get_cleaned_text_file_content(self.cleaned_data["txt"])
def save(self, wg, rev):
filename = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (wg.charter.canonical_name(), rev))
def save(self, group, rev):
filename = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (group.charter.canonical_name(), rev))
with open(filename, 'wb') as destination:
if self.cleaned_data['txt']:
destination.write(self.cleaned_data['txt'])
@ -291,7 +291,7 @@ def submit(request, name=None, acronym=None, option=None):
if acronym and not name:
name = "charter-ietf-" + acronym
charter = get_object_or_404(Document, type="charter", name=name)
wg = charter.group
group = charter.group
login = request.user.get_profile()
@ -313,7 +313,7 @@ def submit(request, name=None, acronym=None, option=None):
if form.is_valid():
save_document_in_history(charter)
# Also save group history so we can search for it
save_group_in_history(wg)
save_group_in_history(group)
charter.rev = next_rev
@ -323,7 +323,7 @@ def submit(request, name=None, acronym=None, option=None):
e.save()
# Save file on disk
form.save(wg, charter.rev)
form.save(group, charter.rev)
charter.time = datetime.datetime.now()
charter.save()
@ -354,7 +354,7 @@ def submit(request, name=None, acronym=None, option=None):
return render_to_response('wgcharter/submit.html',
{'form': form,
'next_rev': next_rev,
'wg': wg },
'group': group },
context_instance=RequestContext(request))
class AnnouncementTextForm(forms.Form):
@ -367,19 +367,20 @@ class AnnouncementTextForm(forms.Form):
def announcement_text(request, name, ann):
"""Editing of announcement text"""
charter = get_object_or_404(Document, type="charter", name=name)
wg = charter.group
group = charter.group
login = request.user.get_profile()
if ann == "action":
existing = charter.latest_event(WriteupDocEvent, type="changed_action_announcement")
elif ann == "review":
existing = charter.latest_event(WriteupDocEvent, type="changed_review_announcement")
if ann in ("action", "review"):
existing = charter.latest_event(WriteupDocEvent, type="changed_%s_announcement" % ann)
if not existing:
if ann == "action":
existing = default_action_text(wg, charter, login)
existing = default_action_text(group, charter, login)
elif ann == "review":
existing = default_review_text(wg, charter, login)
existing = default_review_text(group, charter, login)
if not existing:
raise Http404
form = AnnouncementTextForm(initial=dict(announcement_text=existing.text))
@ -391,7 +392,7 @@ def announcement_text(request, name, ann):
e = WriteupDocEvent(doc=charter, by=login)
e.by = login
e.type = "changed_%s_announcement" % ann
e.desc = "WG %s text was changed" % ann
e.desc = "%s %s text was changed" % (group.type.name, ann)
e.text = t
e.save()
@ -405,9 +406,9 @@ def announcement_text(request, name, ann):
if "regenerate_text" in request.POST:
if ann == "action":
e = default_action_text(wg, charter, login)
e = default_action_text(group, charter, login)
elif ann == "review":
e = default_review_text(wg, charter, login)
e = default_review_text(group, charter, login)
# make sure form has the updated text
form = AnnouncementTextForm(initial=dict(announcement_text=e.text))
@ -439,7 +440,6 @@ class BallotWriteupForm(forms.Form):
def ballot_writeupnotes(request, name):
"""Editing of ballot write-up and notes"""
charter = get_object_or_404(Document, type="charter", name=name)
wg = charter.group
ballot = charter.latest_event(BallotDocEvent, type="created_ballot")
if not ballot:
@ -507,13 +507,13 @@ def ballot_writeupnotes(request, name):
def approve(request, name):
"""Approve charter, changing state, fixing revision, copying file to final location."""
charter = get_object_or_404(Document, type="charter", name=name)
wg = charter.group
group = charter.group
login = request.user.get_profile()
e = charter.latest_event(WriteupDocEvent, type="changed_action_announcement")
if not e:
announcement = default_action_text(wg, charter, login).text
announcement = default_action_text(group, charter, login).text
else:
announcement = e.text
@ -535,13 +535,13 @@ def approve(request, name):
change_description = e.desc
new_state = GroupStateName.objects.get(slug="active")
if wg.state != new_state:
save_group_in_history(wg)
prev_state = wg.state
wg.state = new_state
wg.time = e.time
wg.save()
change_description += " and WG state has been changed to %s" % new_state.name
if group.state != new_state:
save_group_in_history(group)
prev_state = group.state
group.state = new_state
group.time = e.time
group.save()
change_description += " and %s state has been changed to %s" % (group.type.name, new_state.name)
e = log_state_changed(request, charter, login, prev_charter_state)
@ -551,7 +551,9 @@ def approve(request, name):
new = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev)))
shutil.copy(old, new)
except IOError:
raise Http404("Charter text %s" % filename)
return HttpResponse("There was an error copying %s to %s" %
('%s-%s.txt' % (charter.canonical_name(), charter.rev),
'%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev))))
e = NewRevisionDocEvent(doc=charter, by=login, type="new_revision")
e.rev = next_approved_revision(charter.rev)
@ -562,7 +564,57 @@ def approve(request, name):
charter.time = e.time
charter.save()
email_secretariat(request, wg, "state-%s" % new_charter_state.slug, change_description)
email_secretariat(request, group, "state-%s" % new_charter_state.slug, change_description)
# move milestones over
milestones_to_delete = list(group.groupmilestone_set.filter(state__in=("active", "review")))
for m in group.groupmilestone_set.filter(state="charter"):
# see if we got this milestone already (i.e. it was copied
# verbatim to the charter)
found = False
for i, o in enumerate(milestones_to_delete):
if o.desc == m.desc and o.due == m.due and set(o.docs.all()) == set(m.docs.all()):
found = True
break
if found:
# keep existing, whack charter milestone
if not o.state_id == "active":
save_milestone_in_history(o)
o.state_id = "active"
o.save()
MilestoneGroupEvent.objects.create(
group=group, type="changed_milestone", by=login,
desc="Changed milestone \"%s\", changed state from review to active" % o.desc,
milestone=o)
del milestones_to_delete[i]
# don't generate a DocEvent for this, it's implicit in the approval event
save_milestone_in_history(m)
m.state_id = "deleted"
m.save()
else:
# move charter milestone
save_milestone_in_history(m)
m.state_id = "active"
m.save()
MilestoneGroupEvent.objects.create(
group=group, type="changed_milestone", by=login,
desc="Added milestone \"%s\", due %s, from approved charter" % (m.desc, m.due),
milestone=m)
for m in milestones_to_delete:
save_milestone_in_history(m)
m.state_id = "deleted"
m.save()
MilestoneGroupEvent.objects.create(
group=group, type="changed_milestone", by=login,
desc="Deleted milestone \"%s\", not present in approved charter" % m.desc,
milestone=m)
# send announcement
send_mail_preformatted(request, announcement)
@ -571,7 +623,6 @@ def approve(request, name):
return render_to_response('wgcharter/approve.html',
dict(charter=charter,
announcement=announcement,
wg=wg),
announcement=announcement),
context_instance=RequestContext(request))

View file

@ -157,7 +157,6 @@ def edit_milestones(request, acronym, milestone_set="current"):
if c["delete"]:
save_milestone_in_history(m)
m.time = datetime.datetime.now()
m.state_id = "deleted"
m.save()
@ -298,7 +297,6 @@ def reset_charter_milestones(request, acronym):
for m in charter_milestones:
save_milestone_in_history(m)
m.time = datetime.datetime.now()
m.state_id = "deleted"
m.save()
@ -315,7 +313,6 @@ def reset_charter_milestones(request, acronym):
desc=m.desc,
due=m.due,
resolved=m.resolved,
time=datetime.datetime.now(),
)
m.docs = m.docs.all()