Skip to content

Commit 8e007ce

Browse files
committed
Make changing skip_next on a review assignment an explicit decision of the assigner. Commit ready for merge. Fixes ietf-tools#2148.
- Legacy-Id: 12670
1 parent 49dcf67 commit 8e007ce

6 files changed

Lines changed: 42 additions & 19 deletions

File tree

ietf/doc/tests_review.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from ietf.utils.test_data import make_test_data, make_review_data, create_person
2525
from ietf.utils.test_utils import login_testing_unauthorized, unicontent, reload_db_objects
2626
from ietf.utils.mail import outbox, empty_outbox
27+
from ietf.person.factories import PersonFactory
2728

2829
class ReviewTests(TestCase):
2930
def setUp(self):
@@ -180,27 +181,29 @@ def get_skip_next(person):
180181
or ReviewerSettings(team=team))
181182
return settings.skip_next
182183

183-
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[0].pk)
184+
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[0].pk, add_skip=False)
184185
self.assertEqual(NextReviewerInTeam.objects.get(team=team).next_reviewer, reviewers[1])
185186
self.assertEqual(get_skip_next(reviewers[0]), 0)
186187
self.assertEqual(get_skip_next(reviewers[1]), 0)
187188

188-
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[1].pk)
189+
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[1].pk, add_skip=True)
189190
self.assertEqual(NextReviewerInTeam.objects.get(team=team).next_reviewer, reviewers[2])
191+
self.assertEqual(get_skip_next(reviewers[1]), 1)
192+
self.assertEqual(get_skip_next(reviewers[2]), 0)
190193

191194
# skip reviewer 2
192-
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[3].pk)
195+
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[3].pk, add_skip=True)
193196
self.assertEqual(NextReviewerInTeam.objects.get(team=team).next_reviewer, reviewers[2])
194197
self.assertEqual(get_skip_next(reviewers[0]), 0)
195-
self.assertEqual(get_skip_next(reviewers[1]), 0)
198+
self.assertEqual(get_skip_next(reviewers[1]), 1)
196199
self.assertEqual(get_skip_next(reviewers[2]), 0)
197200
self.assertEqual(get_skip_next(reviewers[3]), 1)
198201

199202
# pick reviewer 2, use up reviewer 3's skip_next
200-
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[2].pk)
203+
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[2].pk, add_skip=False)
201204
self.assertEqual(NextReviewerInTeam.objects.get(team=team).next_reviewer, reviewers[4])
202205
self.assertEqual(get_skip_next(reviewers[0]), 0)
203-
self.assertEqual(get_skip_next(reviewers[1]), 0)
206+
self.assertEqual(get_skip_next(reviewers[1]), 1)
204207
self.assertEqual(get_skip_next(reviewers[2]), 0)
205208
self.assertEqual(get_skip_next(reviewers[3]), 0)
206209
self.assertEqual(get_skip_next(reviewers[4]), 0)
@@ -209,7 +212,7 @@ def get_skip_next(person):
209212
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[4].pk)
210213
self.assertEqual(NextReviewerInTeam.objects.get(team=team).next_reviewer, reviewers[0])
211214
self.assertEqual(get_skip_next(reviewers[0]), 0)
212-
self.assertEqual(get_skip_next(reviewers[1]), 0)
215+
self.assertEqual(get_skip_next(reviewers[1]), 1)
213216
self.assertEqual(get_skip_next(reviewers[2]), 0)
214217
self.assertEqual(get_skip_next(reviewers[3]), 0)
215218
self.assertEqual(get_skip_next(reviewers[4]), 0)
@@ -220,13 +223,13 @@ def get_skip_next(person):
220223
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[0].pk)
221224
self.assertEqual(NextReviewerInTeam.objects.get(team=team).next_reviewer, reviewers[2])
222225
self.assertEqual(get_skip_next(reviewers[0]), 0)
223-
self.assertEqual(get_skip_next(reviewers[1]), 0)
226+
self.assertEqual(get_skip_next(reviewers[1]), 1) # don't consume that skip while the reviewer is unavailable
224227
self.assertEqual(get_skip_next(reviewers[2]), 0)
225228
self.assertEqual(get_skip_next(reviewers[3]), 0)
226229
self.assertEqual(get_skip_next(reviewers[4]), 0)
227230

228231
# pick unavailable anyway
229-
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[1].pk)
232+
possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id=reviewers[1].pk, add_skip=False)
230233
self.assertEqual(NextReviewerInTeam.objects.get(team=team).next_reviewer, reviewers[2])
231234
self.assertEqual(get_skip_next(reviewers[0]), 0)
232235
self.assertEqual(get_skip_next(reviewers[1]), 1)
@@ -283,6 +286,10 @@ def test_assign_reviewer(self):
283286
reviewer_settings.skip_next = 1
284287
reviewer_settings.save()
285288

