Skip to content

Commit e91d706

Browse files
committed
Checkpointing. This is an incomplete idea. The tests will fail massively.
- Legacy-Id: 15985
1 parent d820a78 commit e91d706

File tree

12 files changed

+379
-191
lines changed

12 files changed

+379
-191
lines changed

ietf/bin/send-review-reminders

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ today = datetime.date.today()
2727

2828
for review_req in review_requests_needing_reviewer_reminder(today):
2929
email_reviewer_reminder(review_req)
30-
print("Emailed reminder to {} for review of {} in {} (req. id {})".format(review_req.reviewer.address, review_req.doc_id, review_req.team.acronym, review_req.pk))
30+
for review_assignment in review_req.reviewassignment_set.all():
31+
print("Emailed reminder to {} for review of {} in {} (req. id {})".format(review_assignment.reviewer.address, review_req.doc_id, review_req.team.acronym, review_req.pk))
3132

3233
for review_req, secretary_role in review_requests_needing_secretary_reminder(today):
3334
email_secretary_reminder(review_req, secretary_role)

ietf/doc/models.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from ietf.group.models import Group
2222
from ietf.name.models import ( DocTypeName, DocTagName, StreamName, IntendedStdLevelName, StdLevelName,
23-
DocRelationshipName, DocReminderTypeName, BallotPositionName, ReviewRequestStateName, FormalLanguageName,
23+
DocRelationshipName, DocReminderTypeName, BallotPositionName, ReviewRequestStateName, ReviewAssignmentStateName, FormalLanguageName,
2424
DocUrlTagName)
2525
from ietf.person.models import Email, Person
2626
from ietf.person.utils import get_active_ads
@@ -1144,6 +1144,10 @@ class ReviewRequestDocEvent(DocEvent):
11441144
review_request = ForeignKey('review.ReviewRequest')
11451145
state = ForeignKey(ReviewRequestStateName, blank=True, null=True)
11461146

1147+
class ReviewAssignmentDocEvent(DocEvent):
1148+
review_assignment = ForeignKey('review.ReviewAssignment')
1149+
state = ForeignKey(ReviewAssignmentStateName, blank=True, null=True)
1150+
11471151
# charter events
11481152
class InitialReviewDocEvent(DocEvent):
11491153
expires = models.DateTimeField(blank=True, null=True)

ietf/doc/resources.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
TelechatDocEvent, DocReminder, LastCallDocEvent, NewRevisionDocEvent, WriteupDocEvent,
1313
InitialReviewDocEvent, DocHistoryAuthor, BallotDocEvent, RelatedDocument,
1414
RelatedDocHistory, BallotPositionDocEvent, AddedMessageEvent, SubmissionDocEvent,
15-
ReviewRequestDocEvent, EditedAuthorsDocEvent, DocumentURL)
15+
ReviewRequestDocEvent, ReviewAssignmentDocEvent, EditedAuthorsDocEvent, DocumentURL)
1616

1717
from ietf.name.resources import BallotPositionNameResource, DocTypeNameResource
1818
class BallotTypeResource(ModelResource):
@@ -652,3 +652,32 @@ class Meta:
652652
api.doc.register(DocumentURLResource())
653653

654654

655+
656+
657+
from ietf.person.resources import PersonResource
658+
from ietf.review.resources import ReviewAssignmentResource
659+
from ietf.name.resources import ReviewAssignmentStateNameResource
660+
class ReviewAssignmentDocEventResource(ModelResource):
661+
by = ToOneField(PersonResource, 'by')
662+
doc = ToOneField(DocumentResource, 'doc')
663+
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
664+
review_assignment = ToOneField(ReviewAssignmentResource, 'review_assignment')
665+
state = ToOneField(ReviewAssignmentStateNameResource, 'state', null=True)
666+
class Meta:
667+
queryset = ReviewAssignmentDocEvent.objects.all()
668+
serializer = api.Serializer()
669+
cache = SimpleCache()
670+
#resource_name = 'reviewassignmentdocevent'
671+
filtering = {
672+
"id": ALL,
673+
"time": ALL,
674+
"type": ALL,
675+
"rev": ALL,
676+
"desc": ALL,
677+
"by": ALL_WITH_RELATIONS,
678+
"doc": ALL_WITH_RELATIONS,
679+
"docevent_ptr": ALL_WITH_RELATIONS,
680+
"review_assignment": ALL_WITH_RELATIONS,
681+
"state": ALL_WITH_RELATIONS,
682+
}
683+
api.doc.register(ReviewAssignmentDocEventResource())

