From 3ac7d5f092b42bd9d7d4aa5ad911d6baa70f4e06 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Sun, 2 Jun 2024 16:55:48 -0400 Subject: [PATCH 01/18] add upcoming data deadline notification --- tdrs-backend/tdpservice/email/email_enums.py | 1 + tdrs-backend/tdpservice/email/tasks.py | 78 +++++++++ .../upcoming-submission-deadline.html | 27 ++++ .../test/test_upcoming_deadline_email.py | 148 ++++++++++++++++++ tdrs-backend/tdpservice/settings/common.py | 40 +++++ 5 files changed, 294 insertions(+) create mode 100644 tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html create mode 100644 tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py diff --git a/tdrs-backend/tdpservice/email/email_enums.py b/tdrs-backend/tdpservice/email/email_enums.py index 2f56ee6c5..3b7028681 100644 --- a/tdrs-backend/tdpservice/email/email_enums.py +++ b/tdrs-backend/tdpservice/email/email_enums.py @@ -13,3 +13,4 @@ class EmailType(Enum): REQUEST_DENIED = 'request-denied.html' DEACTIVATION_WARNING = 'account-deactivation-warning.html' ACCOUNT_DEACTIVATED = 'account-deactivated.html' + UPCOMING_SUBMISSION_DEADLINE = 'upcoming-submission-deadline.html' diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 3da03d93d..3167180bd 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -11,6 +11,10 @@ import logging from tdpservice.email.helpers.account_access_requests import send_num_access_requests_email from tdpservice.email.helpers.account_deactivation_warning import send_deactivation_warning_email +from tdpservice.stts.models import STT +from tdpservice.data_files.models import DataFile +from .email import automated_email +from .email_enums import EmailType logger = logging.getLogger(__name__) @@ -69,3 +73,77 @@ def email_admin_num_access_requests(): subject, email_context, ) + + +@shared_task +def send_data_submission_reminder(due_date, reporting_period, fiscal_quarter): + """Send all Data Analysts a reminder to submit if they have not already.""" + def get_fiscal_year(calendar_year, fiscal_quarter): + return calendar_year - 1 if fiscal_quarter == 'Q1' else calendar_year + + now = datetime.now() + fiscal_year = get_fiscal_year(now.year, fiscal_quarter) + + all_locations = STT.objects.all() + + # + reminder_locations = [] + for loc in all_locations: + submitted_sections = DataFile.objects.all().filter( + stt=loc, + year=fiscal_year, + quarter=fiscal_quarter, + # version=?? + ) + required_sections = loc.filenames.keys() + + submitted_all_sections = True + for s in required_sections: + if not submitted_sections.filter(section=s).exists(): + submitted_all_sections = False + + if not submitted_all_sections: + reminder_locations.append(loc) + + # + # locations_with_no_submission_for_data_period = all_locations.filter() # -> ? + # spike ticket for improvement and/or iterate + + template_path = EmailType.UPCOMING_SUBMISSION_DEADLINE.value + text_message = 'Your datafiles are due in five days.' + subject = f'Upcoming submission deadline: {due_date}' + + for loc in reminder_locations: + recipients = User.objects.filter( + stt=loc, + account_approval_status=AccountApprovalStatusChoices.APPROVED, + groups=Group.objects.get(name='Data Analyst') + ) + + for rec in recipients: + context = { + 'first_name': rec.first_name, + 'fiscal_year': fiscal_year, + 'fiscal_quarter': fiscal_quarter, + 'submission_deadline': due_date, + 'url': settings.FRONTEND_BASE_URL, + 'subject': subject + } + + logger_context = { + 'user_id': rec.id, + 'object_id': rec.id, + 'object_repr': rec.username, + } + + automated_email( + email_path=template_path, + recipient_email=rec.username, + subject=subject, + email_context=context, + text_message=text_message, + logger_context=logger_context + ) + + if len(recipients) == 0: + print(f'{loc.name} needs a reminder email but has no recipients') diff --git a/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html new file mode 100644 index 000000000..72ac24b57 --- /dev/null +++ b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html @@ -0,0 +1,27 @@ +{% extends 'base.html' %} +{% block content %} + + +

Hello {{ first_name }},

+

This is a friendly reminder that your data files are due in 5 days.