289+
# Need one more person in review team one so we can test incrementing skip_count without immediately decrementing it
290+
another_reviewer = PersonFactory.create()
291+
another_reviewer.role_set.create(name_id='reviewer', email=another_reviewer.email(), group=review_req.team)
292+
286293
UnavailablePeriod.objects.create(
287294
team=review_req.team,
288295
person=reviewer_email.person,
@@ -345,7 +352,7 @@ def test_assign_reviewer(self):
345352
review_req.state = ReviewRequestStateName.objects.get(slug="accepted")
346353
review_req.save()
347354
reviewer = Email.objects.filter(role__name="reviewer", role__group=review_req.team, person=rotation_list[1]).first()
348-
r = self.client.post(assign_url, { "action": "assign", "reviewer": reviewer.pk })
355+
r = self.client.post(assign_url, { "action": "assign", "reviewer": reviewer.pk, "add_skip": 1 })
349356
self.assertEqual(r.status_code, 302)
350357

351358
review_req = reload_db_objects(review_req)
@@ -354,6 +361,7 @@ def test_assign_reviewer(self):
354361
self.assertEqual(len(outbox), 2)
355362
self.assertTrue("cancelled your assignment" in outbox[0].get_payload(decode=True).decode("utf-8"))
356363
self.assertTrue("assigned" in outbox[1].get_payload(decode=True).decode("utf-8"))
364+
self.assertEqual(ReviewerSettings.objects.get(person=reviewer.person).skip_next, 1)
357365

358366
def test_accept_reviewer_assignment(self):
359367
doc = make_test_data()

ietf/doc/views_review.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ def close_request(request, name, request_id):
253253

254254
class AssignReviewerForm(forms.Form):
255255
reviewer = PersonEmailChoiceField(empty_label="(None)", required=False)
256+
add_skip = forms.BooleanField(label='Skip next time', required=False)
256257

257258
def __init__(self, review_req, *args, **kwargs):
258259
super(AssignReviewerForm, self).__init__(*args, **kwargs)
@@ -271,7 +272,8 @@ def assign_reviewer(request, name, request_id):
271272
form = AssignReviewerForm(review_req, request.POST)
272273
if form.is_valid():
273274
reviewer = form.cleaned_data["reviewer"]
274-
assign_review_request_to_reviewer(request, review_req, reviewer)
275+
add_skip = form.cleaned_data["add_skip"]
276+
assign_review_request_to_reviewer(request, review_req, reviewer, add_skip)
275277

276278
return redirect(review_request, name=review_req.doc.name, request_id=review_req.pk)
277279
else:

ietf/group/tests_review.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import ietf.group.views_review
2121
from ietf.utils.mail import outbox, empty_outbox
2222
from ietf.dbtemplate.factories import DBTemplateFactory
23+
from ietf.person.factories import PersonFactory
2324

2425
class ReviewTests(TestCase):
2526
def test_review_requests(self):
@@ -205,6 +206,10 @@ def test_manage_review_requests(self):
205206
deadline=datetime.date.today() - datetime.timedelta(days=80),
206207
reviewer=review_req1.reviewer,
207208
)
209+
210+
# Need one more person in review team one so we can test incrementing skip_count without immediately decrementing it
211+
another_reviewer = PersonFactory.create()
212+
another_reviewer.role_set.create(name_id='reviewer', email=another_reviewer.email(), group=review_req1.team)
208213

209214
# get
210215
r = self.client.get(assigned_url)
@@ -257,6 +262,7 @@ def test_manage_review_requests(self):
257262
"r{}-existing_reviewer".format(review_req2.pk): review_req2.reviewer_id or "",
258263
"r{}-action".format(review_req2.pk): "assign",
259264
"r{}-reviewer".format(review_req2.pk): new_reviewer.pk,
265+
"r{}-add_skip".format(review_req2.pk) : 1,
260266

261267
"action": "save",
262268
})
@@ -280,6 +286,8 @@ def test_manage_review_requests(self):
280286
self.assertEqual(review_req1.state_id, "no-response")
281287
self.assertEqual(review_req2.state_id, "requested")
282288
self.assertEqual(review_req2.reviewer, new_reviewer)
289+
settings = ReviewerSettings.objects.filter(team=review_req2.team, person=new_reviewer.person).first()
290+
self.assertEqual(settings.skip_next,1)
283291
self.assertEqual(review_req3.state_id, "requested")
284292

