Merged in [16765] from sasha@dashcare.nl:
Refs #2277 - Send daily reminders of overdue reviews to secretaries
- Legacy-Id: 16839
Note: SVN reference [16765] has been migrated to Git commit cc64992204
This commit is contained in:
commit
678f8a5787
|
@ -24,7 +24,9 @@ import datetime
|
|||
from ietf.review.utils import (
|
||||
review_assignments_needing_reviewer_reminder, email_reviewer_reminder,
|
||||
review_assignments_needing_secretary_reminder, email_secretary_reminder,
|
||||
send_unavaibility_period_ending_reminder, send_reminder_all_open_reviews)
|
||||
send_unavaibility_period_ending_reminder, send_reminder_all_open_reviews,
|
||||
send_review_reminder_overdue_assignment)
|
||||
|
||||
today = datetime.date.today()
|
||||
|
||||
for assignment in review_assignments_needing_reviewer_reminder(today):
|
||||
|
@ -40,6 +42,8 @@ for assignment, secretary_role in review_assignments_needing_secretary_reminder(
|
|||
period_end_reminders_sent = send_unavaibility_period_ending_reminder(today)
|
||||
print('\n'.join(period_end_reminders_sent))
|
||||
|
||||
overdue_reviews_reminders_sent = send_review_reminder_overdue_assignment(today)
|
||||
print('\n'.join(overdue_reviews_reminders_sent)
|
||||
|
||||
open_reviews_reminders_sent = send_reminder_all_open_reviews(today)
|
||||
print('\n'.join(open_reviews_reminders_sent))
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ from ietf.review.utils import (
|
|||
review_assignments_needing_reviewer_reminder, email_reviewer_reminder,
|
||||
review_assignments_needing_secretary_reminder, email_secretary_reminder,
|
||||
reviewer_rotation_list,
|
||||
send_unavaibility_period_ending_reminder, send_reminder_all_open_reviews)
|
||||
send_unavaibility_period_ending_reminder, send_reminder_all_open_reviews,
|
||||
send_review_reminder_overdue_assignment)
|
||||
from ietf.name.models import ReviewResultName, ReviewRequestStateName, ReviewAssignmentStateName
|
||||
import ietf.group.views
|
||||
from ietf.utils.mail import outbox, empty_outbox
|
||||
|
@ -548,6 +549,26 @@ class ReviewTests(TestCase):
|
|||
self.assertTrue(reviewer.person.name in log[0])
|
||||
self.assertTrue(review_team.acronym in log[0])
|
||||
|
||||
def test_send_review_reminder_overdue_assignment(self):
|
||||
today = datetime.date.today()
|
||||
review_req = ReviewRequestFactory(state_id='assigned', deadline=today - datetime.timedelta(5))
|
||||
reviewer = RoleFactory(name_id='reviewer', group=review_req.team,person__user__username='reviewer').person
|
||||
ReviewAssignmentFactory(review_request=review_req, state_id='assigned', assigned_on=review_req.time, reviewer=reviewer.email_set.first())
|
||||
secretary = RoleFactory(name_id='secr', group=review_req.team, person__user__username='reviewsecretary')
|
||||
|
||||
empty_outbox()
|
||||
log = send_review_reminder_overdue_assignment(today)
|
||||
|
||||
self.assertEqual(len(outbox), 1)
|
||||
self.assertTrue(secretary.person.email_address() in outbox[0]["To"])
|
||||
self.assertEqual(outbox[0]["Subject"], "1 Overdue review for team {}".format(review_req.team.acronym))
|
||||
message = outbox[0].get_payload(decode=True).decode("utf-8")
|
||||
self.assertTrue(review_req.team.acronym + ' has 1 accepted or assigned review overdue by at least 5 days.' in message)
|
||||
self.assertTrue('Review of {} by {}'.format(review_req.doc.name, reviewer.name) in message)
|
||||
self.assertEqual(len(log), 1)
|
||||
self.assertTrue(secretary.person.email_address() in log[0])
|
||||
self.assertTrue('1 overdue review' in log[0])
|
||||
|
||||
def test_send_reminder_all_open_reviews(self):
|
||||
review_req = ReviewRequestFactory(state_id='assigned')
|
||||
reviewer = RoleFactory(name_id='reviewer', group=review_req.team,person__user__username='reviewer').person
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Copyright The IETF Trust 2019, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
MailTrigger = apps.get_model('mailtrigger', 'MailTrigger')
|
||||
Recipient = apps.get_model('mailtrigger', 'Recipient')
|
||||
|
||||
review_reminder_overdue_assignment = MailTrigger.objects.create(
|
||||
slug="review_reminder_overdue_assignment",
|
||||
desc="Recipients for overdue review assignment reminders",
|
||||
)
|
||||
review_reminder_overdue_assignment.to.add(
|
||||
Recipient.objects.get(slug='group_secretaries')
|
||||
)
|
||||
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
MailTrigger = apps.get_model('mailtrigger', 'MailTrigger')
|
||||
MailTrigger.objects.filter(slug='review_reminder_overdue_assignment').delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mailtrigger', '0009_custom_review_complete_mailtriggers'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse)
|
||||
]
|
|
@ -4019,6 +4019,17 @@
|
|||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "review_notify_ad"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [],
|
||||
"desc": "Recipients for overdue review assignment reminders",
|
||||
"to": [
|
||||
"group_secretaries"
|
||||
]
|
||||
},
|
||||
"model": "mailtrigger.mailtrigger",
|
||||
"pk": "review_reminder_overdue_assignment"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
"cc": [],
|
||||
|
|
|
@ -959,6 +959,37 @@ def send_unavaibility_period_ending_reminder(remind_date):
|
|||
return log
|
||||
|
||||
|
||||
def send_review_reminder_overdue_assignment(remind_date):
|
||||
min_overdue_days = 5
|
||||
min_deadline = remind_date + datetime.timedelta(days=min_overdue_days)
|
||||
teams = Group.objects.exclude(reviewteamsettings=None)
|
||||
log = []
|
||||
for team in teams:
|
||||
assignments = ReviewAssignment.objects.filter(
|
||||
state__in=("assigned", "accepted"),
|
||||
review_request__deadline__lte=min_deadline,
|
||||
review_request__team=team,
|
||||
)
|
||||
if not assignments:
|
||||
continue
|
||||
|
||||
(to, cc) = gather_address_lists('review_reminder_overdue_assignment', group=team)
|
||||
domain = Site.objects.get_current().domain
|
||||
subject = "{} Overdue review{} for team {}".format(
|
||||
len(assignments), pluralize(len(assignments)), team.acronym)
|
||||
|
||||
send_mail(None, to, None, subject, "review/review_reminder_overdue_assignment.txt", {
|
||||
"domain": domain,
|
||||
"assignments": assignments,
|
||||
"team": team,
|
||||
"min_overdue_days": min_overdue_days,
|
||||
}, cc=cc)
|
||||
log.append("Emailed reminder to {} about {} overdue reviews in {}".format(
|
||||
to, assignments.count(), team.acronym,
|
||||
))
|
||||
return log
|
||||
|
||||
|
||||
def send_reminder_all_open_reviews(remind_date):
|
||||
log = []
|
||||
# The origin date is arbitrarily chosen, to have a single reference date for "every X days"
|
||||
|
|
14
ietf/templates/review/review_reminder_overdue_assignment.txt
Normal file
14
ietf/templates/review/review_reminder_overdue_assignment.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}
|
||||
Team {{ team.acronym }} has {{ assignments|length }} accepted or assigned review{{ assignments|length|pluralize }} overdue by at least {{ min_overdue_days }} days.
|
||||
|
||||
All reviews overdue by at least {{ min_overdue_days }} days are listed below, including links to mark each of them as no response.
|
||||
|
||||
{% for assignment in assignments %}
|
||||
Review of {{ assignment.review_request.doc }} by {{ assignment.reviewer.person }}
|
||||
https://{{ domain }}{% url 'ietf.doc.views_review.mark_reviewer_assignment_no_response' name=assignment.review_request.doc.name assignment_id=assignment.pk %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
This reminder will be sent daily.
|
||||
|
||||
{% endfilter %}{% endautoescape %}
|
Loading…
Reference in a new issue