refactor: send_nomcom_reminders via celery task (#7424)
* refactor: send_reminders.py -> celery task * chore: add PeriodicTask * chore: remove management command and tests
This commit is contained in:
parent
c9f35987bc
commit
c59d6122d9
|
@ -1,37 +0,0 @@
|
||||||
# Copyright The IETF Trust 2013-2020, All Rights Reserved
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
|
|
||||||
import syslog
|
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
|
||||||
|
|
||||||
from ietf.nomcom.models import NomCom, NomineePosition
|
|
||||||
from ietf.nomcom.utils import send_accept_reminder_to_nominee,send_questionnaire_reminder_to_nominee
|
|
||||||
from ietf.utils.timezone import date_today
|
|
||||||
|
|
||||||
|
|
||||||
def log(message):
|
|
||||||
syslog.syslog(message)
|
|
||||||
|
|
||||||
def is_time_to_send(nomcom,send_date,nomination_date):
|
|
||||||
if nomcom.reminder_interval:
|
|
||||||
days_passed = (send_date - nomination_date).days
|
|
||||||
return days_passed > 0 and days_passed % nomcom.reminder_interval == 0
|
|
||||||
else:
|
|
||||||
return bool(nomcom.reminderdates_set.filter(date=send_date))
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
|
||||||
help = ("Send acceptance and questionnaire reminders to nominees")
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
|
||||||
for nomcom in NomCom.objects.filter(group__state__slug='active'):
|
|
||||||
nps = NomineePosition.objects.filter(nominee__nomcom=nomcom,nominee__duplicated__isnull=True)
|
|
||||||
for nominee_position in nps.pending():
|
|
||||||
if is_time_to_send(nomcom, date_today(), nominee_position.time.date()):
|
|
||||||
send_accept_reminder_to_nominee(nominee_position)
|
|
||||||
log('Sent accept reminder to %s' % nominee_position.nominee.email.address)
|
|
||||||
for nominee_position in nps.accepted().without_questionnaire_response():
|
|
||||||
if is_time_to_send(nomcom, date_today(), nominee_position.time.date()):
|
|
||||||
send_questionnaire_reminder_to_nominee(nominee_position)
|
|
||||||
log('Sent questionnaire reminder to %s' % nominee_position.nominee.email.address)
|
|
10
ietf/nomcom/tasks.py
Normal file
10
ietf/nomcom/tasks.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright The IETF Trust 2024, All Rights Reserved
|
||||||
|
|
||||||
|
from celery import shared_task
|
||||||
|
|
||||||
|
from .utils import send_reminders
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def send_nomcom_reminders_task():
|
||||||
|
send_reminders()
|
|
@ -40,14 +40,14 @@ from ietf.nomcom.models import NomineePosition, Position, Nominee, \
|
||||||
NomineePositionStateName, Feedback, FeedbackTypeName, \
|
NomineePositionStateName, Feedback, FeedbackTypeName, \
|
||||||
Nomination, FeedbackLastSeen, TopicFeedbackLastSeen, ReminderDates, \
|
Nomination, FeedbackLastSeen, TopicFeedbackLastSeen, ReminderDates, \
|
||||||
NomCom
|
NomCom
|
||||||
from ietf.nomcom.management.commands.send_reminders import Command, is_time_to_send
|
|
||||||
from ietf.nomcom.factories import NomComFactory, FeedbackFactory, TopicFactory, \
|
from ietf.nomcom.factories import NomComFactory, FeedbackFactory, TopicFactory, \
|
||||||
nomcom_kwargs_for_year, provide_private_key_to_test_client, \
|
nomcom_kwargs_for_year, provide_private_key_to_test_client, \
|
||||||
key
|
key
|
||||||
|
from ietf.nomcom.tasks import send_nomcom_reminders_task
|
||||||
from ietf.nomcom.utils import get_nomcom_by_year, make_nomineeposition, \
|
from ietf.nomcom.utils import get_nomcom_by_year, make_nomineeposition, \
|
||||||
get_hash_nominee_position, is_eligible, list_eligible, \
|
get_hash_nominee_position, is_eligible, list_eligible, \
|
||||||
get_eligibility_date, suggest_affiliation, ingest_feedback_email, \
|
get_eligibility_date, suggest_affiliation, ingest_feedback_email, \
|
||||||
decorate_volunteers_with_qualifications
|
decorate_volunteers_with_qualifications, send_reminders, _is_time_to_send_reminder
|
||||||
from ietf.person.factories import PersonFactory, EmailFactory
|
from ietf.person.factories import PersonFactory, EmailFactory
|
||||||
from ietf.person.models import Email, Person
|
from ietf.person.models import Email, Person
|
||||||
from ietf.stats.models import MeetingRegistration
|
from ietf.stats.models import MeetingRegistration
|
||||||
|
@ -1207,36 +1207,41 @@ class ReminderTest(TestCase):
|
||||||
teardown_test_public_keys_dir(self)
|
teardown_test_public_keys_dir(self)
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
def test_is_time_to_send(self):
|
def test_is_time_to_send_reminder(self):
|
||||||
self.nomcom.reminder_interval = 4
|
self.nomcom.reminder_interval = 4
|
||||||
today = date_today()
|
today = date_today()
|
||||||
self.assertTrue(is_time_to_send(self.nomcom,today+datetime.timedelta(days=4),today))
|
self.assertTrue(
|
||||||
|
_is_time_to_send_reminder(self.nomcom, today + datetime.timedelta(days=4), today)
|
||||||
|
)
|
||||||
for delta in range(4):
|
for delta in range(4):
|
||||||
self.assertFalse(is_time_to_send(self.nomcom,today+datetime.timedelta(days=delta),today))
|
self.assertFalse(
|
||||||
|
_is_time_to_send_reminder(
|
||||||
|
self.nomcom, today + datetime.timedelta(days=delta), today
|
||||||
|
)
|
||||||
|
)
|
||||||
self.nomcom.reminder_interval = None
|
self.nomcom.reminder_interval = None
|
||||||
self.assertFalse(is_time_to_send(self.nomcom,today,today))
|
self.assertFalse(_is_time_to_send_reminder(self.nomcom, today, today))
|
||||||
self.nomcom.reminderdates_set.create(date=today)
|
self.nomcom.reminderdates_set.create(date=today)
|
||||||
self.assertTrue(is_time_to_send(self.nomcom,today,today))
|
self.assertTrue(_is_time_to_send_reminder(self.nomcom, today, today))
|
||||||
|
|
||||||
def test_command(self):
|
def test_send_reminders(self):
|
||||||
c = Command()
|
messages_before = len(outbox)
|
||||||
messages_before=len(outbox)
|
|
||||||
self.nomcom.reminder_interval = 3
|
self.nomcom.reminder_interval = 3
|
||||||
self.nomcom.save()
|
self.nomcom.save()
|
||||||
c.handle(None,None)
|
send_reminders()
|
||||||
self.assertEqual(len(outbox), messages_before + 2)
|
self.assertEqual(len(outbox), messages_before + 2)
|
||||||
self.assertIn('nominee1@example.org', outbox[-1]['To'])
|
self.assertIn('nominee1@example.org', outbox[-1]['To'])
|
||||||
self.assertIn('please complete', outbox[-1]['Subject'])
|
self.assertIn('please complete', outbox[-1]['Subject'])
|
||||||
self.assertIn('nominee1@example.org', outbox[-2]['To'])
|
self.assertIn('nominee1@example.org', outbox[-2]['To'])
|
||||||
self.assertIn('please accept', outbox[-2]['Subject'])
|
self.assertIn('please accept', outbox[-2]['Subject'])
|
||||||
messages_before=len(outbox)
|
messages_before = len(outbox)
|
||||||
self.nomcom.reminder_interval = 4
|
self.nomcom.reminder_interval = 4
|
||||||
self.nomcom.save()
|
self.nomcom.save()
|
||||||
c.handle(None,None)
|
send_reminders()
|
||||||
self.assertEqual(len(outbox), messages_before + 1)
|
self.assertEqual(len(outbox), messages_before + 1)
|
||||||
self.assertIn('nominee2@example.org', outbox[-1]['To'])
|
self.assertIn('nominee2@example.org', outbox[-1]['To'])
|
||||||
self.assertIn('please accept', outbox[-1]['Subject'])
|
self.assertIn('please accept', outbox[-1]['Subject'])
|
||||||
|
|
||||||
def test_remind_accept_view(self):
|
def test_remind_accept_view(self):
|
||||||
url = reverse('ietf.nomcom.views.send_reminder_mail', kwargs={'year': NOMCOM_YEAR,'type':'accept'})
|
url = reverse('ietf.nomcom.views.send_reminder_mail', kwargs={'year': NOMCOM_YEAR,'type':'accept'})
|
||||||
login_testing_unauthorized(self, CHAIR_USER, url)
|
login_testing_unauthorized(self, CHAIR_USER, url)
|
||||||
|
@ -3048,3 +3053,10 @@ class ReclassifyFeedbackTests(TestCase):
|
||||||
self.assertEqual(fb.type_id, 'junk')
|
self.assertEqual(fb.type_id, 'junk')
|
||||||
self.assertEqual(Feedback.objects.filter(type='read').count(), 0)
|
self.assertEqual(Feedback.objects.filter(type='read').count(), 0)
|
||||||
self.assertEqual(Feedback.objects.filter(type='junk').count(), 1)
|
self.assertEqual(Feedback.objects.filter(type='junk').count(), 1)
|
||||||
|
|
||||||
|
|
||||||
|
class TaskTests(TestCase):
|
||||||
|
@mock.patch("ietf.nomcom.tasks.send_reminders")
|
||||||
|
def test_send_nomcom_reminders_task(self, mock_send):
|
||||||
|
send_nomcom_reminders_task()
|
||||||
|
self.assertEqual(mock_send.call_count, 1)
|
||||||
|
|
|
@ -747,3 +747,27 @@ def ingest_feedback_email(message: bytes, year: int):
|
||||||
email_original_message=message,
|
email_original_message=message,
|
||||||
) from err
|
) from err
|
||||||
log("Received nomcom email from %s" % feedback.author)
|
log("Received nomcom email from %s" % feedback.author)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_time_to_send_reminder(nomcom, send_date, nomination_date):
|
||||||
|
if nomcom.reminder_interval:
|
||||||
|
days_passed = (send_date - nomination_date).days
|
||||||
|
return days_passed > 0 and days_passed % nomcom.reminder_interval == 0
|
||||||
|
else:
|
||||||
|
return bool(nomcom.reminderdates_set.filter(date=send_date))
|
||||||
|
|
||||||
|
|
||||||
|
def send_reminders():
|
||||||
|
from .models import NomCom, NomineePosition
|
||||||
|
for nomcom in NomCom.objects.filter(group__state__slug="active"):
|
||||||
|
nps = NomineePosition.objects.filter(
|
||||||
|
nominee__nomcom=nomcom, nominee__duplicated__isnull=True
|
||||||
|
)
|
||||||
|
for nominee_position in nps.pending():
|
||||||
|
if _is_time_to_send_reminder(nomcom, date_today(), nominee_position.time.date()):
|
||||||
|
send_accept_reminder_to_nominee(nominee_position)
|
||||||
|
log(f"Sent accept reminder to {nominee_position.nominee.email.address}")
|
||||||
|
for nominee_position in nps.accepted().without_questionnaire_response():
|
||||||
|
if _is_time_to_send_reminder(nomcom, date_today(), nominee_position.time.date()):
|
||||||
|
send_questionnaire_reminder_to_nominee(nominee_position)
|
||||||
|
log(f"Sent questionnaire reminder to {nominee_position.nominee.email.address}")
|
||||||
|
|
|
@ -211,6 +211,16 @@ class Command(BaseCommand):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
PeriodicTask.objects.get_or_create(
|
||||||
|
name="Send NomCom reminders",
|
||||||
|
task="ietf.nomcom.tasks.send_nomcom_reminders_task",
|
||||||
|
defaults=dict(
|
||||||
|
enabled=False,
|
||||||
|
crontab=self.crontabs["daily"],
|
||||||
|
description="Send acceptance and questionnaire reminders to nominees",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def show_tasks(self):
|
def show_tasks(self):
|
||||||
for label, crontab in self.crontabs.items():
|
for label, crontab in self.crontabs.items():
|
||||||
tasks = PeriodicTask.objects.filter(crontab=crontab).order_by(
|
tasks = PeriodicTask.objects.filter(crontab=crontab).order_by(
|
||||||
|
|
Loading…
Reference in a new issue