Turn ReviewRequest.deadline into a date field with no time

- Legacy-Id: 11801
This commit is contained in:
Ole Laursen 2016-08-17 15:10:39 +00:00
parent 3ecaf54d51
commit 426542771a
15 changed files with 53 additions and 92 deletions

View file

@ -12,7 +12,7 @@ from pyquery import PyQuery
import debug # pyflakes:ignore
from ietf.review.models import ReviewRequest, ReviewTeamResult, Reviewer
from ietf.review.models import ReviewRequest, ReviewTeamResult, ReviewerSettings
import ietf.review.mailarch
from ietf.person.models import Email, Person
from ietf.name.models import ReviewResultName, ReviewRequestStateName, ReviewTypeName
@ -51,21 +51,20 @@ class ReviewTests(TestCase):
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
deadline_date = datetime.date.today() + datetime.timedelta(days=10)
deadline = datetime.date.today() + datetime.timedelta(days=10)
# post request
r = self.client.post(url, {
"type": "early",
"team": review_team.pk,
"deadline_date": deadline_date.isoformat(),
"deadline": deadline.isoformat(),
"requested_rev": "01",
"requested_by": Person.objects.get(user__username="plain").pk,
})
self.assertEqual(r.status_code, 302)
req = ReviewRequest.objects.get(doc=doc, state="requested")
self.assertEqual(req.deadline.date(), deadline_date)
self.assertEqual(req.deadline.time(), datetime.time(23, 59, 59))
self.assertEqual(req.deadline, deadline)
self.assertEqual(req.team, review_team)
self.assertEqual(req.requested_rev, "01")
self.assertEqual(doc.latest_event().type, "requested_review")
@ -146,14 +145,14 @@ class ReviewTests(TestCase):
team=review_req.team,
state=ReviewRequestStateName.objects.get(slug="completed"),
reviewed_rev="01",
deadline=datetime.datetime.now() - datetime.timedelta(days=80),
deadline=datetime.date.today() - datetime.timedelta(days=80),
reviewer=plain_email,
)
reviewer_obj = Reviewer.objects.get(person__email=plain_email)
reviewer_obj.filter_re = doc.name
reviewer_obj.unavailable_until = datetime.datetime.now() + datetime.timedelta(days=10)
reviewer_obj.save()
reviewer_settings = ReviewerSettings.objects.get(person__email=plain_email)
reviewer_settings.filter_re = doc.name
reviewer_settings.unavailable_until = datetime.datetime.now() + datetime.timedelta(days=10)
reviewer_settings.save()
assign_url = urlreverse('ietf.doc.views_review.assign_reviewer', kwargs={ "name": doc.name, "request_id": review_req.pk })

View file

@ -37,8 +37,7 @@ def clean_doc_revision(doc, rev):
class RequestReviewForm(forms.ModelForm):
team = forms.ModelMultipleChoiceField(queryset=Group.objects.all(), widget=forms.CheckboxSelectMultiple)
deadline_date = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={ "autoclose": "1", "start-date": "+0d" })
deadline_time = forms.TimeField(widget=forms.TextInput(attrs={ 'placeholder': "HH:MM" }), help_text="If time is not specified, end of day is assumed", required=False)
deadline = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={ "autoclose": "1", "start-date": "+0d" })
class Meta:
model = ReviewRequest
@ -59,7 +58,6 @@ class RequestReviewForm(forms.ModelForm):
f.initial = [group.pk for group in f.queryset if can_manage_review_requests_for_team(user, group, allow_non_team_personnel=False)]
self.fields["deadline"].required = False
self.fields["requested_rev"].label = "Document revision"
if has_role(user, "Secretariat"):
@ -68,8 +66,8 @@ class RequestReviewForm(forms.ModelForm):
self.fields["requested_by"].widget = forms.HiddenInput()
self.fields["requested_by"].initial = user.person.pk
def clean_deadline_date(self):
v = self.cleaned_data.get('deadline_date')
def clean_deadline(self):
v = self.cleaned_data.get('deadline')
if v < datetime.date.today():
raise forms.ValidationError("Select today or a date in the future.")
return v
@ -77,18 +75,6 @@ class RequestReviewForm(forms.ModelForm):
def clean_requested_rev(self):
return clean_doc_revision(self.doc, self.cleaned_data.get("requested_rev"))
def clean(self):
deadline_date = self.cleaned_data.get('deadline_date')
deadline_time = self.cleaned_data.get('deadline_time', None)
if deadline_date:
if deadline_time is None:
deadline_time = datetime.time(23, 59, 59)
self.cleaned_data["deadline"] = datetime.datetime.combine(deadline_date, deadline_time)
return self.cleaned_data
@login_required
def request_review(request, name):
doc = get_object_or_404(Document, name=name)

