Merged [7076] from rjsparks@nostrum.com:

Sets the State(type=draft) to Replaced when a document is replaced using views_draft.replaces.
Sets the state back to Active or Expired when a document is no longer replaced by another document.
Adds tests for the above functionality.
Provides a patch to repair the state of documents pointed to by RelatedDocument(relationship__slug='replaces') objects created by views_draft.replaces before this fix.
Fixes bug 1234
 - Legacy-Id: 7222
Note: SVN reference [7076] has been migrated to Git commit a3da5bbd87
This commit is contained in:
Henrik Levkowetz 2014-02-09 20:33:15 +00:00
commit 3abaab1d98
3 changed files with 132 additions and 4 deletions

View file

@ -1098,3 +1098,102 @@ class ChangeStreamStateTests(TestCase):
self.assertTrue("marschairman@ietf.org" in unicode(outbox[-1]))
self.assertTrue("marsdelegate@ietf.org" in unicode(outbox[-1]))
class ChangeReplacesTests(TestCase):
def setUp(self):
make_test_data()
mars_wg = Group.objects.get(acronym='mars')
self.basea = Document.objects.create(
name="draft-test-base-a",
time=datetime.datetime.now(),
type_id="draft",
title="Base A",
stream_id="ietf",
expires=datetime.datetime.now() + datetime.timedelta(days=settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
group=mars_wg,
)
self.baseb = Document.objects.create(
name="draft-test-base-b",
time=datetime.datetime.now()-datetime.timedelta(days=365),
type_id="draft",
title="Base B",
stream_id="ietf",
expires=datetime.datetime.now() - datetime.timedelta(days = 365 - settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
group=mars_wg,
)
self.replacea = Document.objects.create(
name="draft-test-replace-a",
time=datetime.datetime.now(),
type_id="draft",
title="Replace Base A",
stream_id="ietf",
expires=datetime.datetime.now() + datetime.timedelta(days = settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
group=mars_wg,
)
self.replaceboth = Document.objects.create(
name="draft-test-replace-both",
time=datetime.datetime.now(),
type_id="draft",
title="Replace Base A and Base B",
stream_id="ietf",
expires=datetime.datetime.now() + datetime.timedelta(days = settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
group=mars_wg,
)
self.basea.set_state(State.objects.get(used=True, type="draft", slug="active"))
self.baseb.set_state(State.objects.get(used=True, type="draft", slug="expired"))
self.replacea.set_state(State.objects.get(used=True, type="draft", slug="active"))
self.replaceboth.set_state(State.objects.get(used=True, type="draft", slug="active"))
DocAlias.objects.create(document=self.basea,name=self.basea.name)
DocAlias.objects.create(document=self.baseb,name=self.baseb.name)
DocAlias.objects.create(document=self.replacea,name=self.replacea.name)
DocAlias.objects.create(document=self.replaceboth,name=self.replaceboth.name)
def test_change_replaces(self):
url = urlreverse('doc_change_replaces', kwargs=dict(name=self.replacea.name))
login_testing_unauthorized(self, "secretary", url)
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form[class=change-replaces]')), 1)
# Post that says replacea replaces base a
self.assertEquals(self.basea.get_state().slug,'active')
repljson='{"%d":"%s"}'%(DocAlias.objects.get(name=self.basea.name).id,self.basea.name)
r = self.client.post(url, dict(replaces=repljson))
self.assertEquals(r.status_code, 302)
self.assertEqual(RelatedDocument.objects.filter(relationship__slug='replaces',source=self.replacea).count(),1)
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'repl')
# Post that says replaceboth replaces both base a and base b
url = urlreverse('doc_change_replaces', kwargs=dict(name=self.replaceboth.name))
self.assertEquals(self.baseb.get_state().slug,'expired')
repljson='{"%d":"%s","%d":"%s"}'%(DocAlias.objects.get(name=self.basea.name).id,self.basea.name,
DocAlias.objects.get(name=self.baseb.name).id,self.baseb.name)
r = self.client.post(url, dict(replaces=repljson))
self.assertEquals(r.status_code, 302)
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'repl')
self.assertEquals(Document.objects.get(name='draft-test-base-b').get_state().slug,'repl')
# Post that undoes replaceboth
repljson='{}'
r = self.client.post(url, dict(replaces=repljson))
self.assertEquals(r.status_code, 302)
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'repl') # Because A is still also replaced by replacea
self.assertEquals(Document.objects.get(name='draft-test-base-b').get_state().slug,'expired')
# Post that undoes replacea
url = urlreverse('doc_change_replaces', kwargs=dict(name=self.replacea.name))
r = self.client.post(url, dict(replaces=repljson))
self.assertEquals(r.status_code, 302)
self.assertEquals(Document.objects.get(name='draft-test-base-a').get_state().slug,'active')

View file

@ -354,13 +354,14 @@ def replaces(request, name):
for d in old_replaces:
if d not in new_replaces:
emails = collect_email_addresses(emails, d.document)
RelatedDocument.objects.filter(source=doc, target=d,
relationship=relationship).delete()
RelatedDocument.objects.filter(source=doc, target=d, relationship=relationship).delete()
if not RelatedDocument.objects.filter(target=d, relationship=relationship):
d.document.set_state(State.objects.get(type='draft',slug='active' if d.document.expires>datetime.datetime.now() else 'expired'))
for d in new_replaces:
if d not in old_replaces:
emails = collect_email_addresses(emails, d.document)
RelatedDocument.objects.create(source=doc, target=d,
relationship=relationship)
RelatedDocument.objects.create(source=doc, target=d, relationship=relationship)
d.document.set_state(State.objects.get(type='draft',slug='repl'))
e = DocEvent(doc=doc,by=login,type='changed_document')
new_replaces_names = ", ".join([d.name for d in new_replaces])
if not new_replaces_names:

View file

@ -0,0 +1,28 @@
#!/usr/bin/env python
from ietf import settings
from django.core import management
management.setup_environ(settings)
from ietf.doc.models import RelatedDocument,State,DocEvent
from ietf.person.models import Person
relevant_relations = RelatedDocument.objects.filter(relationship__slug='replaces',
target__document__type__slug='draft',
target__document__states__type='draft',
target__document__states__slug__in=['active','expired'])
affected_docs = set([x.target.document for x in relevant_relations])
replaced_state = State.objects.get(type='draft',slug='repl')
system_user = Person.objects.get(name="(System)")
for d in affected_docs:
d.set_state(replaced_state)
DocEvent.objects.create(type="added_comment",
doc=d,
by=system_user,
desc='Draft state administratively corrected to Replaced',
)