285293
def test_email_open_review_assignments(self):

ietf/group/views_review.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class ManageReviewRequestForm(forms.Form):
188188
action = forms.ChoiceField(choices=ACTIONS, widget=forms.HiddenInput, required=False)
189189
close = forms.ModelChoiceField(queryset=close_review_request_states(), required=False)
190190
reviewer = PersonEmailChoiceField(empty_label="(None)", required=False, label_with="person")
191+
add_skip = forms.BooleanField(required=False)
191192

192193
def __init__(self, review_req, *args, **kwargs):
193194
if not "prefix" in kwargs:
@@ -307,7 +308,7 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status=
307308
for review_req in review_requests:
308309
action = review_req.form.cleaned_data.get("action")
309310
if action == "assign":
310-
assign_review_request_to_reviewer(request, review_req, review_req.form.cleaned_data["reviewer"])
311+
assign_review_request_to_reviewer(request, review_req, review_req.form.cleaned_data["reviewer"],review_req.form.cleaned_data["add_skip"])
311312
elif action == "close":
312313
close_review_request(request, review_req, review_req.form.cleaned_data["close"])
313314

ietf/review/utils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ def extract_email_addresses(objs):
417417
"by": by,
418418
})
419419

420-
def assign_review_request_to_reviewer(request, review_req, reviewer):
420+
def assign_review_request_to_reviewer(request, review_req, reviewer, add_skip=False):
421421
assert review_req.state_id in ("requested", "accepted")
422422

423423
if reviewer == review_req.reviewer:
@@ -435,7 +435,7 @@ def assign_review_request_to_reviewer(request, review_req, reviewer):
435435
review_req.save()
436436

437437
if review_req.reviewer:
438-
possibly_advance_next_reviewer_for_team(review_req.team, review_req.reviewer.person_id)
438+
possibly_advance_next_reviewer_for_team(review_req.team, review_req.reviewer.person_id, add_skip)
439439

440440
ReviewRequestDocEvent.objects.create(
441441
type="assigned_review_request",
@@ -456,7 +456,7 @@ def assign_review_request_to_reviewer(request, review_req, reviewer):
456456
"%s has assigned you as a reviewer for this document." % request.user.person,
457457
by=request.user.person, notify_secretary=False, notify_reviewer=True, notify_requested_by=False)
458458

459-
def possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id):
459+
def possibly_advance_next_reviewer_for_team(team, assigned_review_to_person_id, add_skip=False):
460460
assert assigned_review_to_person_id is not None
461461

462462
rotation_list = reviewer_rotation_list(team, skip_unavailable=True, dont_skip=[assigned_review_to_person_id])
@@ -476,7 +476,8 @@ def reviewer_settings_for(person_id):
476476
if assigned_review_to_person_id == reviewer_at_index(current_i):
477477
# move 1 ahead
478478
current_i += 1
479-
else:
479+
480+
if add_skip:
480481
settings = reviewer_settings_for(assigned_review_to_person_id)
481482
settings.skip_next += 1
482483
settings.save()
@@ -491,7 +492,6 @@ def reviewer_settings_for(person_id):
491492
if settings.skip_next > 0:
492493
settings.skip_next -= 1
493494
settings.save()
494-
495495
current_i += 1
496496
else:
497497
nr = NextReviewerInTeam.objects.filter(team=team).first() or NextReviewerInTeam(team=team)

ietf/templates/group/manage_review_requests.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,17 @@ <h3 class="panel-title">
135135

136136
<span class="reviewer-controls form-inline">
137137
<label for="{{ r.form.reviewer.id_for_label }}">Assign:</label>
138-
{{ r.form.reviewer }}
138+
{{ r.form.reviewer }}
139+
{{ r.form.add_skip }} <label for="{{ r.form.add_skip.id_for_label }}">Skip next time</label>
139140
<button type="button" class="btn btn-default undo" title="Cancel assignment" data-initial="{{ r.form.fields.reviewer.initial|default:"" }}">Cancel</button>
140-
{% if r.form.reviewer.errors %}
141+
{% if r.form.reviewer.errors or r.form.add_skip.errors %}
141142
<div class="alert alert-danger">
142143
{% for e in r.form.reviewer.errors %}
143144
{{ e }}
144145
{% endfor %}
146+
{% for e in r.form.add_skip.errors %}
147+
{{ e }}
148+
{% endfor %}
145149
</div>
146150
{% endif %}
147151
</span>

0 commit comments

Comments
 (0)