View file

@ -87,7 +87,7 @@ class ReviewTests(TestCase):
doc=review_req1.doc,
team=review_req1.team,
type_id="early",
deadline=datetime.datetime.combine(datetime.date.today() + datetime.timedelta(days=30), datetime.time(23, 59, 59)),
deadline=datetime.date.today() + datetime.timedelta(days=30),
state_id="accepted",
reviewer=review_req1.reviewer,
requested_by=Person.objects.get(user__username="plain"),
@ -97,7 +97,7 @@ class ReviewTests(TestCase):
doc=review_req1.doc,
team=review_req1.team,
type_id="early",
deadline=datetime.datetime.combine(datetime.date.today() + datetime.timedelta(days=30), datetime.time(23, 59, 59)),
deadline=datetime.date.today() + datetime.timedelta(days=30),
state_id="requested",
requested_by=Person.objects.get(user__username="plain"),
)

View file

@ -653,10 +653,10 @@ def review_requests(request, acronym, group_type=None):
open_review_requests += suggested_review_requests_for_team(group)
now = datetime.datetime.now()
today = datetime.date.today()
for r in open_review_requests:
delta = now - r.deadline
r.due = max(0, int(math.ceil(delta.total_seconds() / 3600.0)))
delta = today - r.deadline
r.due = max(0, delta.days())
closed_review_requests = ReviewRequest.objects.filter(
team=group,

View file

@ -16,7 +16,7 @@ django.setup()
import datetime
from collections import namedtuple
from django.db import connections
from ietf.review.models import ReviewRequest, Reviewer, ReviewResultName
from ietf.review.models import ReviewRequest, ReviewerSettings, ReviewResultName
from ietf.review.models import ReviewRequestStateName, ReviewTypeName, ReviewTeamResult
from ietf.group.models import Group, Role, RoleName
from ietf.person.models import Person, Email, Alias
@ -105,7 +105,7 @@ with db_con.cursor() as c:
if created:
print "created role", unicode(role).encode("utf-8")
reviewer, created = Reviewer.objects.get_or_create(
reviewer, created = ReviewerSettings.objects.get_or_create(
team=team,
person=email.person,
)
@ -217,7 +217,7 @@ with db_con.cursor() as c:
defaults={
"state": states["requested"],
"type": type_name,
"deadline": deadline,
"deadline": deadline.date(),
"requested_by": system_person,
}
)
@ -228,7 +228,7 @@ with db_con.cursor() as c:
req.type = type_name
req.time = time
req.reviewed_rev = reviewed_rev
req.deadline = deadline
req.deadline = deadline.date()
req.save()
# FIXME: add log entries

View file

@ -2,12 +2,13 @@
from __future__ import unicode_literals
from django.db import models, migrations
import datetime
class Migration(migrations.Migration):
dependencies = [
('name', '0012_insert_review_name_data'),
('name', '0013_auto_20160623_0621'),
('group', '0008_auto_20160505_0523'),
('person', '0014_auto_20160613_0751'),
('doc', '0012_auto_20160207_0537'),
@ -15,10 +16,10 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name='Reviewer',
name='ReviewerSettings',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('frequency', models.IntegerField(default=30, help_text=b'Can review every N days')),
('frequency', models.IntegerField(default=30, help_text=b'Can review every N days', choices=[(7, b'Once per week'), (14, b'Once per fortnight'), (30, b'Once per month'), (61, b'Once per two months'), (91, b'Once per quarter')])),
('unavailable_until', models.DateTimeField(help_text=b'When will this reviewer be available again', null=True, blank=True)),
('filter_re', models.CharField(max_length=255, blank=True)),
('skip_next', models.IntegerField(default=0, help_text=b'Skip the next N review assignments')),
@ -34,15 +35,15 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('old_id', models.IntegerField(help_text=b'ID in previous review system', null=True, blank=True)),
('time', models.DateTimeField(auto_now_add=True)),
('deadline', models.DateTimeField()),
('time', models.DateTimeField(default=datetime.datetime.now)),
('deadline', models.DateField()),
('requested_rev', models.CharField(help_text=b'Fill in if a specific revision is to be reviewed, e.g. 02', max_length=16, verbose_name=b'requested revision', blank=True)),
('reviewed_rev', models.CharField(max_length=16, verbose_name=b'reviewed revision', blank=True)),
('doc', models.ForeignKey(related_name='review_request_set', to='doc.Document')),
('requested_by', models.ForeignKey(to='person.Person')),
('result', models.ForeignKey(blank=True, to='name.ReviewResultName', null=True)),
('review', models.OneToOneField(null=True, blank=True, to='doc.Document')),
('reviewer', models.ForeignKey(blank=True, to='person.Email', null=True)),
('requested_by', models.ForeignKey(to='person.Person')),
('state', models.ForeignKey(to='name.ReviewRequestStateName')),
('team', models.ForeignKey(to='group.Group')),
('type', models.ForeignKey(to='name.ReviewTypeName')),

View file

@ -7,7 +7,7 @@ from ietf.group.models import Group
from ietf.person.models import Person, Email
from ietf.name.models import ReviewTypeName, ReviewRequestStateName, ReviewResultName
class Reviewer(models.Model):
class ReviewerSettings(models.Model):
"""Keeps track of admin data associated with the reviewer in the
particular team. There will be one record for each combination of
reviewer and team."""
@ -50,7 +50,7 @@ class ReviewRequest(models.Model):
type = models.ForeignKey(ReviewTypeName)
doc = models.ForeignKey(Document, related_name='review_request_set')
team = models.ForeignKey(Group, limit_choices_to=~models.Q(reviewteamresult=None))
deadline = models.DateTimeField()
deadline = models.DateField()
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")

View file

@ -7,16 +7,16 @@ from tastypie.cache import SimpleCache
from ietf import api
from ietf.api import ToOneField # pyflakes:ignore
from ietf.review.models import Reviewer, ReviewRequest, ReviewTeamResult
from ietf.review.models import ReviewerSettings, ReviewRequest, ReviewTeamResult
from ietf.person.resources import PersonResource
from ietf.group.resources import GroupResource
class ReviewerResource(ModelResource):
class ReviewerSettingsResource(ModelResource):
team = ToOneField(GroupResource, 'team')
person = ToOneField(PersonResource, 'person')
class Meta:
queryset = Reviewer.objects.all()
queryset = ReviewerSettings.objects.all()
serializer = api.Serializer()
cache = SimpleCache()
#resource_name = 'reviewer'
@ -29,7 +29,7 @@ class ReviewerResource(ModelResource):
"team": ALL_WITH_RELATIONS,
"person": ALL_WITH_RELATIONS,
}
api.review.register(ReviewerResource())
api.review.register(ReviewerSettingsResource())
from ietf.doc.resources import DocumentResource
from ietf.group.resources import RoleResource, GroupResource

View file

@ -9,7 +9,7 @@ from ietf.doc.models import Document, DocEvent, State, LastCallDocEvent, Documen
from ietf.iesg.models import TelechatDate
from ietf.person.models import Person, Email
from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream
from ietf.review.models import ReviewRequest, ReviewRequestStateName, ReviewTypeName, Reviewer
from ietf.review.models import ReviewRequest, ReviewRequestStateName, ReviewTypeName, ReviewerSettings
from ietf.utils.mail import send_mail
from ietf.doc.utils import extract_complete_replaces_ancestor_mapping_for_docs
@ -151,11 +151,6 @@ def close_review_request(request, review_req, close_state):
by=request.user.person, notify_secretary=False, notify_reviewer=True, notify_requested_by=True)
def suggested_review_requests_for_team(team):
def fixup_deadline(d):
if d.time() == datetime.time(0):
d = d - datetime.timedelta(seconds=1) # 23:59:59 is treated specially in the view code
return d
system_person = Person.objects.get(name="(System)")
seen_deadlines = {}
@ -170,9 +165,9 @@ def suggested_review_requests_for_team(team):
last_call_docs = Document.objects.filter(states=State.objects.get(type="draft-iesg", slug="lc", used=True))
last_call_expires = { e.doc_id: e.expires for e in LastCallDocEvent.objects.order_by("time", "id") }
for doc in last_call_docs:
deadline = fixup_deadline(last_call_expires.get(doc.pk)) if doc.pk in last_call_expires else datetime.datetime.now()
deadline = last_call_expires[doc.pk].date() if doc.pk in last_call_expires else datetime.date.today()
if deadline > seen_deadlines.get(doc.pk, datetime.datetime.max):
if deadline > seen_deadlines.get(doc.pk, datetime.date.max):
continue
requests[doc.pk] = ReviewRequest(
@ -200,9 +195,9 @@ def suggested_review_requests_for_team(team):
if d not in telechat_dates:
continue
deadline = datetime.datetime.combine(d - telechat_deadline_delta, datetime.time(23, 59, 59))
deadline = d - telechat_deadline_delta
if deadline > seen_deadlines.get(doc.pk, datetime.datetime.max):
if deadline > seen_deadlines.get(doc.pk, datetime.date.max):
continue
requests[doc.pk] = ReviewRequest(
@ -302,7 +297,7 @@ def make_assignment_choices(email_queryset, review_req):
aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True)
reviewers = { r.person_id: r for r in Reviewer.objects.filter(team=team, person__in=[e.person_id for e in possible_emails]) }
reviewers = { r.person_id: r for r in ReviewerSettings.objects.filter(team=team, person__in=[e.person_id for e in possible_emails]) }
# time since past assignment
latest_assignment_for_reviewer = dict(ReviewRequest.objects.filter(
@ -347,7 +342,7 @@ def make_assignment_choices(email_queryset, review_req):
for e in possible_emails:
reviewer = reviewers.get(e.person_id)
if not reviewer:
reviewer = Reviewer()
reviewer = ReviewerSettings()
explanations = []
scores = [] # build up score in separate independent components

View file

@ -1,6 +1,6 @@
{% autoescape off %}
{{ review_req.type.name }} review of: {{ review_req.doc.name }} ({% if review_req.requested_rev %}rev. {{ review_req.requested_rev }}{% else %}no specific version{% endif %})
Deadline: {% if review_req.deadline|date:"H:i" != "23:59" %}{{ review_req.deadline|date:"Y-m-d H:i" }}{% else %}{{ review_req.deadline|date:"Y-m-d" }}{% endif %}
Deadline: {{ review_req.deadline|date:"Y-m-d" }}
{{ review_req_url }}

View file

@ -33,8 +33,7 @@
{% bootstrap_field form.requested_by layout="horizontal" %}
{% bootstrap_field form.type layout="horizontal" %}
{% bootstrap_field form.team layout="horizontal" %}
{% bootstrap_field form.deadline_date layout="horizontal" %}
{% bootstrap_field form.deadline_time layout="horizontal" %}
{% bootstrap_field form.deadline layout="horizontal" %}
{% bootstrap_field form.requested_rev layout="horizontal" %}
{% buttons %}

View file

@ -50,13 +50,7 @@
<tr>
<th></th>
<th>Deadline</th>
<td>
{% if review_req.deadline|date:"H:i" != "23:59" %}
{{ review_req.deadline|date:"Y-m-d H:i" }}
{% else %}
{{ review_req.deadline|date:"Y-m-d" }}
{% endif %}
</td>
<td>{{ review_req.deadline|date:"Y-m-d" }}</td>
</tr>
<tr>

View file

@ -47,12 +47,8 @@
<td>{{ r.type.name }}</td>
<td>{% if r.time %}{{ r.time|date:"Y-m-d" }}{% else %}<em>auto-suggested</em>{% endif %}</td>
<td>
{% if r.deadline|date:"H:i" != "23:59" %}
{{ r.deadline|date:"Y-m-d H:i" }}
{% else %}
{{ r.deadline|date:"Y-m-d" }}
{% endif %}
{% if r.due %}<span class="label label-warning">{{ r.due }} hour{{ r.due|pluralize }}</span>{% endif %}
{{ r.deadline|date:"Y-m-d" }}
{% if r.due %}<span class="label label-warning">{{ r.due }} day{{ r.due|pluralize }}</span>{% endif %}
</td>
<td>
{% if r.reviewer %}

View file

@ -33,12 +33,8 @@
<td>{{ r.type.name }}</td>
<td>{% if r.time %}{{ r.time|date:"Y-m-d" }}{% else %}<em>auto-suggested</em>{% endif %}</td>
<td>
{% if r.deadline|date:"H:i" != "23:59" %}
{{ r.deadline|date:"Y-m-d H:i" }}
{% else %}
{{ r.deadline|date:"Y-m-d" }}
{% endif %}
{% if r.due %}<span class="label label-warning">{{ r.due }} hour{{ r.due|pluralize }}</span>{% endif %}
{{ r.deadline|date:"Y-m-d" }}
{% if r.due %}<span class="label label-warning">{{ r.due }} day{{ r.due|pluralize }}</span>{% endif %}
</td>
<td>
{% if r.reviewer %}
@ -86,13 +82,7 @@
<td><a href="{% url "ietf.doc.views_review.review_request" name=r.doc.name request_id=r.pk %}">{{ r.doc.name }}{% if r.requested_rev %}-{{ r.requested_rev }}{% endif %}</a></td>
<td>{{ r.type }}</td>
<td>{{ r.time|date:"Y-m-d" }}</td>
<td>
{% if r.deadline|date:"H:i" != "23:59" %}
{{ r.deadline|date:"Y-m-d H:i" }}
{% else %}
{{ r.deadline|date:"Y-m-d" }}
{% endif %}
</td>
<td>{{ r.deadline|date:"Y-m-d" }}</td>
<td>
{% if r.reviewer %}
{{ r.reviewer.person }}
@ -104,7 +94,8 @@
<td>
{% if r.result %}
{{ r.result.name }}
{% endif %}</td>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>

View file

@ -13,7 +13,7 @@ from ietf.ipr.models import HolderIprDisclosure, IprDocRel, IprDisclosureStateNa
from ietf.meeting.models import Meeting
from ietf.name.models import StreamName, DocRelationshipName
from ietf.person.models import Person, Email
from ietf.review.models import ReviewRequest, Reviewer, ReviewResultName, ReviewTeamResult
from ietf.review.models import ReviewRequest, ReviewerSettings, ReviewResultName, ReviewTeamResult
def create_person(group, role_name, name=None, username=None, email_address=None, password=None):
"""Add person/user/email and role."""
@ -367,7 +367,7 @@ def make_review_data(doc):
p = Person.objects.get(user__username="plain")
email = p.email_set.first()
Role.objects.create(name_id="reviewer", person=p, email=email, group=team)
Reviewer.objects.create(team=team, person=p, frequency=14, skip_next=0)
ReviewerSettings.objects.create(team=team, person=p, frequency=14, skip_next=0)
review_req = ReviewRequest.objects.create(
doc=doc,