+

Please sign in to the TANF Data Portal +to upload and submit data files for Fiscal Year {{ fiscal_year }} - {{ fiscal_quarter}} by {{ submission_deadline }}.

+ + + + +

Submit your data files

+ +Need help?
+We're here for you! Check out the TDP Knowledge Center for specific gudiance on Submitting Data Files and Frequently Asked Questions. +

+TDP is now the only method for data submissions; you should not be submitting data through SFTP or Cyberfusion. Reach out to the TDP support team by replying to this email and we will follow up with you directly.

+

Thank you,

+

The TDP Team

+ + + + + + +{% endblock %} diff --git a/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py b/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py new file mode 100644 index 000000000..eb40906c3 --- /dev/null +++ b/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py @@ -0,0 +1,148 @@ +"""Test function for sending upcoming data deadline reminders.""" +import pytest +from django.core import mail +from tdpservice.email.tasks import send_data_submission_reminder +from datetime import datetime +from django.contrib.auth.models import Group + +from tdpservice.stts.models import STT +from tdpservice.users.models import User +from tdpservice.data_files.models import DataFile + + +@pytest.mark.parametrize('due_date, reporting_period, fiscal_quarter', [ + ('February 14', 'Oct - Dec', 'Q1'), + ('May 15th', 'Jan - Mar', 'Q2'), + ('August 14th', 'Apr - Jun', 'Q3'), + ('November 14th', 'Jul - Sep', 'Q4'), +]) +@pytest.mark.django_db +def test_upcoming_deadline_sends_no_sections_submitted( + due_date, reporting_period, fiscal_quarter): + """Test that the send_deactivation_warning_email function runs when no sections have been submitted.""" + + stt = STT.objects.create( + name='Arkansas', + filenames={ + "Active Case Data": "test-filename.txt", + "Closed Case Data": "test-filename-closed.txt", + } + ) + + data_analyst = User.objects.create( + username='test@email.com', + stt=stt, + account_approval_status='Approved' + ) + data_analyst.groups.add(Group.objects.get(name='Data Analyst')) + data_analyst.save() + + send_data_submission_reminder(due_date, reporting_period, fiscal_quarter) + + assert len(mail.outbox) == 1 + assert mail.outbox[0].subject == f"Upcoming submission deadline: {due_date}" + + +@pytest.mark.parametrize('due_date, reporting_period, fiscal_quarter', [ + ('February 14', 'Oct - Dec', 'Q1'), + ('May 15th', 'Jan - Mar', 'Q2'), + ('August 14th', 'Apr - Jun', 'Q3'), + ('November 14th', 'Jul - Sep', 'Q4'), +]) +@pytest.mark.django_db +def test_upcoming_deadline_sends_some_sections_submitted( + due_date, reporting_period, fiscal_quarter): + """Test that the send_deactivation_warning_email function runs when some sections have been submitted.""" + + stt = STT.objects.create( + name='Arkansas', + filenames={ + "Active Case Data": "test-filename.txt", + "Closed Case Data": "test-filename-closed.txt", + } + ) + + data_analyst = User.objects.create( + username='test@email.com', + stt=stt, + account_approval_status='Approved' + ) + data_analyst.groups.add(Group.objects.get(name='Data Analyst')) + data_analyst.save() + + now = datetime.now() + fiscal_year = now.year - 1 if fiscal_quarter == 'Q1' else now.year + + data_file = DataFile.create_new_version({ + "section": 'Active Case Data', + "quarter": fiscal_quarter, + "year": fiscal_year, + "stt": stt, + "user": data_analyst, + }) + + send_data_submission_reminder(due_date, reporting_period, fiscal_quarter) + + assert len(mail.outbox) == 1 + assert mail.outbox[0].subject == f"Upcoming submission deadline: {due_date}" + + +"""Test function for sending upcoming data deadline reminders.""" +import pytest +from django.core import mail +from tdpservice.email.tasks import send_data_submission_reminder +from django.contrib.auth.models import Group + +from tdpservice.stts.models import STT +from tdpservice.users.models import User + + +@pytest.mark.parametrize('due_date, reporting_period, fiscal_quarter', [ + ('February 14', 'Oct - Dec', 'Q1'), + ('May 15th', 'Jan - Mar', 'Q2'), + ('August 14th', 'Apr - Jun', 'Q3'), + ('November 14th', 'Jul - Sep', 'Q4'), +]) +@pytest.mark.django_db +def test_upcoming_deadline_no_send_when_all_sections_complete( + due_date, reporting_period, fiscal_quarter): + """Test that the send_deactivation_warning_email function does not run when all sections have been submitted.""" + + stt = STT.objects.create( + name='Arkansas', + filenames={ + "Active Case Data": "test-filename.txt", + "Closed Case Data": "test-filename-closed.txt", + } + ) + + data_analyst = User.objects.create( + username='test@email.com', + stt=stt, + account_approval_status='Approved' + ) + data_analyst.groups.add(Group.objects.get(name='Data Analyst')) + data_analyst.save() + + now = datetime.now() + fiscal_year = now.year - 1 if fiscal_quarter == 'Q1' else now.year + + data_file = DataFile.create_new_version({ + "section": 'Active Case Data', + "quarter": fiscal_quarter, + "year": fiscal_year, + "stt": stt, + "user": data_analyst, + }) + + data_file2 = DataFile.create_new_version({ + "section": 'Closed Case Data', + "quarter": fiscal_quarter, + "year": fiscal_year, + "stt": stt, + "user": data_analyst, + }) + + send_data_submission_reminder(due_date, reporting_period, fiscal_quarter) + + assert len(mail.outbox) == 0 diff --git a/tdrs-backend/tdpservice/settings/common.py b/tdrs-backend/tdpservice/settings/common.py index 6ca924fe0..13875a52d 100644 --- a/tdrs-backend/tdpservice/settings/common.py +++ b/tdrs-backend/tdpservice/settings/common.py @@ -489,6 +489,46 @@ class Common(Configuration): 'task': 'tdpservice.email.tasks.email_admin_num_access_requests', 'schedule': crontab(minute='0', hour='1', day_of_week='*', day_of_month='*', month_of_year='*'), # Every day at 1am UTC (9pm EST) }, + 'Email Data Analyst Q1 Upcoming Submission Deadline Reminder': { + 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + 'schedule': crontab(month_of_year='2', day_of_month='9', hour='13', minute='0'), + # 'schedule': crontab(minute='*/3'), + 'kwargs': { + 'due_date': 'February 14th', + 'reporting_period': 'Oct - Dec', + 'fiscal_quarter': 'Q1', + } + }, + 'Email Data Analyst Q2 Upcoming Submission Deadline Reminder': { + 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + 'schedule': crontab(month_of_year='5', day_of_month='10', hour='13', minute='0'), + # 'schedule': crontab(minute='*/3'), + 'kwargs': { + 'due_date': 'May 15th', + 'reporting_period': 'Jan - Mar', + 'fiscal_quarter': 'Q2', + } + }, + 'Email Data Analyst Q3 Upcoming Submission Deadline Reminder': { + 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + 'schedule': crontab(month_of_year='8', day_of_month='9', hour='13', minute='0'), + # 'schedule': crontab(minute='*/3'), + 'kwargs': { + 'due_date': 'August 14th', + 'reporting_period': 'Apr - Jun', + 'fiscal_quarter': 'Q3', + } + }, + 'Email Data Analyst Q4 Upcoming Submission Deadline Reminder': { + 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + 'schedule': crontab(month_of_year='11', day_of_month='9', hour='13', minute='0'), + # 'schedule': crontab(minute='*/3'), + 'kwargs': { + 'due_date': 'November 14th', + 'reporting_period': 'Jul - Sep', + 'fiscal_quarter': 'Q4', + } + }, } CYPRESS_TOKEN = os.getenv('CYPRESS_TOKEN', None) From 24bceb9d5e6794a7e6b76f3bcb20790f2f8739f5 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Sun, 2 Jun 2024 17:06:10 -0400 Subject: [PATCH 02/18] lint --- .../test/test_upcoming_deadline_email.py | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py b/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py index eb40906c3..b6511505d 100644 --- a/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py +++ b/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py @@ -1,10 +1,9 @@ """Test function for sending upcoming data deadline reminders.""" import pytest +from datetime import datetime from django.core import mail from tdpservice.email.tasks import send_data_submission_reminder -from datetime import datetime from django.contrib.auth.models import Group - from tdpservice.stts.models import STT from tdpservice.users.models import User from tdpservice.data_files.models import DataFile @@ -20,7 +19,6 @@ def test_upcoming_deadline_sends_no_sections_submitted( due_date, reporting_period, fiscal_quarter): """Test that the send_deactivation_warning_email function runs when no sections have been submitted.""" - stt = STT.objects.create( name='Arkansas', filenames={ @@ -53,7 +51,6 @@ def test_upcoming_deadline_sends_no_sections_submitted( def test_upcoming_deadline_sends_some_sections_submitted( due_date, reporting_period, fiscal_quarter): """Test that the send_deactivation_warning_email function runs when some sections have been submitted.""" - stt = STT.objects.create( name='Arkansas', filenames={ @@ -73,7 +70,7 @@ def test_upcoming_deadline_sends_some_sections_submitted( now = datetime.now() fiscal_year = now.year - 1 if fiscal_quarter == 'Q1' else now.year - data_file = DataFile.create_new_version({ + _ = DataFile.create_new_version({ "section": 'Active Case Data', "quarter": fiscal_quarter, "year": fiscal_year, @@ -87,16 +84,6 @@ def test_upcoming_deadline_sends_some_sections_submitted( assert mail.outbox[0].subject == f"Upcoming submission deadline: {due_date}" -"""Test function for sending upcoming data deadline reminders.""" -import pytest -from django.core import mail -from tdpservice.email.tasks import send_data_submission_reminder -from django.contrib.auth.models import Group - -from tdpservice.stts.models import STT -from tdpservice.users.models import User - - @pytest.mark.parametrize('due_date, reporting_period, fiscal_quarter', [ ('February 14', 'Oct - Dec', 'Q1'), ('May 15th', 'Jan - Mar', 'Q2'), @@ -107,7 +94,6 @@ def test_upcoming_deadline_sends_some_sections_submitted( def test_upcoming_deadline_no_send_when_all_sections_complete( due_date, reporting_period, fiscal_quarter): """Test that the send_deactivation_warning_email function does not run when all sections have been submitted.""" - stt = STT.objects.create( name='Arkansas', filenames={ @@ -127,7 +113,7 @@ def test_upcoming_deadline_no_send_when_all_sections_complete( now = datetime.now() fiscal_year = now.year - 1 if fiscal_quarter == 'Q1' else now.year - data_file = DataFile.create_new_version({ + _ = DataFile.create_new_version({ "section": 'Active Case Data', "quarter": fiscal_quarter, "year": fiscal_year, @@ -135,7 +121,7 @@ def test_upcoming_deadline_no_send_when_all_sections_complete( "user": data_analyst, }) - data_file2 = DataFile.create_new_version({ + _ = DataFile.create_new_version({ "section": 'Closed Case Data', "quarter": fiscal_quarter, "year": fiscal_year, From fd351e30b3324556eb61d524fadbefca13c1bfd9 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Mon, 3 Jun 2024 13:52:15 -0400 Subject: [PATCH 03/18] query efficiency --- tdrs-backend/tdpservice/email/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 3167180bd..c9d6c5e21 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -94,12 +94,12 @@ def get_fiscal_year(calendar_year, fiscal_quarter): year=fiscal_year, quarter=fiscal_quarter, # version=?? - ) + ).values_list('section', flat=True).distinct() required_sections = loc.filenames.keys() submitted_all_sections = True for s in required_sections: - if not submitted_sections.filter(section=s).exists(): + if s not in submitted_sections: submitted_all_sections = False if not submitted_all_sections: From c34dd0411dc8761a466344707ca6c6a5395437ec Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Mon, 3 Jun 2024 14:52:13 -0400 Subject: [PATCH 04/18] query efficiency --- tdrs-backend/tdpservice/email/tasks.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index c9d6c5e21..dd5fbed18 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -88,13 +88,13 @@ def get_fiscal_year(calendar_year, fiscal_quarter): # reminder_locations = [] + year_quarter_files = DataFile.objects.all().filter( + year=fiscal_year, + quarter=fiscal_quarter, + ) + for loc in all_locations: - submitted_sections = DataFile.objects.all().filter( - stt=loc, - year=fiscal_year, - quarter=fiscal_quarter, - # version=?? - ).values_list('section', flat=True).distinct() + submitted_sections = year_quarter_files.filter(stt=loc).values_list('section', flat=True).distinct() required_sections = loc.filenames.keys() submitted_all_sections = True From cb8b37a81a24402819a39062521ab9efb61cad1f Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Mon, 3 Jun 2024 14:52:19 -0400 Subject: [PATCH 05/18] clarity comment --- tdrs-backend/tdpservice/settings/common.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tdrs-backend/tdpservice/settings/common.py b/tdrs-backend/tdpservice/settings/common.py index 13875a52d..4a12a855c 100644 --- a/tdrs-backend/tdpservice/settings/common.py +++ b/tdrs-backend/tdpservice/settings/common.py @@ -491,6 +491,7 @@ class Common(Configuration): }, 'Email Data Analyst Q1 Upcoming Submission Deadline Reminder': { 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + # Feb 9 at 1pm UTC (9am EST) 'schedule': crontab(month_of_year='2', day_of_month='9', hour='13', minute='0'), # 'schedule': crontab(minute='*/3'), 'kwargs': { @@ -501,6 +502,7 @@ class Common(Configuration): }, 'Email Data Analyst Q2 Upcoming Submission Deadline Reminder': { 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + # May 10 at 1pm UTC (9am EST) 'schedule': crontab(month_of_year='5', day_of_month='10', hour='13', minute='0'), # 'schedule': crontab(minute='*/3'), 'kwargs': { @@ -511,6 +513,7 @@ class Common(Configuration): }, 'Email Data Analyst Q3 Upcoming Submission Deadline Reminder': { 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + # Aug 9 at 1pm UTC (9am EST) 'schedule': crontab(month_of_year='8', day_of_month='9', hour='13', minute='0'), # 'schedule': crontab(minute='*/3'), 'kwargs': { @@ -521,6 +524,7 @@ class Common(Configuration): }, 'Email Data Analyst Q4 Upcoming Submission Deadline Reminder': { 'task': 'tdpservice.email.tasks.send_data_submission_reminder', + # Nov 9 at 1pm UTC (9am EST) 'schedule': crontab(month_of_year='11', day_of_month='9', hour='13', minute='0'), # 'schedule': crontab(minute='*/3'), 'kwargs': { From e1296c74c65a59898005546a374afb13435e79b8 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Mon, 3 Jun 2024 14:55:54 -0400 Subject: [PATCH 06/18] add no recips logentry --- tdrs-backend/tdpservice/email/tasks.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index dd5fbed18..20216ba68 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -13,7 +13,7 @@ from tdpservice.email.helpers.account_deactivation_warning import send_deactivation_warning_email from tdpservice.stts.models import STT from tdpservice.data_files.models import DataFile -from .email import automated_email +from .email import automated_email, log from .email_enums import EmailType @@ -146,4 +146,13 @@ def get_fiscal_year(calendar_year, fiscal_quarter): ) if len(recipients) == 0: - print(f'{loc.name} needs a reminder email but has no recipients') + system_user, created = User.objects.get_or_create(username='system') + if created: + log('Created reserved system user.') + + logger_context = { + 'user_id': system_user.pk, + 'object_id': loc.id, + 'object_repr': loc.name, + } + log(f"{loc.name} has no recipients for data submission deadline reminder.", logger_context=logger_context) From 29bc6697c199bdeae7f3b9f5dc70bde376f24449 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Mon, 3 Jun 2024 17:20:00 -0400 Subject: [PATCH 07/18] rm comments --- tdrs-backend/tdpservice/email/tasks.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 20216ba68..fe0aafd22 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -86,7 +86,6 @@ def get_fiscal_year(calendar_year, fiscal_quarter): all_locations = STT.objects.all() - # reminder_locations = [] year_quarter_files = DataFile.objects.all().filter( year=fiscal_year, @@ -105,13 +104,9 @@ def get_fiscal_year(calendar_year, fiscal_quarter): if not submitted_all_sections: reminder_locations.append(loc) - # - # locations_with_no_submission_for_data_period = all_locations.filter() # -> ? - # spike ticket for improvement and/or iterate - template_path = EmailType.UPCOMING_SUBMISSION_DEADLINE.value - text_message = 'Your datafiles are due in five days.' - subject = f'Upcoming submission deadline: {due_date}' + text_message = f'Your datafiles are due by {due_date}.' + subject = f'Action Requested: Please submit your {TANF/SSP} data files' for loc in reminder_locations: recipients = User.objects.filter( From 5c52b060283c874820189cce844f3d5f30767781 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Mon, 3 Jun 2024 17:22:53 -0400 Subject: [PATCH 08/18] update email subject to include ssp/tanf --- tdrs-backend/tdpservice/email/tasks.py | 4 +++- .../tdpservice/email/test/test_upcoming_deadline_email.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index fe0aafd22..4abd58c89 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -106,9 +106,11 @@ def get_fiscal_year(calendar_year, fiscal_quarter): template_path = EmailType.UPCOMING_SUBMISSION_DEADLINE.value text_message = f'Your datafiles are due by {due_date}.' - subject = f'Action Requested: Please submit your {TANF/SSP} data files' for loc in reminder_locations: + tanf_ssp_label = 'SSP' if loc.ssp else 'TANF' + subject = f'Action Requested: Please submit your {tanf_ssp_label} data files' + recipients = User.objects.filter( stt=loc, account_approval_status=AccountApprovalStatusChoices.APPROVED, diff --git a/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py b/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py index b6511505d..1c7b224dd 100644 --- a/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py +++ b/tdrs-backend/tdpservice/email/test/test_upcoming_deadline_email.py @@ -38,7 +38,7 @@ def test_upcoming_deadline_sends_no_sections_submitted( send_data_submission_reminder(due_date, reporting_period, fiscal_quarter) assert len(mail.outbox) == 1 - assert mail.outbox[0].subject == f"Upcoming submission deadline: {due_date}" + assert mail.outbox[0].subject == "Action Requested: Please submit your TANF data files" @pytest.mark.parametrize('due_date, reporting_period, fiscal_quarter', [ @@ -81,7 +81,7 @@ def test_upcoming_deadline_sends_some_sections_submitted( send_data_submission_reminder(due_date, reporting_period, fiscal_quarter) assert len(mail.outbox) == 1 - assert mail.outbox[0].subject == f"Upcoming submission deadline: {due_date}" + assert mail.outbox[0].subject == "Action Requested: Please submit your TANF data files" @pytest.mark.parametrize('due_date, reporting_period, fiscal_quarter', [ From 9d9b1412f99154adc319152f77101e8ea9087c08 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Mon, 3 Jun 2024 17:26:36 -0400 Subject: [PATCH 09/18] SSP -> TANF and SSP --- tdrs-backend/tdpservice/email/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 4abd58c89..92ff0b9e8 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -108,7 +108,7 @@ def get_fiscal_year(calendar_year, fiscal_quarter): text_message = f'Your datafiles are due by {due_date}.' for loc in reminder_locations: - tanf_ssp_label = 'SSP' if loc.ssp else 'TANF' + tanf_ssp_label = 'TANF and SSP' if loc.ssp else 'TANF' subject = f'Action Requested: Please submit your {tanf_ssp_label} data files' recipients = User.objects.filter( From 3be46db469d66c6fb7c5dc6a223312e6b22ebdaf Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 4 Jun 2024 11:35:29 -0400 Subject: [PATCH 10/18] query efficiency --- tdrs-backend/tdpservice/email/tasks.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 92ff0b9e8..480c971f7 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -107,15 +107,16 @@ def get_fiscal_year(calendar_year, fiscal_quarter): template_path = EmailType.UPCOMING_SUBMISSION_DEADLINE.value text_message = f'Your datafiles are due by {due_date}.' + all_data_analysts = User.objects.all().filter( + account_approval_status=AccountApprovalStatusChoices.APPROVED, + groups=Group.objects.get(name='Data Analyst') + ) + for loc in reminder_locations: tanf_ssp_label = 'TANF and SSP' if loc.ssp else 'TANF' subject = f'Action Requested: Please submit your {tanf_ssp_label} data files' - recipients = User.objects.filter( - stt=loc, - account_approval_status=AccountApprovalStatusChoices.APPROVED, - groups=Group.objects.get(name='Data Analyst') - ) + recipients = all_data_analysts.filter(stt=loc) for rec in recipients: context = { From 6c50bdc434cf67ac2a2ffd2e61617dcf354691f6 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 11 Jun 2024 12:14:38 -0400 Subject: [PATCH 11/18] abs import --- tdrs-backend/tdpservice/email/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 480c971f7..972c7eef6 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -13,8 +13,8 @@ from tdpservice.email.helpers.account_deactivation_warning import send_deactivation_warning_email from tdpservice.stts.models import STT from tdpservice.data_files.models import DataFile -from .email import automated_email, log -from .email_enums import EmailType +from tdpservice.email import automated_email, log +from tdpservice.email.email_enums import EmailType logger = logging.getLogger(__name__) From cb82c56dbd882af6ace3d1caf05720cc0c340d03 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 11 Jun 2024 12:16:15 -0400 Subject: [PATCH 12/18] move calendar_to_fiscal to util --- tdrs-backend/tdpservice/email/tasks.py | 5 ++--- tdrs-backend/tdpservice/parsers/util.py | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 972c7eef6..15b255ad8 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -15,6 +15,7 @@ from tdpservice.data_files.models import DataFile from tdpservice.email import automated_email, log from tdpservice.email.email_enums import EmailType +from tdpservice.parsers.util import calendar_to_fiscal logger = logging.getLogger(__name__) @@ -78,11 +79,9 @@ def email_admin_num_access_requests(): @shared_task def send_data_submission_reminder(due_date, reporting_period, fiscal_quarter): """Send all Data Analysts a reminder to submit if they have not already.""" - def get_fiscal_year(calendar_year, fiscal_quarter): - return calendar_year - 1 if fiscal_quarter == 'Q1' else calendar_year now = datetime.now() - fiscal_year = get_fiscal_year(now.year, fiscal_quarter) + fiscal_year = calendar_to_fiscal(now.year, fiscal_quarter) all_locations = STT.objects.all() diff --git a/tdrs-backend/tdpservice/parsers/util.py b/tdrs-backend/tdpservice/parsers/util.py index 287c58cff..839f9f142 100644 --- a/tdrs-backend/tdpservice/parsers/util.py +++ b/tdrs-backend/tdpservice/parsers/util.py @@ -130,6 +130,11 @@ def fiscal_to_calendar(year, fiscal_quarter): ind_qtr = array.index(int_qtr) # get the index so we can easily wrap-around end of array return year, "Q{}".format(array[ind_qtr - 1]) # return the previous quarter + +def calendar_to_fiscal(calendar_year, fiscal_quarter): + return calendar_year - 1 if fiscal_quarter == 'Q1' else calendar_year + + def transform_to_months(quarter): """Return a list of months in a quarter depending the quarter's format.""" match quarter: From dd65bbe0e4761187883da905228539010f59ecd3 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 11 Jun 2024 14:35:21 -0400 Subject: [PATCH 13/18] fix tests --- tdrs-backend/tdpservice/email/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 15b255ad8..84e5f1415 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -13,7 +13,7 @@ from tdpservice.email.helpers.account_deactivation_warning import send_deactivation_warning_email from tdpservice.stts.models import STT from tdpservice.data_files.models import DataFile -from tdpservice.email import automated_email, log +from tdpservice.email.email import automated_email, log from tdpservice.email.email_enums import EmailType from tdpservice.parsers.util import calendar_to_fiscal From 2cfcfb30ef5c47b6965d13934a6c5b78840e3383 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 11 Jun 2024 14:45:56 -0400 Subject: [PATCH 14/18] lint --- tdrs-backend/tdpservice/email/tasks.py | 1 - tdrs-backend/tdpservice/parsers/util.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index 84e5f1415..73b2158e9 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -79,7 +79,6 @@ def email_admin_num_access_requests(): @shared_task def send_data_submission_reminder(due_date, reporting_period, fiscal_quarter): """Send all Data Analysts a reminder to submit if they have not already.""" - now = datetime.now() fiscal_year = calendar_to_fiscal(now.year, fiscal_quarter) diff --git a/tdrs-backend/tdpservice/parsers/util.py b/tdrs-backend/tdpservice/parsers/util.py index 839f9f142..76c29dd37 100644 --- a/tdrs-backend/tdpservice/parsers/util.py +++ b/tdrs-backend/tdpservice/parsers/util.py @@ -132,6 +132,7 @@ def fiscal_to_calendar(year, fiscal_quarter): def calendar_to_fiscal(calendar_year, fiscal_quarter): + """Decrement the calendar year if in Q1.""" return calendar_year - 1 if fiscal_quarter == 'Q1' else calendar_year From ed8f67e8acb7dff5c1bd9f6d45013f6a7571a960 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 16 Jul 2024 09:43:31 -0400 Subject: [PATCH 15/18] dynamic url to email template --- .../email/templates/upcoming-submission-deadline.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html index 72ac24b57..55519c07a 100644 --- a/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html +++ b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html @@ -4,13 +4,13 @@

