forked from HHS/TANF-app
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into fix/992-notify-data-file-search-selection…
…-changes
- Loading branch information
Showing
11 changed files
with
234 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
tdrs-backend/tdpservice/email/helpers/account_deactivation_warning.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"""Helper methods for sending emails to users about their account deactivation.""" | ||
from tdpservice.email.email_enums import EmailType | ||
from tdpservice.email.email import automated_email | ||
from datetime import datetime, timedelta, timezone | ||
|
||
|
||
def send_deactivation_warning_email(users, days): | ||
"""Send an email to users that are about to be deactivated.""" | ||
template_path = EmailType.DEACTIVATION_WARNING.value | ||
text_message = f'Your account will be deactivated in {days} days.' | ||
subject = f'Account Deactivation Warning: {days} days remaining' | ||
deactivation_date = datetime.now(timezone.utc) + timedelta(days=days) | ||
|
||
for user in users: | ||
recipient_email = user.email | ||
context = { | ||
'first_name': user.first_name, | ||
'days': days, | ||
'deactivation_date': deactivation_date | ||
} | ||
|
||
logger_context = { | ||
'user_id': user.id, | ||
'object_id': user.id, | ||
'object_repr': user.email | ||
} | ||
|
||
automated_email.delay( | ||
email_path=template_path, | ||
recipient_email=recipient_email, | ||
subject=subject, | ||
email_context=context, | ||
text_message=text_message, | ||
logger_context=logger_context | ||
) |
20 changes: 20 additions & 0 deletions
20
tdrs-backend/tdpservice/email/helpers/test/test_account_deactivation_warnings.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
"""Test functions for email helper.""" | ||
import pytest | ||
|
||
import tdpservice | ||
from tdpservice.email.helpers.account_deactivation_warning import send_deactivation_warning_email | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_send_deactivation_warning_email(mocker, user): | ||
"""Test that the send_deactivation_warning_email function runs.""" | ||
mocker.patch( | ||
'tdpservice.email.helpers.account_deactivation_warning.automated_email.delay', | ||
return_value=None | ||
) | ||
send_deactivation_warning_email([user], 10) | ||
|
||
assert tdpservice.email.email.automated_email.delay.called_once_with( | ||
recipient_email=user.email, | ||
subject='Account Deactivation Warning: 10 days remaining', | ||
) |
23 changes: 23 additions & 0 deletions
23
tdrs-backend/tdpservice/email/templates/account-deactivation-warning.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{% extends 'base.html' %} | ||
{% block content %} | ||
<!-- Body copy --> | ||
<p style="color: #000000;"> | ||
<p>Dear {{ first_name }},</p> | ||
|
||
<p>We noticed that you have not logged into the TANF Data Portal (TDP) for almost 180 days.</p> | ||
|
||
<p>Since your account has been inactive, it’s scheduled to be deactivated in <b>{{ days }} day(s)</b> on <b>{{ deactivation_date }}</b> at <b>5PM EST</b>. However, if you are interested in keeping your account, it’s easy! </p> | ||
|
||
<!-- This link uses descriptive text to inform the user what will happen with the link is tapped. --> | ||
<!-- It also uses inline styles since some email clients won't render embedded styles from the head. --> | ||
<!-- <a href="" style="color: #336a90; text-decoration: underline;">Reset your password now</a> --> | ||
<p><a class="button" href="{{ url }}" | ||
style="background-color:#336a90;border-radius:4px;color:#ffffff;display:inline-block;font-family:sans-serif;font-size:18px;font-weight:bold;line-height:60px;text-align:center;text-decoration:none;width: auto; padding-left: 24px; padding-right: 24px;-webkit-text-size-adjust:none;">Sign in to keep your account active</a></p> | ||
|
||
<b>Need help?</b><br> | ||
We're here for you! Check out the <a href="http://tdp-project-updates.app.cloud.gov/knowledge-center/" target="_blank">Getting Started</a> guide or reach out to the TDP Admin team at <a href="mailto:TANFData@acf.hhs.gov" target="_blank">TANFData@acf.hhs.gov</a>. | ||
|
||
<p>Thank you,</p> | ||
TDP Team | ||
</p> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"""Tasks that are triggered by the scheduler.""" | ||
from __future__ import absolute_import | ||
from tdpservice.users.models import User, AccountApprovalStatusChoices | ||
|
||
from django.utils import timezone | ||
from celery import shared_task | ||
from datetime import datetime, timedelta | ||
import logging | ||
from tdpservice.email.helpers.account_deactivation_warning import send_deactivation_warning_email | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
@shared_task | ||
def check_for_accounts_needing_deactivation_warning(): | ||
"""Check for accounts that need deactivation warning emails.""" | ||
deactivate_in_10_days = users_to_deactivate(10) | ||
deactivate_in_3_days = users_to_deactivate(3) | ||
deactivate_in_1_day = users_to_deactivate(1) | ||
|
||
if deactivate_in_10_days: | ||
send_deactivation_warning_email(deactivate_in_10_days, 10) | ||
if deactivate_in_3_days: | ||
send_deactivation_warning_email(deactivate_in_3_days, 3) | ||
if deactivate_in_1_day: | ||
send_deactivation_warning_email(deactivate_in_1_day, 1) | ||
|
||
def users_to_deactivate(days): | ||
"""Return a list of users that have not logged in in the last {180 - days} days.""" | ||
days = 180 - days | ||
return User.objects.filter( | ||
last_login__lte=datetime.now(tz=timezone.utc) - timedelta(days=days), | ||
last_login__gte=datetime.now(tz=timezone.utc) - timedelta(days=days+1), | ||
account_approval_status=AccountApprovalStatusChoices.APPROVED, | ||
) |
98 changes: 98 additions & 0 deletions
98
tdrs-backend/tdpservice/scheduling/test/test_user_deactivation_warning.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
"""Test functions for deactivated account warnings.""" | ||
from django.utils import timezone | ||
|
||
import pytest | ||
import tdpservice | ||
from datetime import datetime, timedelta | ||
from tdpservice.scheduling.tasks import check_for_accounts_needing_deactivation_warning | ||
from tdpservice.users.models import AccountApprovalStatusChoices | ||
|
||
import logging | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_deactivation_email_10_days(user, mocker): | ||
"""Test that the check_for_accounts_needing_deactivation_warning task runs.""" | ||
mocker.patch( | ||
'tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email', | ||
return_value=None | ||
) | ||
mocker.patch( | ||
'tdpservice.scheduling.tasks.users_to_deactivate', | ||
return_value=[user] | ||
) | ||
|
||
user.last_login = datetime.now(tz=timezone.utc) - timedelta(days=170) | ||
user.first_name = 'UniqueName' | ||
user.save() | ||
check_for_accounts_needing_deactivation_warning() | ||
assert tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email.called_once_with( | ||
users=[user], days=10) | ||
|
||
@pytest.mark.django_db | ||
def test_deactivation_email_3_days(user, mocker): | ||
"""Test that the check_for_accounts_needing_deactivation_warning task runs.""" | ||
mocker.patch( | ||
'tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email', | ||
return_value=None | ||
) | ||
mocker.patch( | ||
'tdpservice.scheduling.tasks.users_to_deactivate', | ||
return_value=[user] | ||
) | ||
|
||
user.last_login = datetime.now(tz=timezone.utc) - timedelta(days=177) | ||
user.first_name = 'UniqueName' | ||
user.save() | ||
check_for_accounts_needing_deactivation_warning() | ||
assert tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email.called_once_with( | ||
users=[user], days=3) | ||
|
||
@pytest.mark.django_db | ||
def test_deactivation_email_1_days(user, mocker): | ||
"""Test that the check_for_accounts_needing_deactivation_warning task runs.""" | ||
mocker.patch( | ||
'tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email', | ||
return_value=None | ||
) | ||
mocker.patch( | ||
'tdpservice.scheduling.tasks.users_to_deactivate', | ||
return_value=[user] | ||
) | ||
|
||
user.last_login = datetime.now(tz=timezone.utc) - timedelta(days=179) | ||
user.first_name = 'UniqueName' | ||
user.save() | ||
check_for_accounts_needing_deactivation_warning() | ||
assert tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email.called_once_with( | ||
users=[user], days=1) | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_no_users_to_warn(user, mocker): | ||
"""Test that the check_for_accounts_needing_deactivation_warning task runs.""" | ||
mocker.patch( | ||
'tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email', | ||
return_value=None | ||
) | ||
mocker.patch( | ||
'tdpservice.scheduling.tasks.users_to_deactivate', | ||
return_value=[user] | ||
) | ||
|
||
user.last_login = datetime.now() - timedelta(days=169) | ||
user.first_name = 'UniqueName' | ||
user.save() | ||
check_for_accounts_needing_deactivation_warning() | ||
tdpservice.email.helpers.account_deactivation_warning.send_deactivation_warning_email.assert_not_called() | ||
|
||
@pytest.mark.django_db | ||
def test_users_to_deactivate(user): | ||
"""Test that the users_to_deactivate function returns the correct users.""" | ||
user.last_login = datetime.now() - timedelta(days=170) | ||
user.first_name = 'UniqueName' | ||
user.account_approval_status = AccountApprovalStatusChoices.APPROVED | ||
user.save() | ||
users = tdpservice.scheduling.tasks.users_to_deactivate(10) | ||
assert users[0].first_name == user.first_name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters