Slight refactor of the review models to capture review team settings. Allows configuring review teams to get automatic suggestions for reviews or not. Provides a better admin for creating/managing review teams. Fixes #2048 and #2072. Commit ready for merge.

- Legacy-Id: 12520
This commit is contained in:
Robert Sparks 2016-12-14 23:26:32 +00:00
parent 57fa52e186
commit b24bdb5bc3
10 changed files with 141 additions and 37 deletions

View file

@ -12,7 +12,7 @@ from pyquery import PyQuery
import debug # pyflakes:ignore import debug # pyflakes:ignore
from ietf.review.models import (ReviewRequest, ResultUsedInReviewTeam, ReviewerSettings, from ietf.review.models import (ReviewRequest, ReviewerSettings,
ReviewWish, UnavailablePeriod, NextReviewerInTeam) ReviewWish, UnavailablePeriod, NextReviewerInTeam)
from ietf.review.utils import reviewer_rotation_list, possibly_advance_next_reviewer_for_team from ietf.review.utils import reviewer_rotation_list, possibly_advance_next_reviewer_for_team
import ietf.review.mailarch import ietf.review.mailarch
@ -479,8 +479,7 @@ class ReviewTests(TestCase):
review_req.state = ReviewRequestStateName.objects.get(slug="accepted") review_req.state = ReviewRequestStateName.objects.get(slug="accepted")
review_req.save() review_req.save()
for r in ReviewResultName.objects.filter(slug__in=("issues", "ready")): for r in ReviewResultName.objects.filter(slug__in=("issues", "ready")):
ResultUsedInReviewTeam.objects.get_or_create(team=review_req.team, result=r) review_req.team.reviewteamsettings.review_results.add(r)
review_req.team.save()
url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": doc.name, "request_id": review_req.pk }) url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": doc.name, "request_id": review_req.pk })
@ -517,7 +516,7 @@ class ReviewTests(TestCase):
test_file.name = "unnamed" test_file.name = "unnamed"
r = self.client.post(url, data={ r = self.client.post(url, data={
"result": ReviewResultName.objects.get(resultusedinreviewteam__team=review_req.team, slug="ready").pk, "result": ReviewResultName.objects.get(reviewteamsettings__group=review_req.team, slug="ready").pk,
"state": ReviewRequestStateName.objects.get(slug="completed").pk, "state": ReviewRequestStateName.objects.get(slug="completed").pk,
"reviewed_rev": review_req.doc.rev, "reviewed_rev": review_req.doc.rev,
"review_submission": "upload", "review_submission": "upload",
@ -560,7 +559,7 @@ class ReviewTests(TestCase):
empty_outbox() empty_outbox()
r = self.client.post(url, data={ r = self.client.post(url, data={
"result": ReviewResultName.objects.get(resultusedinreviewteam__team=review_req.team, slug="ready").pk, "result": ReviewResultName.objects.get(reviewteamsettings__group=review_req.team, slug="ready").pk,
"state": ReviewRequestStateName.objects.get(slug="completed").pk, "state": ReviewRequestStateName.objects.get(slug="completed").pk,
"reviewed_rev": review_req.doc.rev, "reviewed_rev": review_req.doc.rev,
"review_submission": "enter", "review_submission": "enter",
@ -590,7 +589,7 @@ class ReviewTests(TestCase):
empty_outbox() empty_outbox()
r = self.client.post(url, data={ r = self.client.post(url, data={
"result": ReviewResultName.objects.get(resultusedinreviewteam__team=review_req.team, slug="ready").pk, "result": ReviewResultName.objects.get(reviewteamsettings__group=review_req.team, slug="ready").pk,
"state": ReviewRequestStateName.objects.get(slug="completed").pk, "state": ReviewRequestStateName.objects.get(slug="completed").pk,
"reviewed_rev": review_req.doc.rev, "reviewed_rev": review_req.doc.rev,
"review_submission": "link", "review_submission": "link",
@ -618,7 +617,7 @@ class ReviewTests(TestCase):
empty_outbox() empty_outbox()
r = self.client.post(url, data={ r = self.client.post(url, data={
"result": ReviewResultName.objects.get(resultusedinreviewteam__team=review_req.team, slug="ready").pk, "result": ReviewResultName.objects.get(reviewteamsettings__group=review_req.team, slug="ready").pk,
"state": ReviewRequestStateName.objects.get(slug="part-completed").pk, "state": ReviewRequestStateName.objects.get(slug="part-completed").pk,
"reviewed_rev": review_req.doc.rev, "reviewed_rev": review_req.doc.rev,
"review_submission": "enter", "review_submission": "enter",
@ -652,7 +651,7 @@ class ReviewTests(TestCase):
url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": review_req.doc.name, "request_id": review_req.pk }) url = urlreverse('ietf.doc.views_review.complete_review', kwargs={ "name": review_req.doc.name, "request_id": review_req.pk })
r = self.client.post(url, data={ r = self.client.post(url, data={
"result": ReviewResultName.objects.get(resultusedinreviewteam__team=review_req.team, slug="ready").pk, "result": ReviewResultName.objects.get(reviewteamsettings__group=review_req.team, slug="ready").pk,
"state": ReviewRequestStateName.objects.get(slug="completed").pk, "state": ReviewRequestStateName.objects.get(slug="completed").pk,
"reviewed_rev": review_req.doc.rev, "reviewed_rev": review_req.doc.rev,
"review_submission": "enter", "review_submission": "enter",
@ -677,7 +676,7 @@ class ReviewTests(TestCase):
empty_outbox() empty_outbox()
r = self.client.post(url, data={ r = self.client.post(url, data={
"result": ReviewResultName.objects.get(resultusedinreviewteam__team=review_req.team, slug="ready").pk, "result": ReviewResultName.objects.get(reviewteamsettings__group=review_req.team, slug="ready").pk,
"state": ReviewRequestStateName.objects.get(slug="completed").pk, "state": ReviewRequestStateName.objects.get(slug="completed").pk,
"reviewed_rev": review_req.doc.rev, "reviewed_rev": review_req.doc.rev,
"review_submission": "enter", "review_submission": "enter",
@ -702,7 +701,7 @@ class ReviewTests(TestCase):
# revise again # revise again
empty_outbox() empty_outbox()
r = self.client.post(url, data={ r = self.client.post(url, data={
"result": ReviewResultName.objects.get(resultusedinreviewteam__team=review_req.team, slug="ready").pk, "result": ReviewResultName.objects.get(reviewteamsettings__group=review_req.team, slug="ready").pk,
"state": ReviewRequestStateName.objects.get(slug="part-completed").pk, "state": ReviewRequestStateName.objects.get(slug="part-completed").pk,
"reviewed_rev": review_req.doc.rev, "reviewed_rev": review_req.doc.rev,
"review_submission": "enter", "review_submission": "enter",

View file

@ -14,7 +14,7 @@ from django.core.urlresolvers import reverse as urlreverse
from ietf.doc.models import (Document, NewRevisionDocEvent, State, DocAlias, from ietf.doc.models import (Document, NewRevisionDocEvent, State, DocAlias,
LastCallDocEvent, ReviewRequestDocEvent) LastCallDocEvent, ReviewRequestDocEvent)
from ietf.name.models import ReviewRequestStateName, ReviewResultName, DocTypeName from ietf.name.models import ReviewRequestStateName, ReviewResultName, DocTypeName
from ietf.review.models import ReviewRequest, TypeUsedInReviewTeam from ietf.review.models import ReviewRequest
from ietf.group.models import Group from ietf.group.models import Group
from ietf.person.fields import PersonEmailChoiceField, SearchablePersonField from ietf.person.fields import PersonEmailChoiceField, SearchablePersonField
from ietf.ietfauth.utils import is_authorized_in_doc_stream, user_is_person, has_role from ietf.ietfauth.utils import is_authorized_in_doc_stream, user_is_person, has_role
@ -57,7 +57,7 @@ class RequestReviewForm(forms.ModelForm):
f.queryset = active_review_teams() f.queryset = active_review_teams()
f.initial = [group.pk for group in f.queryset if can_manage_review_requests_for_team(user, group, allow_personnel_outside_team=False)] f.initial = [group.pk for group in f.queryset if can_manage_review_requests_for_team(user, group, allow_personnel_outside_team=False)]
self.fields['type'].queryset = self.fields['type'].queryset.filter(used=True, typeusedinreviewteam__team__in=self.fields["team"].queryset).distinct() self.fields['type'].queryset = self.fields['type'].queryset.filter(used=True, reviewteamsettings__group__in=self.fields["team"].queryset).distinct()
self.fields['type'].widget = forms.RadioSelect(choices=[t for t in self.fields['type'].choices if t[0]]) self.fields['type'].widget = forms.RadioSelect(choices=[t for t in self.fields['type'].choices if t[0]])
self.fields["requested_rev"].label = "Document revision" self.fields["requested_rev"].label = "Document revision"
@ -83,7 +83,7 @@ class RequestReviewForm(forms.ModelForm):
if chosen_type and chosen_teams: if chosen_type and chosen_teams:
for t in chosen_teams: for t in chosen_teams:
if not TypeUsedInReviewTeam.objects.filter(type=chosen_type, team=t).exists(): if chosen_type not in t.reviewteamsettings.review_types.all():
self.add_error("type", "{} does not use the review type {}.".format(t.name, chosen_type.name)) self.add_error("type", "{} does not use the review type {}.".format(t.name, chosen_type.name))
return self.cleaned_data return self.cleaned_data
@ -361,7 +361,7 @@ class CompleteReviewForm(forms.Form):
" ".join("<a class=\"rev label label-default\">{}</a>".format(r) " ".join("<a class=\"rev label label-default\">{}</a>".format(r)
for r in known_revisions)) for r in known_revisions))
self.fields["result"].queryset = self.fields["result"].queryset.filter(resultusedinreviewteam__team=review_req.team) self.fields["result"].queryset = self.fields["result"].queryset.filter(reviewteamsettings__group=review_req.team)
def format_submission_choice(label): def format_submission_choice(label):
if revising_review: if revising_review:

View file

@ -2,7 +2,7 @@ from django.contrib import admin
from ietf.review.models import (ReviewerSettings, UnavailablePeriod, ReviewWish, from ietf.review.models import (ReviewerSettings, UnavailablePeriod, ReviewWish,
ResultUsedInReviewTeam, TypeUsedInReviewTeam, NextReviewerInTeam, ResultUsedInReviewTeam, TypeUsedInReviewTeam, NextReviewerInTeam,
ReviewRequest) ReviewRequest, ReviewTeamSettings )
class ReviewerSettingsAdmin(admin.ModelAdmin): class ReviewerSettingsAdmin(admin.ModelAdmin):
def acronym(self, obj): def acronym(self, obj):
@ -72,3 +72,11 @@ class ReviewRequestAdmin(admin.ModelAdmin):
search_fields = ["doc__name", "reviewer__person__name"] search_fields = ["doc__name", "reviewer__person__name"]
admin.site.register(ReviewRequest, ReviewRequestAdmin) admin.site.register(ReviewRequest, ReviewRequestAdmin)
class ReviewTeamSettingsAdmin(admin.ModelAdmin):
list_display = ["group", ]
search_fields = ["group__acronym", ]
raw_id_fields = ["group", ]
filter_horizontal = ["review_types", "review_results", ]
admin.site.register(ReviewTeamSettings, ReviewTeamSettingsAdmin)

View file

@ -16,8 +16,8 @@ django.setup()
import datetime, re, itertools import datetime, re, itertools
from collections import namedtuple from collections import namedtuple
from django.db import connections from django.db import connections
from ietf.review.models import (ReviewRequest, ReviewerSettings, ReviewResultName, ResultUsedInReviewTeam, from ietf.review.models import (ReviewRequest, ReviewerSettings, ReviewResultName,
ReviewRequestStateName, ReviewTypeName, TypeUsedInReviewTeam, ReviewRequestStateName, ReviewTypeName,
UnavailablePeriod, NextReviewerInTeam) UnavailablePeriod, NextReviewerInTeam)
from ietf.group.models import Group, Role, RoleName from ietf.group.models import Group, Role, RoleName
from ietf.person.models import Person, Email, Alias from ietf.person.models import Person, Email, Alias
@ -190,10 +190,10 @@ with db_con.cursor() as c:
summaries = [v.strip().lower() for v in row.value.split(";") if v.strip()] summaries = [v.strip().lower() for v in row.value.split(";") if v.strip()]
for s in summaries: for s in summaries:
ResultUsedInReviewTeam.objects.get_or_create(team=team, result=results[s]) team.reviewteamsettings.review_results.add(results[s])
for t in ReviewTypeName.objects.filter(slug__in=["early", "lc", "telechat"]): for t in ReviewTypeName.objects.filter(slug__in=["early", "lc", "telechat"]):
TypeUsedInReviewTeam.objects.get_or_create(team=team, type=t) team.reviewteamsettings.review_types.add(t)
# review requests # review requests

View file

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import ietf.review.models
class Migration(migrations.Migration):
dependencies = [
('name', '0016_auto_20161013_1010'),
('group', '0009_auto_20150930_0758'),
('review', '0006_auto_20161209_0436'),
]
operations = [
migrations.CreateModel(
name='ReviewTeamSettings',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('autosuggest', models.BooleanField(default=True, verbose_name=b'Automatically suggest possible review requests')),
('group', models.OneToOneField(to='group.Group')),
('review_results', models.ManyToManyField(default=ietf.review.models.get_default_review_results, to='name.ReviewResultName')),
('review_types', models.ManyToManyField(default=ietf.review.models.get_default_review_types, to='name.ReviewTypeName')),
],
options={
'verbose_name': 'Review team settings',
'verbose_name_plural': 'Review team settings',
},
),
]

View file

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def forward(apps, schema_editor):
ReviewTeamSettings = apps.get_model('review','ReviewTeamSettings')
ResultUsedInReviewTeam = apps.get_model('review','ResultUsedInReviewTeam')
TypeUsedInReviewTeam = apps.get_model('review','TypeUsedInReviewTeam')
for group_id in ResultUsedInReviewTeam.objects.values_list('team',flat=True).distinct():
rts = ReviewTeamSettings.objects.create(group_id=group_id)
rts.review_types = TypeUsedInReviewTeam.objects.filter(team_id=group_id).values_list('type',flat=True).distinct()
rts.review_results = ResultUsedInReviewTeam.objects.filter(team_id=group_id).values_list('result',flat=True).distinct()
def reverse(apps, schema_editor):
ReviewTeamSettings = apps.get_model('review','ReviewTeamSettings')
ReviewTeamSettings.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
('review', '0007_reviewteamsettings'),
]
operations = [
migrations.RunPython(forward, reverse)
]

View file

@ -10,7 +10,7 @@ from ietf.utils.validators import validate_regular_expression_string
class ReviewerSettings(models.Model): class ReviewerSettings(models.Model):
"""Keeps track of admin data associated with a reviewer in a team.""" """Keeps track of admin data associated with a reviewer in a team."""
team = models.ForeignKey(Group, limit_choices_to=~models.Q(resultusedinreviewteam=None)) team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamsettings=None))
person = models.ForeignKey(Person) person = models.ForeignKey(Person)
INTERVALS = [ INTERVALS = [
(7, "Once per week"), (7, "Once per week"),
@ -34,7 +34,7 @@ class ReviewerSettings(models.Model):
class ReviewSecretarySettings(models.Model): class ReviewSecretarySettings(models.Model):
"""Keeps track of admin data associated with a secretary in a team.""" """Keeps track of admin data associated with a secretary in a team."""
team = models.ForeignKey(Group, limit_choices_to=~models.Q(resultusedinreviewteam=None)) team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamsettings=None))
person = models.ForeignKey(Person) person = models.ForeignKey(Person)
remind_days_before_deadline = models.IntegerField(null=True, blank=True, help_text="To get an email reminder in case a reviewer forgets to do an assigned review, enter the number of days before review deadline you want to receive it. Clear the field if you don't want a reminder.") remind_days_before_deadline = models.IntegerField(null=True, blank=True, help_text="To get an email reminder in case a reviewer forgets to do an assigned review, enter the number of days before review deadline you want to receive it. Clear the field if you don't want a reminder.")
@ -45,7 +45,7 @@ class ReviewSecretarySettings(models.Model):
verbose_name_plural = "review secretary settings" verbose_name_plural = "review secretary settings"
class UnavailablePeriod(models.Model): class UnavailablePeriod(models.Model):
team = models.ForeignKey(Group, limit_choices_to=~models.Q(resultusedinreviewteam=None)) team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamsettings=None))
person = models.ForeignKey(Person) person = models.ForeignKey(Person)
start_date = models.DateField(default=datetime.date.today, null=True, help_text="Choose the start date so that you can still do a review if it's assigned just before the start date - this usually means you should mark yourself unavailable for assignment some time before you are actually away.") start_date = models.DateField(default=datetime.date.today, null=True, help_text="Choose the start date so that you can still do a review if it's assigned just before the start date - this usually means you should mark yourself unavailable for assignment some time before you are actually away.")
end_date = models.DateField(blank=True, null=True, help_text="Leaving the end date blank means that the period continues indefinitely. You can end it later.") end_date = models.DateField(blank=True, null=True, help_text="Leaving the end date blank means that the period continues indefinitely. You can end it later.")
@ -76,7 +76,7 @@ class UnavailablePeriod(models.Model):
class ReviewWish(models.Model): class ReviewWish(models.Model):
"""Reviewer wishes to review a document when it becomes available for review.""" """Reviewer wishes to review a document when it becomes available for review."""
time = models.DateTimeField(default=datetime.datetime.now) time = models.DateTimeField(default=datetime.datetime.now)
team = models.ForeignKey(Group, limit_choices_to=~models.Q(resultusedinreviewteam=None)) team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamsettings=None))
person = models.ForeignKey(Person) person = models.ForeignKey(Person)
doc = models.ForeignKey(Document) doc = models.ForeignKey(Document)
@ -104,7 +104,7 @@ class ResultUsedInReviewTeam(models.Model):
class TypeUsedInReviewTeam(models.Model): class TypeUsedInReviewTeam(models.Model):
"""Captures that a type name is valid for a given team for new """Captures that a type name is valid for a given team for new
reviews. """ reviews. """
team = models.ForeignKey(Group, limit_choices_to=~models.Q(resultusedinreviewteam=None)) team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamsettings=None))
type = models.ForeignKey(ReviewTypeName) type = models.ForeignKey(ReviewTypeName)
def __unicode__(self): def __unicode__(self):
@ -115,7 +115,7 @@ class TypeUsedInReviewTeam(models.Model):
verbose_name_plural = "review type used in team settings" verbose_name_plural = "review type used in team settings"
class NextReviewerInTeam(models.Model): class NextReviewerInTeam(models.Model):
team = models.ForeignKey(Group, limit_choices_to=~models.Q(resultusedinreviewteam=None)) team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamsettings=None))
next_reviewer = models.ForeignKey(Person) next_reviewer = models.ForeignKey(Person)
def __unicode__(self): def __unicode__(self):
@ -138,7 +138,7 @@ class ReviewRequest(models.Model):
time = models.DateTimeField(default=datetime.datetime.now) time = models.DateTimeField(default=datetime.datetime.now)
type = models.ForeignKey(ReviewTypeName) type = models.ForeignKey(ReviewTypeName)
doc = models.ForeignKey(Document, related_name='reviewrequest_set') doc = models.ForeignKey(Document, related_name='reviewrequest_set')
team = models.ForeignKey(Group, limit_choices_to=~models.Q(resultusedinreviewteam=None)) team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamsettings=None))
deadline = models.DateField() deadline = models.DateField()
requested_by = models.ForeignKey(Person) requested_by = models.ForeignKey(Person)
requested_rev = models.CharField(verbose_name="requested revision", max_length=16, blank=True, help_text="Fill in if a specific revision is to be reviewed, e.g. 02") requested_rev = models.CharField(verbose_name="requested revision", max_length=16, blank=True, help_text="Fill in if a specific revision is to be reviewed, e.g. 02")
@ -156,3 +156,23 @@ class ReviewRequest(models.Model):
def __unicode__(self): def __unicode__(self):
return u"%s review on %s by %s %s" % (self.type, self.doc, self.team, self.state) return u"%s review on %s by %s %s" % (self.type, self.doc, self.team, self.state)
def get_default_review_types():
return ReviewTypeName.objects.filter(slug__in=['early','lc','telechat'])
def get_default_review_results():
return ReviewResultName.objects.filter(slug__in=['not-ready', 'right-track', 'almost-ready', 'ready-issues', 'ready-nits', 'ready'])
class ReviewTeamSettings(models.Model):
"""Holds configuration specific to groups that are review teams"""
group = models.OneToOneField(Group)
autosuggest = models.BooleanField(default=True, verbose_name="Automatically suggest possible review requests")
review_types = models.ManyToManyField(ReviewTypeName, default=get_default_review_types)
review_results = models.ManyToManyField(ReviewResultName, default=get_default_review_results)
def __unicode__(self):
return u"%s" % (self.group.acronym,)
class Meta:
verbose_name = "Review team settings"
verbose_name_plural = "Review team settings"

View file

@ -10,7 +10,7 @@ from ietf.api import ToOneField # pyflakes:ignore
from ietf.review.models import (ReviewerSettings, ReviewRequest, from ietf.review.models import (ReviewerSettings, ReviewRequest,
ResultUsedInReviewTeam, TypeUsedInReviewTeam, ResultUsedInReviewTeam, TypeUsedInReviewTeam,
UnavailablePeriod, ReviewWish, NextReviewerInTeam, UnavailablePeriod, ReviewWish, NextReviewerInTeam,
ReviewSecretarySettings) ReviewSecretarySettings, ReviewTeamSettings )
from ietf.person.resources import PersonResource from ietf.person.resources import PersonResource
@ -185,3 +185,18 @@ class ReviewSecretarySettingsResource(ModelResource):
} }
api.review.register(ReviewSecretarySettingsResource()) api.review.register(ReviewSecretarySettingsResource())
class ReviewTeamSettingsResource(ModelResource):
group = ToOneField(GroupResource, 'group')
review_types = ToManyField(ReviewTypeNameResource, 'review_types')
review_results = ToManyField(ReviewResultNameResource, 'review_results')
class Meta:
queryset = ReviewTeamSettings.objects.all()
serializer = api.Serializer()
cache = SimpleCache()
filtering = {
"id": ALL,
"autosuggest": ALL,
"review_types": ALL_WITH_RELATIONS,
"review_results": ALL_WITH_RELATIONS,
}
api.review.register(ReviewTeamSettingsResource())

View file

@ -14,15 +14,14 @@ from ietf.doc.models import (Document, ReviewRequestDocEvent, State,
from ietf.iesg.models import TelechatDate from ietf.iesg.models import TelechatDate
from ietf.person.models import Person from ietf.person.models import Person
from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream
from ietf.review.models import (ReviewRequest, ReviewRequestStateName, ReviewTypeName, TypeUsedInReviewTeam, from ietf.review.models import (ReviewRequest, ReviewRequestStateName, ReviewTypeName,
ReviewerSettings, UnavailablePeriod, ReviewWish, NextReviewerInTeam, ReviewerSettings, UnavailablePeriod, ReviewWish, NextReviewerInTeam,
ReviewSecretarySettings) ReviewSecretarySettings)
from ietf.utils.mail import send_mail from ietf.utils.mail import send_mail
from ietf.doc.utils import extract_complete_replaces_ancestor_mapping_for_docs from ietf.doc.utils import extract_complete_replaces_ancestor_mapping_for_docs
def active_review_teams(): def active_review_teams():
# if there's a ResultUsedInReviewTeam defined, it's a review team return Group.objects.filter(reviewteamsettings__isnull=False,state="active")
return Group.objects.filter(state="active").exclude(resultusedinreviewteam=None)
def close_review_request_states(): def close_review_request_states():
return ReviewRequestStateName.objects.filter(used=True).exclude(slug__in=["requested", "accepted", "rejected", "part-completed", "completed"]) return ReviewRequestStateName.objects.filter(used=True).exclude(slug__in=["requested", "accepted", "rejected", "part-completed", "completed"])
@ -526,6 +525,10 @@ def close_review_request(request, review_req, close_state):
by=request.user.person, notify_secretary=False, notify_reviewer=True, notify_requested_by=True) by=request.user.person, notify_secretary=False, notify_reviewer=True, notify_requested_by=True)
def suggested_review_requests_for_team(team): def suggested_review_requests_for_team(team):
if not team.reviewteamsettings.autosuggest:
return []
system_person = Person.objects.get(name="(System)") system_person = Person.objects.get(name="(System)")
seen_deadlines = {} seen_deadlines = {}
@ -539,7 +542,7 @@ def suggested_review_requests_for_team(team):
requested_state = ReviewRequestStateName.objects.get(slug="requested", used=True) requested_state = ReviewRequestStateName.objects.get(slug="requested", used=True)
last_call_type = ReviewTypeName.objects.get(slug="lc") last_call_type = ReviewTypeName.objects.get(slug="lc")
if TypeUsedInReviewTeam.objects.filter(team=team, type=last_call_type).exists(): if last_call_type in team.reviewteamsettings.review_types.all():
# in Last Call # in Last Call
last_call_docs = reviewable_docs_qs.filter( last_call_docs = reviewable_docs_qs.filter(
states=State.objects.get(type="draft-iesg", slug="lc", used=True) states=State.objects.get(type="draft-iesg", slug="lc", used=True)
@ -567,7 +570,7 @@ def suggested_review_requests_for_team(team):
telechat_type = ReviewTypeName.objects.get(slug="telechat") telechat_type = ReviewTypeName.objects.get(slug="telechat")
if TypeUsedInReviewTeam.objects.filter(team=team, type=telechat_type).exists(): if telechat_type in team.reviewteamsettings.review_types.all():
# on Telechat Agenda # on Telechat Agenda
telechat_dates = list(TelechatDate.objects.active().order_by('date').values_list("date", flat=True)[:4]) telechat_dates = list(TelechatDate.objects.active().order_by('date').values_list("date", flat=True)[:4])
@ -910,4 +913,3 @@ def email_secretary_reminder(review_request, secretary_role):
"deadline_days": deadline_days, "deadline_days": deadline_days,
"remind_days": remind_days, "remind_days": remind_days,
}) })

View file

@ -14,8 +14,7 @@ from ietf.meeting.models import Meeting
from ietf.name.models import StreamName, DocRelationshipName from ietf.name.models import StreamName, DocRelationshipName
from ietf.person.models import Person, Email from ietf.person.models import Person, Email
from ietf.group.utils import setup_default_community_list_for_group from ietf.group.utils import setup_default_community_list_for_group
from ietf.review.models import (ReviewRequest, ReviewerSettings, ReviewResultName, ResultUsedInReviewTeam, from ietf.review.models import (ReviewRequest, ReviewerSettings, ReviewResultName, ReviewTypeName, ReviewTeamSettings )
ReviewTypeName, TypeUsedInReviewTeam)
def create_person(group, role_name, name=None, username=None, email_address=None, password=None): def create_person(group, role_name, name=None, username=None, email_address=None, password=None):
"""Add person/user/email and role.""" """Add person/user/email and role."""
@ -390,10 +389,11 @@ def make_review_data(doc):
team2 = create_group(acronym="reviewteam2", name="Review Team 2", type_id="dir", list_email="reviewteam2@ietf.org", parent=Group.objects.get(acronym="farfut")) team2 = create_group(acronym="reviewteam2", name="Review Team 2", type_id="dir", list_email="reviewteam2@ietf.org", parent=Group.objects.get(acronym="farfut"))
team3 = create_group(acronym="reviewteam3", name="Review Team 3", type_id="dir", list_email="reviewteam2@ietf.org", parent=Group.objects.get(acronym="farfut")) team3 = create_group(acronym="reviewteam3", name="Review Team 3", type_id="dir", list_email="reviewteam2@ietf.org", parent=Group.objects.get(acronym="farfut"))
for team in (team1, team2, team3): for team in (team1, team2, team3):
ReviewTeamSettings.objects.create(group=team)
for r in ReviewResultName.objects.filter(slug__in=["issues", "ready-issues", "ready", "not-ready"]): for r in ReviewResultName.objects.filter(slug__in=["issues", "ready-issues", "ready", "not-ready"]):
ResultUsedInReviewTeam.objects.create(team=team, result=r) team.reviewteamsettings.review_results.add(r)
for t in ReviewTypeName.objects.filter(slug__in=["early", "lc", "telechat"]): for t in ReviewTypeName.objects.filter(slug__in=["early", "lc", "telechat"]):
TypeUsedInReviewTeam.objects.create(team=team, type=t) team.reviewteamsettings.review_types.add(t)
u = User.objects.create(username="reviewer") u = User.objects.create(username="reviewer")
u.set_password("reviewer+password") u.set_password("reviewer+password")