mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-01 23:42:17 +02:00
Merge pull request #2369 from cisagov/za/2157-use-creator-email
Ticket #2157: Use creator email rather than submitters for status updates / domain request
This commit is contained in:
commit
1b86322ed1
12 changed files with 99 additions and 40 deletions
|
@ -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');
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ from django.conf import settings
|
|||
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
|
||||
|
@ -17,8 +18,6 @@ from .utility.time_stamped_model import TimeStampedModel
|
|||
from ..utility.email import send_templated_email, EmailSendingError
|
||||
from itertools import chain
|
||||
|
||||
from waffle.decorators import flag_is_active
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -675,34 +674,50 @@ class DomainRequest(TimeStampedModel):
|
|||
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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ from registrar.utility.constants import BranchChoices
|
|||
|
||||
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
|
||||
|
@ -33,29 +34,44 @@ from django_fsm import TransitionNotAllowed
|
|||
@boto3_mocking.patching
|
||||
class TestDomainRequest(TestCase):
|
||||
def setUp(self):
|
||||
|
||||
self.dummy_user, _ = Contact.objects.get_or_create(
|
||||
email="mayor@igorville.com", first_name="Hello", last_name="World"
|
||||
)
|
||||
self.dummy_user_2, _ = User.objects.get_or_create(
|
||||
username="intern@igorville.com", email="intern@igorville.com", 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
|
||||
|
@ -199,7 +215,9 @@ class TestDomainRequest(TestCase):
|
|||
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="mayor@igorville.com"
|
||||
):
|
||||
"""Check if an email was sent after performing an action."""
|
||||
|
||||
with self.subTest(msg=msg, action=action):
|
||||
|
@ -213,19 +231,35 @@ class TestDomainRequest(TestCase):
|
|||
sent_emails = [
|
||||
email
|
||||
for email in MockSESClient.EMAILS_SENT
|
||||
if "mayor@igorville.gov" 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="intern@igorville.com"
|
||||
)
|
||||
|
||||
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."
|
||||
|
@ -239,18 +273,24 @@ class TestDomainRequest(TestCase):
|
|||
|
||||
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."
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue