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:
Jennifer Richards 2024-05-15 15:25:15 -03:00 committed by GitHub
parent c9f35987bc
commit c59d6122d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 70 additions and 51 deletions

View file

@ -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
View 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()

View file

@ -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)

View file

@ -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}")

View file

@ -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(