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, \
|
||||
Nomination, FeedbackLastSeen, TopicFeedbackLastSeen, ReminderDates, \
|
||||
NomCom
|
||||
from ietf.nomcom.management.commands.send_reminders import Command, is_time_to_send
|
||||
from ietf.nomcom.factories import NomComFactory, FeedbackFactory, TopicFactory, \
|
||||
nomcom_kwargs_for_year, provide_private_key_to_test_client, \
|
||||
key
|
||||
from ietf.nomcom.tasks import send_nomcom_reminders_task
|
||||
from ietf.nomcom.utils import get_nomcom_by_year, make_nomineeposition, \
|
||||
get_hash_nominee_position, is_eligible, list_eligible, \
|
||||
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.models import Email, Person
|
||||
from ietf.stats.models import MeetingRegistration
|
||||
|
@ -1207,36 +1207,41 @@ class ReminderTest(TestCase):
|
|||
teardown_test_public_keys_dir(self)
|
||||
super().tearDown()
|
||||
|
||||
def test_is_time_to_send(self):
|
||||
def test_is_time_to_send_reminder(self):
|
||||
self.nomcom.reminder_interval = 4
|
||||
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):
|
||||
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.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.assertTrue(is_time_to_send(self.nomcom,today,today))
|
||||
self.assertTrue(_is_time_to_send_reminder(self.nomcom, today, today))
|
||||
|
||||
def test_command(self):
|
||||
c = Command()
|
||||
messages_before=len(outbox)
|
||||
def test_send_reminders(self):
|
||||
messages_before = len(outbox)
|
||||
self.nomcom.reminder_interval = 3
|
||||
self.nomcom.save()
|
||||
c.handle(None,None)
|
||||
send_reminders()
|
||||
self.assertEqual(len(outbox), messages_before + 2)
|
||||
self.assertIn('nominee1@example.org', outbox[-1]['To'])
|
||||
self.assertIn('please complete', outbox[-1]['Subject'])
|
||||
self.assertIn('nominee1@example.org', outbox[-2]['To'])
|
||||
self.assertIn('please accept', outbox[-2]['Subject'])
|
||||
messages_before=len(outbox)
|
||||
messages_before = len(outbox)
|
||||
self.nomcom.reminder_interval = 4
|
||||
self.nomcom.save()
|
||||
c.handle(None,None)
|
||||
send_reminders()
|
||||
self.assertEqual(len(outbox), messages_before + 1)
|
||||
self.assertIn('nominee2@example.org', outbox[-1]['To'])
|
||||
self.assertIn('please accept', outbox[-1]['Subject'])
|
||||
|
||||
|
||||
def test_remind_accept_view(self):
|
||||
url = reverse('ietf.nomcom.views.send_reminder_mail', kwargs={'year': NOMCOM_YEAR,'type':'accept'})
|
||||
login_testing_unauthorized(self, CHAIR_USER, url)
|
||||
|
@ -3048,3 +3053,10 @@ class ReclassifyFeedbackTests(TestCase):
|
|||
self.assertEqual(fb.type_id, 'junk')
|
||||
self.assertEqual(Feedback.objects.filter(type='read').count(), 0)
|
||||
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,
|
||||
) from err
|
||||
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):
|
||||
for label, crontab in self.crontabs.items():
|
||||
tasks = PeriodicTask.objects.filter(crontab=crontab).order_by(
|
||||
|
|
Loading…
Reference in a new issue