Hello {{ first_name }},

This is a friendly reminder that your data files are due in 5 days.

-

Please sign in to the TANF Data Portal +

Please sign in to the TANF Data Portal to upload and submit data files for Fiscal Year {{ fiscal_year }} - {{ fiscal_quarter}} by {{ submission_deadline }}.

-

Submit your data files

+

Submit your data files

Need help?
We're here for you! Check out the TDP Knowledge Center for specific gudiance on Submitting Data Files and Frequently Asked Questions. From 57ca5f621fe888de06d80743188279f71c4d2006 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 16 Jul 2024 09:46:05 -0400 Subject: [PATCH 16/18] no-reply language change --- .../email/templates/upcoming-submission-deadline.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html index 55519c07a..59f0c5235 100644 --- a/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html +++ b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html @@ -15,7 +15,7 @@ Need help?
We're here for you! Check out the TDP Knowledge Center for specific gudiance on Submitting Data Files and Frequently Asked Questions.

-TDP is now the only method for data submissions; you should not be submitting data through SFTP or Cyberfusion. Reach out to the TDP support team by replying to this email and we will follow up with you directly.

+TDP is now the only method for data submissions; you should not be submitting data through SFTP or Cyberfusion. Reach out to the TDP support team if you have any questions or concerns, and we will follow up with you directly.

Thank you,

The TDP Team

From 2618dd612f5651037669e125e591e270bda81fd9 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 16 Jul 2024 09:48:50 -0400 Subject: [PATCH 17/18] turn down log sensitivity in dev --- tdrs-backend/tdpservice/email/tasks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tdrs-backend/tdpservice/email/tasks.py b/tdrs-backend/tdpservice/email/tasks.py index aaf46c0e4..089ea4e8d 100644 --- a/tdrs-backend/tdpservice/email/tasks.py +++ b/tdrs-backend/tdpservice/email/tasks.py @@ -157,4 +157,7 @@ def send_data_submission_reminder(due_date, reporting_period, fiscal_quarter): 'object_id': loc.id, 'object_repr': loc.name, } - log(f"{loc.name} has no recipients for data submission deadline reminder.", logger_context=logger_context) + log( + f"{loc.name} has no recipients for data submission deadline reminder.", + logger_context=logger_context if not settings.DEBUG else None + ) From 05dbc4669a62e3aaabc161691df971120bddd935 Mon Sep 17 00:00:00 2001 From: Jan Timpe Date: Tue, 16 Jul 2024 12:14:31 -0400 Subject: [PATCH 18/18] email reply language --- .../email/templates/upcoming-submission-deadline.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html index 59f0c5235..191e099cd 100644 --- a/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html +++ b/tdrs-backend/tdpservice/email/templates/upcoming-submission-deadline.html @@ -15,7 +15,7 @@ Need help?
We're here for you! Check out the TDP Knowledge Center for specific gudiance on Submitting Data Files and Frequently Asked Questions.

-TDP is now the only method for data submissions; you should not be submitting data through SFTP or Cyberfusion. Reach out to the TDP support team if you have any questions or concerns, and we will follow up with you directly.

+TDP is now the only method for data submissions; you should not be submitting data through SFTP or Cyberfusion. Please reach out to the TDP support team at TANFData@acf.hhs.gov if you have any questions or need assistance.

Thank you,

The TDP Team