ietf/doc/views_review.py

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@
2121

2222
from ietf.doc.models import (Document, NewRevisionDocEvent, State, DocAlias,
2323
LastCallDocEvent, ReviewRequestDocEvent, DocumentAuthor)
24-
from ietf.name.models import ReviewRequestStateName, ReviewResultName, DocTypeName
25-
from ietf.review.models import ReviewRequest
24+
from ietf.name.models import ReviewRequestStateName, ReviewAssignmentStateName, ReviewResultName, DocTypeName
25+
from ietf.review.models import ReviewRequest, ReviewAssignment
2626
from ietf.group.models import Group
2727
from ietf.ietfauth.utils import is_authorized_in_doc_stream, user_is_person, has_role
2828
from ietf.message.models import Message
2929
from ietf.message.utils import infer_message
3030
from ietf.person.fields import PersonEmailChoiceField, SearchablePersonField
3131
from ietf.review.utils import (active_review_teams, assign_review_request_to_reviewer,
3232
can_request_review_of_doc, can_manage_review_requests_for_team,
33-
email_review_request_change, make_new_review_request_from_existing,
34-
close_review_request_states, close_review_request,
35-
setup_reviewer_field)
33+
email_review_assignment_change, email_review_request_change,
34+
make_new_review_request_from_existing, close_review_request_states,
35+
close_review_request, setup_reviewer_field)
3636
from ietf.review import mailarch
3737
from ietf.utils.fields import DatepickerDateField
3838
from ietf.utils.text import strip_prefix, xslugify
@@ -281,7 +281,7 @@ def __init__(self, review_req, *args, **kwargs):
281281
@login_required
282282
def assign_reviewer(request, name, request_id):
283283
doc = get_object_or_404(Document, name=name)
284-
review_req = get_object_or_404(ReviewRequest, pk=request_id, state__in=["requested", "accepted"])
284+
review_req = get_object_or_404(ReviewRequest, pk=request_id, state__in=["requested", "assigned"])
285285

286286
if not can_manage_review_requests_for_team(request.user, review_req.team):
287287
return HttpResponseForbidden("You do not have permission to perform this action")
@@ -307,58 +307,55 @@ class RejectReviewerAssignmentForm(forms.Form):
307307
message_to_secretary = forms.CharField(widget=forms.Textarea, required=False, help_text="Optional explanation of rejection, will be emailed to team secretary if filled in", strip=False)
308308

309309
@login_required
310-
def reject_reviewer_assignment(request, name, request_id):
310+
def reject_reviewer_assignment(request, name, assignment_id):
311311
doc = get_object_or_404(Document, name=name)
312-
review_req = get_object_or_404(ReviewRequest, pk=request_id, state__in=["requested", "accepted"])
312+
review_assignment = get_object_or_404(ReviewAssignment, pk=assignment_id, state__in=["assigned", "accepted"])
313313

314-
if not review_req.reviewer:
315-
return redirect(review_request, name=review_req.doc.name, request_id=review_req.pk)
314+
if not review_assignment.reviewer:
315+
return redirect(review_request, name=review_assignment.review_request.doc.name, request_id=review_assignment.review_request.pk)
316316

317-
is_reviewer = user_is_person(request.user, review_req.reviewer.person)
318-
can_manage_request = can_manage_review_requests_for_team(request.user, review_req.team)
317+
is_reviewer = user_is_person(request.user, review_assignment.reviewer.person)
318+
can_manage_request = can_manage_review_requests_for_team(request.user, review_assignment.review_request.team)
319319

