Skip to content

Commit

Permalink
Merge pull request #2369 from cisagov/za/2157-use-creator-email
Browse files Browse the repository at this point in the history
Ticket #2157: Use creator email rather than submitters for status updates / domain request
  • Loading branch information
zandercymatics authored Jun 28, 2024
2 parents e668dc2 + 2cde874 commit 1b86322
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 40 deletions.
4 changes: 4 additions & 0 deletions src/registrar/assets/js/get-gov-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ function initializeWidgetOnList(list, parentId) {
let statusSelect = document.getElementById('id_status');

function moveStatusChangelog(actionNeededReasonFormGroup, statusSelect) {
if (!actionNeededReasonFormGroup || !statusSelect) {
return;
}

let flexContainer = actionNeededReasonFormGroup.querySelector('.flex-container');
let statusChangelog = document.getElementById('dja-status-changelog');

Expand Down
37 changes: 26 additions & 11 deletions src/registrar/models/domain_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.db import models
from django_fsm import FSMField, transition # type: ignore
from django.utils import timezone
from waffle import flag_is_active
from registrar.models.domain import Domain
from registrar.models.federal_agency import FederalAgency
from registrar.models.utility.generic_helper import CreateOrUpdateOrganizationTypeHelper
Expand All @@ -17,8 +18,6 @@
from ..utility.email import send_templated_email, EmailSendingError
from itertools import chain

from waffle.decorators import flag_is_active

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -675,34 +674,50 @@ def delete_and_clean_up_domain(self, called_from):
def _send_status_update_email(
self, new_status, email_template, email_template_subject, send_email=True, bcc_address="", wrap_email=False
):
"""Send a status update email to the submitter.
"""Send a status update email to the creator.
The email goes to the email address that the submitter gave as their
contact information. If there is not submitter information, then do
The email goes to the email address that the creator gave as their
contact information. If there is not creator information, then do
nothing.
If the waffle flag "profile_feature" is active, then this email will be sent to the
domain request creator rather than the submitter
send_email: bool -> Used to bypass the send_templated_email function, in the event
we just want to log that an email would have been sent, rather than actually sending one.
wrap_email: bool -> Wraps emails using `wrap_text_and_preserve_paragraphs` if any given
paragraph exceeds our desired max length (for prettier display).
"""

if self.submitter is None or self.submitter.email is None:
logger.warning(f"Cannot send {new_status} email, no submitter email address.")
recipient = self.creator if flag_is_active(None, "profile_feature") else self.submitter
if recipient is None or recipient.email is None:
logger.warning(
f"Cannot send {new_status} email, no creator email address for domain request with pk: {self.pk}."
f" Name: {self.requested_domain.name}"
if self.requested_domain
else ""
)
return None

if not send_email:
logger.info(f"Email was not sent. Would send {new_status} email: {self.submitter.email}")
logger.info(f"Email was not sent. Would send {new_status} email to: {recipient.email}")
return None

try:
send_templated_email(
email_template,
email_template_subject,
self.submitter.email,
context={"domain_request": self},
recipient.email,
context={
"domain_request": self,
# This is the user that we refer to in the email
"recipient": recipient,
},
bcc_address=bcc_address,
wrap_email=wrap_email,
)
logger.info(f"The {new_status} email sent to: {self.submitter.email}")
logger.info(f"The {new_status} email sent to: {recipient.email}")
except EmailSendingError:
logger.warning("Failed to send confirmation email", exc_info=True)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

We've identified an action that you’ll need to complete before we continue reviewing your .gov domain request.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

We've identified an action that you’ll need to complete before we continue reviewing your .gov domain request.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

We've identified an action that you’ll need to complete before we continue reviewing your .gov domain request.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

We've identified an action that you’ll need to complete before we continue reviewing your .gov domain request.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

Your .gov domain request has been withdrawn and will not be reviewed by our team.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Purpose of your domain:
{{ domain_request.purpose }}

Your contact information:
{% spaceless %}{% include "emails/includes/contact.txt" with contact=domain_request.submitter %}{% endspaceless %}
{% spaceless %}{% include "emails/includes/contact.txt" with contact=recipient %}{% endspaceless %}

Other employees from your organization:{% for other in domain_request.other_contacts.all %}
{% spaceless %}{% include "emails/includes/contact.txt" with contact=other %}{% endspaceless %}
Expand Down
2 changes: 1 addition & 1 deletion src/registrar/templates/emails/status_change_approved.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

Congratulations! Your .gov domain request has been approved.

Expand Down
2 changes: 1 addition & 1 deletion src/registrar/templates/emails/status_change_rejected.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

Your .gov domain request has been rejected.

Expand Down
2 changes: 1 addition & 1 deletion src/registrar/templates/emails/submission_confirmation.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
Hi, {{ domain_request.submitter.first_name }}.
Hi, {{ recipient.first_name }}.

We received your .gov domain request.

Expand Down
80 changes: 60 additions & 20 deletions src/registrar/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

from .common import MockSESClient, less_console_noise, completed_domain_request, set_domain_request_investigators
from django_fsm import TransitionNotAllowed
from waffle.testutils import override_flag


# Test comment for push -- will remove
Expand All @@ -33,29 +34,44 @@
@boto3_mocking.patching
class TestDomainRequest(TestCase):
def setUp(self):

self.dummy_user, _ = Contact.objects.get_or_create(
email="[email protected]", first_name="Hello", last_name="World"
)
self.dummy_user_2, _ = User.objects.get_or_create(
username="[email protected]", email="[email protected]", first_name="Lava", last_name="World"
)
self.started_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.STARTED, name="started.gov"
status=DomainRequest.DomainRequestStatus.STARTED,
name="started.gov",
)
self.submitted_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.SUBMITTED, name="submitted.gov"
status=DomainRequest.DomainRequestStatus.SUBMITTED,
name="submitted.gov",
)
self.in_review_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.IN_REVIEW, name="in-review.gov"
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
name="in-review.gov",
)
self.action_needed_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.ACTION_NEEDED, name="action-needed.gov"
status=DomainRequest.DomainRequestStatus.ACTION_NEEDED,
name="action-needed.gov",
)
self.approved_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.APPROVED, name="approved.gov"
status=DomainRequest.DomainRequestStatus.APPROVED,
name="approved.gov",
)
self.withdrawn_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.WITHDRAWN, name="withdrawn.gov"
status=DomainRequest.DomainRequestStatus.WITHDRAWN,
name="withdrawn.gov",
)
self.rejected_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.REJECTED, name="rejected.gov"
status=DomainRequest.DomainRequestStatus.REJECTED,
name="rejected.gov",
)
self.ineligible_domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.INELIGIBLE, name="ineligible.gov"
status=DomainRequest.DomainRequestStatus.INELIGIBLE,
name="ineligible.gov",
)

# Store all domain request statuses in a variable for ease of use
Expand Down Expand Up @@ -199,7 +215,9 @@ def test_status_fsm_submit_succeed(self):
domain_request.submit()
self.assertEqual(domain_request.status, domain_request.DomainRequestStatus.SUBMITTED)

def check_email_sent(self, domain_request, msg, action, expected_count):
def check_email_sent(
self, domain_request, msg, action, expected_count, expected_content=None, expected_email="[email protected]"
):
"""Check if an email was sent after performing an action."""

with self.subTest(msg=msg, action=action):
Expand All @@ -213,19 +231,35 @@ def check_email_sent(self, domain_request, msg, action, expected_count):
sent_emails = [
email
for email in MockSESClient.EMAILS_SENT
if "[email protected]" in email["kwargs"]["Destination"]["ToAddresses"]
if expected_email in email["kwargs"]["Destination"]["ToAddresses"]
]
self.assertEqual(len(sent_emails), expected_count)

if expected_content:
email_content = sent_emails[0]["kwargs"]["Content"]["Simple"]["Body"]["Text"]["Data"]
self.assertIn(expected_content, email_content)

@override_flag("profile_feature", active=False)
def test_submit_from_started_sends_email(self):
msg = "Create a domain request and submit it and see if email was sent."
domain_request = completed_domain_request()
self.check_email_sent(domain_request, msg, "submit", 1)
domain_request = completed_domain_request(submitter=self.dummy_user, user=self.dummy_user_2)
self.check_email_sent(domain_request, msg, "submit", 1, expected_content="Hello")

@override_flag("profile_feature", active=True)
def test_submit_from_started_sends_email_to_creator(self):
"""Tests if, when the profile feature flag is on, we send an email to the creator"""
msg = "Create a domain request and submit it and see if email was sent when the feature flag is on."
domain_request = completed_domain_request(submitter=self.dummy_user, user=self.dummy_user_2)
self.check_email_sent(
domain_request, msg, "submit", 1, expected_content="Lava", expected_email="[email protected]"
)

def test_submit_from_withdrawn_sends_email(self):
msg = "Create a withdrawn domain request and submit it and see if email was sent."
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.WITHDRAWN)
self.check_email_sent(domain_request, msg, "submit", 1)
domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.WITHDRAWN, submitter=self.dummy_user
)
self.check_email_sent(domain_request, msg, "submit", 1, expected_content="Hello")

def test_submit_from_action_needed_does_not_send_email(self):
msg = "Create a domain request with ACTION_NEEDED status and submit it, check if email was not sent."
Expand All @@ -239,18 +273,24 @@ def test_submit_from_in_review_does_not_send_email(self):

def test_approve_sends_email(self):
msg = "Create a domain request and approve it and see if email was sent."
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
self.check_email_sent(domain_request, msg, "approve", 1)
domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.IN_REVIEW, submitter=self.dummy_user
)
self.check_email_sent(domain_request, msg, "approve", 1, expected_content="Hello")

def test_withdraw_sends_email(self):
msg = "Create a domain request and withdraw it and see if email was sent."
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
self.check_email_sent(domain_request, msg, "withdraw", 1)
domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.IN_REVIEW, submitter=self.dummy_user
)
self.check_email_sent(domain_request, msg, "withdraw", 1, expected_content="Hello")

def test_reject_sends_email(self):
msg = "Create a domain request and reject it and see if email was sent."
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.APPROVED)
self.check_email_sent(domain_request, msg, "reject", 1)
domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.APPROVED, submitter=self.dummy_user
)
self.check_email_sent(domain_request, msg, "reject", 1, expected_content="Hello")

def test_reject_with_prejudice_does_not_send_email(self):
msg = "Create a domain request and reject it with prejudice and see if email was sent."
Expand Down

0 comments on commit 1b86322

Please sign in to comment.