320320
if not (is_reviewer or can_manage_request):
321321
return HttpResponseForbidden("You do not have permission to perform this action")
322322

323323
if request.method == "POST" and request.POST.get("action") == "reject":
324324
form = RejectReviewerAssignmentForm(request.POST)
325325
if form.is_valid():
326-
# reject the request
327-
review_req.state = ReviewRequestStateName.objects.get(slug="rejected")
328-
review_req.save()
329-
330-
ReviewRequestDocEvent.objects.create(
331-
type="closed_review_request",
332-
doc=review_req.doc,
333-
rev=review_req.doc.rev,
334-
by=request.user.person,
335-
desc="Assignment of request for {} review by {} to {} was rejected".format(
336-
review_req.type.name,
337-
review_req.team.acronym.upper(),
338-
review_req.reviewer.person,
339-
),
340-
review_request=review_req,
341-
state=review_req.state,
342-
)
343-
344-
# make a new unassigned review request
345-
new_review_req = make_new_review_request_from_existing(review_req)
346-
new_review_req.save()
326+
# reject the assignment
327+
review_assignment.state = ReviewAssignmentStateName.objects.get(slug="rejected")
328+
review_assignment.save()
329+
330+
# TODO: this needs to be reworked as a ReviewAssignmentDocEvent
331+
#ReviewRequestDocEvent.objects.create(
332+
# type="closed_review_request",
333+
# doc=review_req.doc,
334+
# rev=review_req.doc.rev,
335+
# by=request.user.person,
336+
# desc="Assignment of request for {} review by {} to {} was rejected".format(
337+
# review_req.type.name,
338+
# review_req.team.acronym.upper(),
339+
# review_req.reviewer.person,
340+
# ),
341+
# review_request=review_req,
342+
# state=review_req.state,
343+
#)
347344

348345
msg = render_to_string("review/reviewer_assignment_rejected.txt", {
349346
"by": request.user.person,
350347
"message_to_secretary": form.cleaned_data.get("message_to_secretary")
351348
})
352349

353-
email_review_request_change(request, review_req, "Reviewer assignment rejected", msg, by=request.user.person, notify_secretary=True, notify_reviewer=True, notify_requested_by=False)
350+
email_review_assignment_change(request, review_assignment, "Reviewer assignment rejected", msg, by=request.user.person, notify_secretary=True, notify_reviewer=True, notify_requested_by=False)
354351

355-
return redirect(review_request, name=new_review_req.doc.name, request_id=new_review_req.pk)
352+
return redirect(review_request, name=review_assignment.review_request.doc.name, request_id=review_assignment.review_request.pk)
356353
else:
357354
form = RejectReviewerAssignmentForm()
358355

359356
return render(request, 'doc/review/reject_reviewer_assignment.html', {
360357
'doc': doc,
361-
'review_req': review_req,
358+
'review_req': review_assignment.review_request,
362359
'form': form,
363360
})
364361

ietf/group/views.py

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
from ietf.meeting.utils import group_sessions
8686
from ietf.name.models import GroupTypeName, StreamName
8787
from ietf.person.models import Email
88-
from ietf.review.models import ReviewRequest, ReviewerSettings, ReviewSecretarySettings
88+
from ietf.review.models import ReviewRequest, ReviewAssignment, ReviewerSettings, ReviewSecretarySettings
8989
from ietf.review.utils import (can_manage_review_requests_for_team,
9090
can_access_review_stats_for_team,
9191

@@ -1262,27 +1262,26 @@ def group_menu_data(request):
12621262
# --- Review views -----------------------------------------------------
12631263

12641264
def get_open_review_requests_for_team(team, assignment_status=None):
1265-
open_review_requests = ReviewRequest.objects.filter(
1266-
team=team,
1267-
state__in=("requested", "accepted")
1265+
open_review_requests = ReviewRequest.objects.filter(team=team).filter(
1266+
Q(state_id='requested') | Q(state_id='assigned',reviewassignment__state__in=('assigned','accepted'))
12681267
).prefetch_related(
1269-
"reviewer__person", "type", "state", "doc", "doc__states",
1268+
"type", "state", "doc", "doc__states",
12701269
).order_by("-time", "-id")
12711270

12721271
if assignment_status == "unassigned":
1273-
open_review_requests = suggested_review_requests_for_team(team) + list(open_review_requests.filter(reviewer=None))
1272+
open_review_requests = suggested_review_requests_for_team(team) + list(open_review_requests.filter(state_id='requested'))
12741273
elif assignment_status == "assigned":
1275-
open_review_requests = list(open_review_requests.exclude(reviewer=None))
1274+
open_review_requests = list(open_review_requests.filter(state_id='assigned'))
12761275
else:
12771276
open_review_requests = suggested_review_requests_for_team(team) + list(open_review_requests)
12781277

1279-
today = datetime.date.today()
1280-
unavailable_periods = current_unavailable_periods_for_reviewers(team)
1281-
for r in open_review_requests:
1282-
if r.reviewer:
1283-
r.reviewer_unavailable = any(p.availability == "unavailable"
1284-
for p in unavailable_periods.get(r.reviewer.person_id, []))
1285-
r.due = max(0, (today - r.deadline).days)
1278+
#today = datetime.date.today()
1279+
#unavailable_periods = current_unavailable_periods_for_reviewers(team)
1280+
#for r in open_review_requests:
1281+
#if r.reviewer:
1282+
# r.reviewer_unavailable = any(p.availability == "unavailable"
1283+
# for p in unavailable_periods.get(r.reviewer.person_id, []))
1284+
#r.due = max(0, (today - r.deadline).days)
12861285

12871286
return open_review_requests
12881287

@@ -1291,25 +1290,19 @@ def review_requests(request, acronym, group_type=None):
12911290
if not group.features.has_reviews:
12921291
raise Http404
12931292

1294-
assigned_review_requests = []
1295-
unassigned_review_requests = []
1293+
unassigned_review_requests = [r for r in get_open_review_requests_for_team(group) if not r.state_id=='assigned']
12961294

1297-
for r in get_open_review_requests_for_team(group):
1298-
if r.reviewer:
1299-
assigned_review_requests.append(r)
1300-
else:
1301-
unassigned_review_requests.append(r)
1295+
open_review_assignments = list(ReviewAssignment.objects.filter(review_request__team=group, state_id__in=('assigned','accepted')).order_by('-assigned_on'))
1296+
today = datetime.date.today()
1297+
unavailable_periods = current_unavailable_periods_for_reviewers(group)
1298+
for a in open_review_assignments:
1299+
a.reviewer_unavailable = any(p.availability == "unavailable"
1300+
for p in unavailable_periods.get(a.reviewer.person_id, []))
1301+
a.due = max(0, (today - a.review_request.deadline).days)
13021302

1303-
open_review_requests = [
1304-
("Unassigned", unassigned_review_requests),
1305-
("Assigned", assigned_review_requests),
1306-
]
1303+
closed_review_assignments = ReviewAssignment.objects.filter(review_request__team=group).exclude(state_id__in=('assigned','accepted')).prefetch_related("state","result").order_by('-assigned_on')
13071304

1308-
closed_review_requests = ReviewRequest.objects.filter(
1309-
team=group,
1310-
).exclude(
1311-
state__in=("requested", "accepted")
1312-
).prefetch_related("reviewer__person", "type", "state", "doc", "result").order_by("-time", "-id")
1305+
closed_review_requests = ReviewRequest.objects.filter(team=group).exclude(state__in=("requested", "assigned")).prefetch_related("type", "state", "doc").order_by("-time", "-id")
13131306

13141307
since_choices = [
13151308
(None, "1 month"),
@@ -1337,10 +1330,14 @@ def review_requests(request, acronym, group_type=None):
13371330
| Q(reviewrequestdocevent__isnull=True, time__gte=datetime.date.today() - date_limit)
13381331
).distinct()
13391332

1333+
closed_review_assignments = closed_review_assignments.filter(completed_on__gte = datetime.date.today() - date_limit)
1334+
13401335
return render(request, 'group/review_requests.html',
13411336
construct_group_menu_context(request, group, "review requests", group_type, {
1342-
"open_review_requests": open_review_requests,
1337+
"unassigned_review_requests": unassigned_review_requests,
1338+
"open_review_assignments": open_review_assignments,
13431339
"closed_review_requests": closed_review_requests,
1340+
"closed_review_assignments": closed_review_assignments,
13441341
"since_choices": since_choices,
13451342
"since": since,
13461343
"can_manage_review_requests": can_manage_review_requests_for_team(request.user, group),

ietf/name/models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ class LiaisonStatementEventTypeName(NameModel):
9595
class LiaisonStatementTagName(NameModel):
9696
"Action Required, Action Taken"
9797
class ReviewRequestStateName(NameModel):
98-
"""Requested, Accepted, Rejected, Withdrawn, Overtaken By Events,
99-
No Response, No Review of Version, No Review of Document, Partially Completed, Completed"""
98+
"""Requested, Assigned, Withdrawn, Overtaken By Events, No Review of Version, No Review of Document"""
99+
class ReviewAssignmentStateName(NameModel):
100+
"""Accepted, Rejected, Withdrawn, Overtaken By Events, No Response, Partially Completed, Completed"""
100101
class ReviewTypeName(NameModel):
101102
"""Early Review, Last Call, Telechat"""
102103
class ReviewResultName(NameModel):

ietf/name/resources.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
ImportantDateName, IntendedStdLevelName, IprDisclosureStateName, IprEventTypeName,
1515
IprLicenseTypeName, LiaisonStatementEventTypeName, LiaisonStatementPurposeName,
1616
LiaisonStatementState, LiaisonStatementTagName, MeetingTypeName, NomineePositionStateName,
17-
ReviewRequestStateName, ReviewResultName, ReviewTypeName, RoleName, RoomResourceName,
18-
SessionStatusName, StdLevelName, StreamName, TimeSlotTypeName, TopicAudienceName, )
17+
ReviewAssignmentStateName, ReviewRequestStateName, ReviewResultName, ReviewTypeName,
18+
RoleName, RoomResourceName, SessionStatusName, StdLevelName, StreamName, TimeSlotTypeName,
19+
TopicAudienceName, )
1920

2021
class TimeSlotTypeNameResource(ModelResource):
2122
class Meta:
@@ -567,3 +568,19 @@ class Meta:
567568
"order": ALL,
568569
}
569570
api.name.register(AgendaTypeNameResource())
571+
572+
573+
class ReviewAssignmentStateNameResource(ModelResource):
574+
class Meta:
575+
queryset = ReviewAssignmentStateName.objects.all()
576+
serializer = api.Serializer()
577+
cache = SimpleCache()
578+
#resource_name = 'reviewassignmentstatename'
579+
filtering = {
580+
"slug": ALL,
581+
"name": ALL,
582+
"desc": ALL,
583+
"used": ALL,
584+
"order": ALL,
585+
}
586+
api.name.register(ReviewAssignmentStateNameResource())

ietf/review/admin.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ class NextReviewerInTeamAdmin(admin.ModelAdmin):
5353
class ReviewRequestAdmin(admin.ModelAdmin):
5454
list_display = ["doc", "time", "type", "team", "deadline"]
5555
list_display_links = ["doc"]
56-
list_filter = ["team", "type", "state", "result"]
56+
list_filter = ["team", "type", "state"]
5757
ordering = ["-id"]
58-
raw_id_fields = ["doc", "team", "requested_by", "reviewer", "review"]
58+
raw_id_fields = ["doc", "team", "requested_by"]
5959
date_hierarchy = "time"
60-
search_fields = ["doc__name", "reviewer__person__name"]
60+
search_fields = ["doc__name"]
6161

6262
admin.site.register(ReviewRequest, ReviewRequestAdmin)
6363

0 commit comments

Comments
 (0)