From ed653e4562a099d805f9b1e35c37aa631983d782 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 11:11:23 -0600
Subject: [PATCH 43/71] add pr suggestion for spacing
---
.../django/admin/includes/detail_table_fieldset.html | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
index 2aa5c0a60..f0ff7be3f 100644
--- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
+++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
@@ -145,10 +145,10 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% block field_other %}
{% if field.field.name == "action_needed_reason_email" %}
- {{ field.field }}
-
No email will be sent.
+ {{ field.field }}
+
No email will be sent.
{% else %}
- {{ field.field }}
+ {{ field.field }}
{% endif %}
{% endblock field_other %}
From 025a128baef4c7a3fc08113df5a529d3ddd491c8 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 11:54:27 -0600
Subject: [PATCH 44/71] Refactor
---
src/registrar/admin.py | 68 +++++++++++-------------
src/registrar/assets/js/get-gov-admin.js | 67 ++++++++++-------------
2 files changed, 58 insertions(+), 77 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 7d5708e62..8f00ab519 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1731,46 +1731,37 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
if not change:
return super().save_model(request, obj, form, change)
- # == Handle non-status changes == #
# Get the original domain request from the database.
original_obj = models.DomainRequest.objects.get(pk=obj.pk)
- # If the reason is in a state where we can send out an email,
- # set the email to a default one if a custom email isn't provided.
- if obj.action_needed_reason and obj.action_needed_reason != obj.ActionNeededReasons.OTHER:
- obj = self._handle_existing_action_needed_reason_email(obj, original_obj)
- else:
+ # == Handle action_needed_reason == #
+ # Store the email that was sent out if one was sent and it isn't saved to a variable yet
+ if not obj.action_needed_reason or obj.action_needed_reason == obj.ActionNeededReasons.OTHER:
+ # Reset the action needed email to none if we don't send out an email.
obj.action_needed_reason_email = None
+ else:
+ # We send out an email -- store which one we send out.
+ # Set the email to a default one if a custom email isn't provided.
+ default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason)
+ body_text = default_email.get("email_body_text")
+ # Set the action_needed_reason_email to the default
+ reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
+ is_default_email = body_text == obj.action_needed_reason_email
+ if body_text and is_default_email and reason_changed:
+ obj.action_needed_reason_email = body_text
+
+ # == Handle status == #
if obj.status == original_obj.status:
# If the status hasn't changed, let the base function take care of it
return super().save_model(request, obj, form, change)
+ else:
+ # Run some checks on the current object for invalid status changes
+ obj, should_save = self._handle_status_change(request, obj, original_obj)
- # == Handle status changes == #
- # Run some checks on the current object for invalid status changes
- obj, should_save = self._handle_status_change(request, obj, original_obj)
-
- # We should only save if we don't display any errors in the steps above.
- if should_save:
- return super().save_model(request, obj, form, change)
-
- def _handle_existing_action_needed_reason_email(self, obj, original_obj):
- """
- Changes the action_needed_reason to the default email.
- This occurs if the email changes and if it is empty.
- """
-
- # Get the default email
- text = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason)
- body_text = text.get("email_body_text")
-
- # Set the action_needed_reason_email to the default
- reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
- is_default_email = body_text == obj.action_needed_reason_email
- if body_text and is_default_email and reason_changed:
- obj.action_needed_reason_email = body_text
-
- return obj
+ # We should only save if we don't display any errors in the steps above.
+ if should_save:
+ return super().save_model(request, obj, form, change)
def _handle_status_change(self, request, obj, original_obj):
"""
@@ -1976,17 +1967,18 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
for this particular domain request."""
emails = {}
for action_needed_reason in domain_request.ActionNeededReasons:
- enum_value = action_needed_reason.value
- custom_text = None
- if domain_request.action_needed_reason == enum_value and domain_request.action_needed_reason_email:
- custom_text = domain_request.action_needed_reason_email
+ if action_needed_reason != DomainRequest.ActionNeededReasons.OTHER:
+ enum_value = action_needed_reason.value
+ custom_text = None
+ if domain_request.action_needed_reason == enum_value and domain_request.action_needed_reason_email:
+ custom_text = domain_request.action_needed_reason_email
- emails[enum_value] = self._get_action_needed_reason_default_email(domain_request, enum_value, custom_text)
+ emails[enum_value] = self._get_action_needed_reason_default_email(domain_request, enum_value, custom_text)
return json.dumps(emails)
- def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason: str, custom_text=None):
+ def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason, custom_text=None):
"""Returns the default email associated with the given action needed reason"""
- if action_needed_reason is None or action_needed_reason == domain_request.ActionNeededReasons.OTHER:
+ if not action_needed_reason:
return {
"subject_text": None,
"email_body_text": None,
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index f6aee5dbe..e41431ba3 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -528,65 +528,54 @@ function initializeWidgetOnList(list, parentId) {
(function () {
let actionNeededReasonDropdown = document.querySelector("#id_action_needed_reason");
let actionNeededEmail = document.querySelector("#id_action_needed_reason_email");
+ let actionNeededEmailData = document.getElementById('action-needed-emails-data').textContent);
let noEmailMessage = document.getElementById("no-email-message");
const emptyReasonText = "---------"
const noEmailText = "No email will be sent."
- if(actionNeededReasonDropdown && actionNeededEmail) {
+ if(actionNeededReasonDropdown && actionNeededEmail && actionNeededEmailData) {
// Add a change listener to the action needed reason dropdown
- handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail);
+ handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail, actionNeededEmailData);
document.addEventListener('DOMContentLoaded', function() {
- if (!actionNeededReasonDropdown.value) {
- noEmailMessage.innerHTML = emptyReasonText
- showNoEmailMessage(actionNeededEmail, noEmailMessage);
- } else if (actionNeededReasonDropdown.value == "other") {
- noEmailMessage.innerHTML = noEmailText
+ let reason = actionNeededReasonDropdown.value;
+ noEmailMessage.innerHTML = reason ? noEmailText : emptyReasonText;
+ if (reason && reason != "other") {
+ // Show the email
+ showElement(actionNeededEmail);
+ hideElement(noEmailMessage);
+ } else {
+ // Show the no email message
+ hideElement(actionNeededEmail);
+ showElement(noEmailMessage);
}
});
}
- function handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail) {
+ function handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail, actionNeededEmailData) {
actionNeededReasonDropdown.addEventListener("change", function() {
let reason = actionNeededReasonDropdown.value;
+ let actionNeededEmailsJson = JSON.parse(actionNeededEmailData)
- // If a reason isn't specified, no email will be sent.
- // You also cannot save the model in this state.
- // This flow occurs if you switch back to the empty picker state.
- if(!reason) {
- noEmailMessage.innerHTML = emptyReasonText
- showNoEmailMessage(actionNeededEmail, noEmailMessage);
- return;
- }else if (reason === "other") {
- noEmailMessage.innerHTML = noEmailText
- }
-
- let actionNeededEmails = JSON.parse(document.getElementById('action-needed-emails-data').textContent)
- let emailData = actionNeededEmails[reason];
- if (emailData) {
+ // Show the "no email will be sent" text only if a reason is actually selected.
+ noEmailMessage.innerHTML = reason ? noEmailText : emptyReasonText;
+ if (reason && reason in actionNeededEmailsJson) {
+ let emailData = actionNeededEmailsJson[reason];
let emailBody = emailData.email_body_text
if (emailBody) {
+ // Show the email
actionNeededEmail.value = emailBody
- showActionNeededEmail(actionNeededEmail, noEmailMessage);
+ showElement(actionNeededEmail);
+ hideElement(noEmailMessage);
}else {
- showNoEmailMessage(actionNeededEmail, noEmailMessage);
+ // Show the no email message
+ hideElement(actionNeededEmail);
+ showElement(noEmailMessage);
}
}else {
- showNoEmailMessage(actionNeededEmail, noEmailMessage);
+ // Show the no email message
+ hideElement(actionNeededEmail);
+ showElement(noEmailMessage);
}
-
});
}
-
- // Show the text field. Hide the "no email" message.
- function showActionNeededEmail(actionNeededEmail, noEmailMessage){
- showElement(actionNeededEmail);
- hideElement(noEmailMessage);
- }
-
- // Hide the text field. Show the "no email" message.
- function showNoEmailMessage(actionNeededEmail, noEmailMessage) {
- hideElement(actionNeededEmail);
- showElement(noEmailMessage);
- }
-
})();
From 6d63c9f868dc4881f0055115f62a5d73b27715e9 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 11:59:36 -0600
Subject: [PATCH 45/71] Minor edits to not use kwargs and lint
---
src/registrar/admin.py | 4 +++-
src/registrar/models/domain_request.py | 25 ++++++++++++++++---------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 8f00ab519..870fb900e 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1973,7 +1973,9 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
if domain_request.action_needed_reason == enum_value and domain_request.action_needed_reason_email:
custom_text = domain_request.action_needed_reason_email
- emails[enum_value] = self._get_action_needed_reason_default_email(domain_request, enum_value, custom_text)
+ emails[enum_value] = self._get_action_needed_reason_default_email(
+ domain_request, enum_value, custom_text
+ )
return json.dumps(emails)
def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason, custom_text=None):
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index 1d26e0d2f..f2f43be33 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -612,8 +612,8 @@ class DomainRequest(TimeStampedModel):
super().save(*args, **kwargs)
- # Handle the action needed email. We send one when moving to action_needed,
- # but we don't send one when we are _already_ in the state and change the reason.
+ # Handle the action needed email.
+ # An email is sent out when action_needed_reason is changed or added.
if self.status == self.DomainRequestStatus.ACTION_NEEDED and self.action_needed_reason:
self.sync_action_needed_reason()
@@ -683,7 +683,15 @@ class DomainRequest(TimeStampedModel):
logger.error(f"Can't query an approved domain while attempting {called_from}")
def _send_status_update_email(
- self, new_status, email_template, email_template_subject, bcc_address="", context=None, **kwargs
+ self,
+ new_status,
+ email_template,
+ email_template_subject,
+ bcc_address="",
+ context=None,
+ send_email=True,
+ wrap_email=False,
+ custom_email_content=None,
):
"""Send a status update email to the creator.
@@ -694,7 +702,11 @@ class DomainRequest(TimeStampedModel):
If the waffle flag "profile_feature" is active, then this email will be sent to the
domain request creator rather than the submitter
- kwargs:
+ Optional args:
+ bcc_address: str -> the address to bcc to
+
+ context: dict -> The context sent to the template
+
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.
@@ -704,11 +716,6 @@ class DomainRequest(TimeStampedModel):
custom_email_content: str -> Renders an email with the content of this string as its body text.
"""
- # Email config options
- wrap_email = kwargs.get("wrap_email", False)
- send_email = kwargs.get("send_email", True)
- custom_email_content = kwargs.get("custom_email_content", None)
-
recipient = self.creator if flag_is_active(None, "profile_feature") else self.submitter
if recipient is None or recipient.email is None:
logger.warning(
From 8ff6d526525d20bfb9873c8b364e21afb7acd0f4 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 12:12:04 -0600
Subject: [PATCH 46/71] Simplify logic further
---
src/registrar/models/domain_request.py | 48 +++++++-------------------
1 file changed, 13 insertions(+), 35 deletions(-)
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index f2f43be33..c8ec643e6 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -614,7 +614,7 @@ class DomainRequest(TimeStampedModel):
# Handle the action needed email.
# An email is sent out when action_needed_reason is changed or added.
- if self.status == self.DomainRequestStatus.ACTION_NEEDED and self.action_needed_reason:
+ if self.action_needed_reason and self.status == self.DomainRequestStatus.ACTION_NEEDED:
self.sync_action_needed_reason()
# Update the cached values after saving
@@ -625,8 +625,7 @@ class DomainRequest(TimeStampedModel):
was_already_action_needed = self._cached_status == self.DomainRequestStatus.ACTION_NEEDED
reason_exists = self._cached_action_needed_reason is not None and self.action_needed_reason is not None
reason_changed = self._cached_action_needed_reason != self.action_needed_reason
- reason_email_changed = self._cached_action_needed_reason_email != self.action_needed_reason_email
- if was_already_action_needed and (reason_exists and reason_changed or reason_email_changed):
+ if was_already_action_needed and reason_exists and reason_changed:
# We don't send emails out in state "other"
if self.action_needed_reason != self.ActionNeededReasons.OTHER:
self._send_action_needed_reason_email(email_content=self.action_needed_reason_email)
@@ -880,43 +879,22 @@ class DomainRequest(TimeStampedModel):
def _send_action_needed_reason_email(self, send_email=True, email_content=None):
"""Sends out an automatic email for each valid action needed reason provided"""
- email_template_name: str = ""
- email_template_subject_name: str = ""
-
- if email_content is not None:
- email_template_name = "custom_email.txt"
-
- # Check for the "type" of action needed reason.
- can_send_email = True
- match self.action_needed_reason:
- # Add to this match if you need to pass in a custom filename for these templates.
- case self.ActionNeededReasons.OTHER, _:
- # Unknown and other are default cases - do nothing
- can_send_email = False
-
- # Assumes that the template name matches the action needed reason if nothing is specified.
- # This is so you can override if you need, or have this taken care of for you.
- if not email_template_name:
- email_template_name = f"{self.action_needed_reason}.txt"
-
- if not email_template_subject_name:
- email_template_subject_name = f"{self.action_needed_reason}_subject.txt"
+ email_template_name = "custom_email.txt"
+ email_template_subject_name = f"{self.action_needed_reason}_subject.txt"
bcc_address = ""
if settings.IS_PRODUCTION:
bcc_address = settings.DEFAULT_FROM_EMAIL
- # If we can, try to send out an email as long as send_email=True
- if can_send_email:
- self._send_status_update_email(
- new_status="action needed",
- email_template=f"emails/action_needed_reasons/{email_template_name}",
- email_template_subject=f"emails/action_needed_reasons/{email_template_subject_name}",
- send_email=send_email,
- bcc_address=bcc_address,
- custom_email_content=email_content,
- wrap_email=True,
- )
+ self._send_status_update_email(
+ new_status="action needed",
+ email_template=f"emails/action_needed_reasons/{email_template_name}",
+ email_template_subject=f"emails/action_needed_reasons/{email_template_subject_name}",
+ send_email=send_email,
+ bcc_address=bcc_address,
+ custom_email_content=email_content,
+ wrap_email=True,
+ )
@transition(
field="status",
From 41835d275fd7bb701f215d08128660189b71b09d Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 12:44:14 -0600
Subject: [PATCH 47/71] Further simplification
---
src/registrar/admin.py | 58 +++++++-----------------
src/registrar/assets/js/get-gov-admin.js | 2 +-
2 files changed, 17 insertions(+), 43 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 870fb900e..fd529b652 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1736,20 +1736,14 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
# == Handle action_needed_reason == #
# Store the email that was sent out if one was sent and it isn't saved to a variable yet
- if not obj.action_needed_reason or obj.action_needed_reason == obj.ActionNeededReasons.OTHER:
- # Reset the action needed email to none if we don't send out an email.
- obj.action_needed_reason_email = None
- else:
- # We send out an email -- store which one we send out.
- # Set the email to a default one if a custom email isn't provided.
- default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason)
- body_text = default_email.get("email_body_text")
-
- # Set the action_needed_reason_email to the default
+ default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason)
+ if default_email:
+ # Set the action_needed_reason_email to the default.
+ # Since this check occurs after save, if the user enters a value then
+ # we won't update.
reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
- is_default_email = body_text == obj.action_needed_reason_email
- if body_text and is_default_email and reason_changed:
- obj.action_needed_reason_email = body_text
+ if reason_changed and default_email == obj.action_needed_reason_email:
+ obj.action_needed_reason_email = default_email
# == Handle status == #
if obj.status == original_obj.status:
@@ -1967,24 +1961,16 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
for this particular domain request."""
emails = {}
for action_needed_reason in domain_request.ActionNeededReasons:
- if action_needed_reason != DomainRequest.ActionNeededReasons.OTHER:
- enum_value = action_needed_reason.value
- custom_text = None
- if domain_request.action_needed_reason == enum_value and domain_request.action_needed_reason_email:
- custom_text = domain_request.action_needed_reason_email
-
- emails[enum_value] = self._get_action_needed_reason_default_email(
- domain_request, enum_value, custom_text
- )
+ # Map the action_needed_reason to its default email
+ emails[action_needed_reason.value] = self._get_action_needed_reason_default_email(
+ domain_request, action_needed_reason.value
+ )
return json.dumps(emails)
- def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason, custom_text=None):
+ def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason):
"""Returns the default email associated with the given action needed reason"""
- if not action_needed_reason:
- return {
- "subject_text": None,
- "email_body_text": None,
- }
+ if not action_needed_reason or action_needed_reason == DomainRequest.ActionNeededReasons.OTHER:
+ return None
if flag_is_active(None, "profile_feature"): # type: ignore
recipient = domain_request.creator
@@ -1994,27 +1980,15 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
# Return the context of the rendered views
context = {"domain_request": domain_request, "recipient": recipient}
- # Get the email subject
- template_subject_path = f"emails/action_needed_reasons/{action_needed_reason}_subject.txt"
- subject_text = get_template(template_subject_path).render(context=context)
-
# Get the email body
- if not custom_text:
- template_path = f"emails/action_needed_reasons/{action_needed_reason}.txt"
- else:
- template_path = "emails/action_needed_reasons/custom_email.txt"
- context["custom_email_content"] = custom_text
+ template_path = f"emails/action_needed_reasons/{action_needed_reason}.txt"
email_body_text = get_template(template_path).render(context=context)
-
email_body_text_cleaned = None
if email_body_text:
email_body_text_cleaned = email_body_text.strip().lstrip("\n")
- return {
- "subject_text": subject_text,
- "email_body_text": email_body_text_cleaned,
- }
+ return email_body_text_cleaned
def process_log_entry(self, log_entry):
"""Process a log entry and return filtered entry dictionary if applicable."""
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index e41431ba3..b5df21538 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -528,7 +528,7 @@ function initializeWidgetOnList(list, parentId) {
(function () {
let actionNeededReasonDropdown = document.querySelector("#id_action_needed_reason");
let actionNeededEmail = document.querySelector("#id_action_needed_reason_email");
- let actionNeededEmailData = document.getElementById('action-needed-emails-data').textContent);
+ let actionNeededEmailData = document.getElementById('action-needed-emails-data').textContent;
let noEmailMessage = document.getElementById("no-email-message");
const emptyReasonText = "---------"
const noEmailText = "No email will be sent."
From f6e82c7a989d2b27e5fab6a16ad01ed16d228fc2 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 12:53:26 -0600
Subject: [PATCH 48/71] tests
---
src/registrar/tests/test_admin.py | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py
index 22bdc8558..34d64190f 100644
--- a/src/registrar/tests/test_admin.py
+++ b/src/registrar/tests/test_admin.py
@@ -1496,7 +1496,8 @@ class TestDomainRequestAdmin(MockEppLib):
self.assert_email_is_accurate("custom email content", 4, EMAIL, bcc_email_address=BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 5)
- # Tests if a new email gets sent when just the email is changed
+ # Tests if a new email gets sent when just the email is changed.
+ # An email should NOT be sent out if we just modify the email content.
self.transition_state_and_send_email(
domain_request,
action_needed,
@@ -1504,7 +1505,22 @@ class TestDomainRequestAdmin(MockEppLib):
action_needed_reason_email="dummy email content",
)
- self.assert_email_is_accurate("dummy email content", 5, EMAIL, bcc_email_address=BCC_EMAIL)
+ self.assertEqual(len(self.mock_client.EMAILS_SENT), 5)
+
+ # Set the request back to in review
+ domain_request.in_review()
+
+ # no email was sent, so no email should be stored
+ self.assertEqual(domain_request.action_needed_reason_email, None)
+
+ # Try sending another email when changing states AND including content
+ self.transition_state_and_send_email(
+ domain_request,
+ action_needed,
+ action_needed_reason=questionable_so,
+ action_needed_reason_email="custom content when starting anew",
+ )
+ self.assert_email_is_accurate("custom content when starting anew", 5, EMAIL, bcc_email_address=BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 6)
def test_save_model_sends_submitted_email(self):
From bac9dc94aa52aa1439b7658d45917b329e1a71f8 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 12:59:28 -0600
Subject: [PATCH 49/71] Cleanup
---
src/registrar/assets/js/get-gov-admin.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index b5df21538..e5aa495f5 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -530,7 +530,7 @@ function initializeWidgetOnList(list, parentId) {
let actionNeededEmail = document.querySelector("#id_action_needed_reason_email");
let actionNeededEmailData = document.getElementById('action-needed-emails-data').textContent;
let noEmailMessage = document.getElementById("no-email-message");
- const emptyReasonText = "---------"
+ const emptyReasonText = "-"
const noEmailText = "No email will be sent."
if(actionNeededReasonDropdown && actionNeededEmail && actionNeededEmailData) {
// Add a change listener to the action needed reason dropdown
@@ -558,9 +558,10 @@ function initializeWidgetOnList(list, parentId) {
// Show the "no email will be sent" text only if a reason is actually selected.
noEmailMessage.innerHTML = reason ? noEmailText : emptyReasonText;
+ console.log(`reaso: ${reason} vs in ${reason in actionNeededEmailsJson}`)
+ console.log(noEmailMessage)
if (reason && reason in actionNeededEmailsJson) {
- let emailData = actionNeededEmailsJson[reason];
- let emailBody = emailData.email_body_text
+ let emailBody = actionNeededEmailsJson[reason];
if (emailBody) {
// Show the email
actionNeededEmail.value = emailBody
From 58605f11e5d7debd2ec700e7e7339b3bde9b3894 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 12 Jul 2024 15:11:42 -0600
Subject: [PATCH 50/71] Readonly on send
---
src/registrar/admin.py | 13 ++++-
src/registrar/assets/js/get-gov-admin.js | 50 +++++++++++++------
.../admin/includes/detail_table_fieldset.html | 1 +
3 files changed, 48 insertions(+), 16 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index fd529b652..42d2872a2 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1742,8 +1742,11 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
# Since this check occurs after save, if the user enters a value then
# we won't update.
reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
- if reason_changed and default_email == obj.action_needed_reason_email:
- obj.action_needed_reason_email = default_email
+ if reason_changed:
+ request.session["action_needed_email_sent"] = True
+ logger.info("added session object")
+ if default_email == obj.action_needed_reason_email:
+ obj.action_needed_reason_email = default_email
# == Handle status == #
if obj.status == original_obj.status:
@@ -1953,6 +1956,12 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
extra_context["action_needed_reason_emails"] = self.get_all_action_needed_reason_emails_as_json(obj)
extra_context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
+ # Denote if an action needed email was sent or not
+ email_sent = request.session.get("action_needed_email_sent", False)
+ extra_context["action_needed_email_sent"] = email_sent
+ if email_sent:
+ email_sent = request.session["action_needed_email_sent"] = False
+
# Call the superclass method with updated extra_context
return super().change_view(request, object_id, form_url, extra_context)
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index e5aa495f5..07722fdfc 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -36,6 +36,15 @@ function openInNewTab(el, removeAttribute = false){
}
};
+// Adds or removes a boolean from our session
+function addOrRemoveSessionBoolean(name, add){
+ if (add) {
+ sessionStorage.setItem(name, "true");
+ }else {
+ sessionStorage.removeItem(name);
+ }
+}
+
// <<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>>
// Event handlers.
@@ -418,15 +427,6 @@ function initializeWidgetOnList(list, parentId) {
object.classList.add("display-none");
}
}
-
- // Adds or removes a boolean from our session
- function addOrRemoveSessionBoolean(name, add){
- if (add) {
- sessionStorage.setItem(name, "true");
- }else {
- sessionStorage.removeItem(name);
- }
- }
})();
/** An IIFE for toggling the submit bar on domain request forms
@@ -529,9 +529,12 @@ function initializeWidgetOnList(list, parentId) {
let actionNeededReasonDropdown = document.querySelector("#id_action_needed_reason");
let actionNeededEmail = document.querySelector("#id_action_needed_reason_email");
let actionNeededEmailData = document.getElementById('action-needed-emails-data').textContent;
- let noEmailMessage = document.getElementById("no-email-message");
- const emptyReasonText = "-"
- const noEmailText = "No email will be sent."
+ let noEmailMessage = document.querySelector("#no-email-message");
+ const oldDropdownValue = actionNeededReasonDropdown ? actionNeededReasonDropdown.value : null;
+ const oldEmailValue = actionNeededEmailData ? actionNeededEmailData.value : null;
+ const emptyReasonText = "-";
+ const noEmailText = "No email will be sent.";
+ const domainRequestId = actionNeededReasonDropdown ? document.querySelector("#domain_request_id").value : null
if(actionNeededReasonDropdown && actionNeededEmail && actionNeededEmailData) {
// Add a change listener to the action needed reason dropdown
handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail, actionNeededEmailData);
@@ -548,6 +551,16 @@ function initializeWidgetOnList(list, parentId) {
hideElement(actionNeededEmail);
showElement(noEmailMessage);
}
+
+ let emailWasSent = document.getElementById("action-needed-email-sent")
+ console.log(`email ${emailWasSent.value} vs session ${sessionStorage.getItem("actionNeededEmailSent")} vs id ${domainRequestId}`)
+ if (emailWasSent && emailWasSent.value) {
+ // add the session object
+ if (sessionStorage.getItem(`actionNeededEmailSent-${domainRequestId}`) === null) {
+ sessionStorage.setItem(`actionNeededEmailSent-${domainRequestId}`, domainRequestId);
+ }
+ actionNeededEmail.readOnly = true
+ }
});
}
@@ -558,8 +571,6 @@ function initializeWidgetOnList(list, parentId) {
// Show the "no email will be sent" text only if a reason is actually selected.
noEmailMessage.innerHTML = reason ? noEmailText : emptyReasonText;
- console.log(`reaso: ${reason} vs in ${reason in actionNeededEmailsJson}`)
- console.log(noEmailMessage)
if (reason && reason in actionNeededEmailsJson) {
let emailBody = actionNeededEmailsJson[reason];
if (emailBody) {
@@ -567,6 +578,17 @@ function initializeWidgetOnList(list, parentId) {
actionNeededEmail.value = emailBody
showElement(actionNeededEmail);
hideElement(noEmailMessage);
+
+ // Reset the session object on change since change refreshes the email content.
+ // Only do this if we change the action needed reason, or if we:
+ // change the reason => modify email content => change back to old reason.
+ if (oldDropdownValue != actionNeededReasonDropdown.value || oldEmailValue != actionNeededEmail.value) {
+ let emailSent = sessionStorage.getItem(`actionNeededEmailSent-${domainRequestId}`)
+ if (emailSent !== null){
+ sessionStorage.removeItem(`actionNeededEmailSent-${domainRequestId}`);
+ }
+ actionNeededEmail.readOnly = false;
+ }
}else {
// Show the no email message
hideElement(actionNeededEmail);
diff --git a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
index f0ff7be3f..d477b55a7 100644
--- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
+++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
@@ -147,6 +147,7 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% if field.field.name == "action_needed_reason_email" %}
{{ field.field }}
No email will be sent.
+
{% else %}
{{ field.field }}
{% endif %}
From 2bb2af5089ee2c19484400239866626e405eaff0 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 15 Jul 2024 08:07:28 -0600
Subject: [PATCH 51/71] Readonly view
---
src/registrar/assets/js/get-gov-admin.js | 21 +++++++++++++++++--
.../admin/includes/detail_table_fieldset.html | 20 ++++++++++++++++++
2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index 07722fdfc..fbbea7003 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -559,7 +559,7 @@ function initializeWidgetOnList(list, parentId) {
if (sessionStorage.getItem(`actionNeededEmailSent-${domainRequestId}`) === null) {
sessionStorage.setItem(`actionNeededEmailSent-${domainRequestId}`, domainRequestId);
}
- actionNeededEmail.readOnly = true
+ hideReadonly(actionNeededEmail.parentElement)
}
});
}
@@ -587,7 +587,7 @@ function initializeWidgetOnList(list, parentId) {
if (emailSent !== null){
sessionStorage.removeItem(`actionNeededEmailSent-${domainRequestId}`);
}
- actionNeededEmail.readOnly = false;
+ showReadonly(actionNeededEmail.parentElement)
}
}else {
// Show the no email message
@@ -601,4 +601,21 @@ function initializeWidgetOnList(list, parentId) {
}
});
}
+
+ function showReadonly(actionNeededEmailParent) {
+ let readonlyView = document.querySelector("#action-needed-reason-email-readonly")
+ if (readonlyView) {
+ hideElement(readonlyView)
+ showElement(actionNeededEmailParent)
+ }
+ }
+
+ function hideReadonly(actionNeededEmailParent) {
+ let readonlyView = document.querySelector("#action-needed-reason-email-readonly")
+ if (readonlyView) {
+ showElement(readonlyView)
+ hideElement(actionNeededEmailParent)
+ }
+ }
+
})();
diff --git a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
index d477b55a7..a23cd8f55 100644
--- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
+++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
@@ -145,9 +145,29 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% block field_other %}
{% if field.field.name == "action_needed_reason_email" %}
+
+
+
+
+
No email will be sent.
+
+
+
+
+
{{ field.field }}
No email will be sent.
+
{% else %}
{{ field.field }}
{% endif %}
From 646e37570800ee77404e7114f7f8bd0eda30614d Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 15 Jul 2024 09:49:46 -0600
Subject: [PATCH 52/71] Fix bugs
---
src/registrar/admin.py | 18 ++++-----
src/registrar/assets/js/get-gov-admin.js | 50 ++++++++++++++++--------
2 files changed, 42 insertions(+), 26 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 42d2872a2..e15228534 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1735,18 +1735,18 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
original_obj = models.DomainRequest.objects.get(pk=obj.pk)
# == Handle action_needed_reason == #
- # Store the email that was sent out if one was sent and it isn't saved to a variable yet
+
default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason)
- if default_email:
+ reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
+ if reason_changed:
+ # Track that we sent out an email
+ request.session["action_needed_email_sent"] = True
+
# Set the action_needed_reason_email to the default.
# Since this check occurs after save, if the user enters a value then
# we won't update.
- reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
- if reason_changed:
- request.session["action_needed_email_sent"] = True
- logger.info("added session object")
- if default_email == obj.action_needed_reason_email:
- obj.action_needed_reason_email = default_email
+ if default_email and default_email == obj.action_needed_reason_email:
+ obj.action_needed_reason_email = default_email
# == Handle status == #
if obj.status == original_obj.status:
@@ -1960,7 +1960,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
email_sent = request.session.get("action_needed_email_sent", False)
extra_context["action_needed_email_sent"] = email_sent
if email_sent:
- email_sent = request.session["action_needed_email_sent"] = False
+ request.session["action_needed_email_sent"] = False
# Call the superclass method with updated extra_context
return super().change_view(request, object_id, form_url, extra_context)
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index fbbea7003..503055a89 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -535,10 +535,11 @@ function initializeWidgetOnList(list, parentId) {
const emptyReasonText = "-";
const noEmailText = "No email will be sent.";
const domainRequestId = actionNeededReasonDropdown ? document.querySelector("#domain_request_id").value : null
- if(actionNeededReasonDropdown && actionNeededEmail && actionNeededEmailData) {
+ const emailSentSessionVariableName = `actionNeededEmailSent-${domainRequestId}`;
+
+ if(actionNeededReasonDropdown && actionNeededEmail && actionNeededEmailData && domainRequestId) {
// Add a change listener to the action needed reason dropdown
handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail, actionNeededEmailData);
-
document.addEventListener('DOMContentLoaded', function() {
let reason = actionNeededReasonDropdown.value;
noEmailMessage.innerHTML = reason ? noEmailText : emptyReasonText;
@@ -552,14 +553,21 @@ function initializeWidgetOnList(list, parentId) {
showElement(noEmailMessage);
}
+
let emailWasSent = document.getElementById("action-needed-email-sent")
- console.log(`email ${emailWasSent.value} vs session ${sessionStorage.getItem("actionNeededEmailSent")} vs id ${domainRequestId}`)
- if (emailWasSent && emailWasSent.value) {
- // add the session object
- if (sessionStorage.getItem(`actionNeededEmailSent-${domainRequestId}`) === null) {
- sessionStorage.setItem(`actionNeededEmailSent-${domainRequestId}`, domainRequestId);
- }
+ if (emailWasSent && emailWasSent.value === "True") {
+ // An email was sent out - store that information in a session variable
+ addOrRemoveSessionBoolean(emailSentSessionVariableName, add=true)
+ }
+
+ if (sessionStorage.getItem(emailSentSessionVariableName) !== null) {
+ // Show the readonly field, hide the editable field
+ showReadonly(actionNeededEmail.parentElement)
+ console.log("adding data")
+ }else {
+ // No email was sent out -- show the editable field
hideReadonly(actionNeededEmail.parentElement)
+ console.log("removing data")
}
});
}
@@ -582,13 +590,22 @@ function initializeWidgetOnList(list, parentId) {
// Reset the session object on change since change refreshes the email content.
// Only do this if we change the action needed reason, or if we:
// change the reason => modify email content => change back to old reason.
- if (oldDropdownValue != actionNeededReasonDropdown.value || oldEmailValue != actionNeededEmail.value) {
- let emailSent = sessionStorage.getItem(`actionNeededEmailSent-${domainRequestId}`)
+ if (oldDropdownValue !== actionNeededReasonDropdown.value || oldEmailValue !== actionNeededEmail.value) {
+ let emailSent = sessionStorage.getItem(emailSentSessionVariableName)
if (emailSent !== null){
- sessionStorage.removeItem(`actionNeededEmailSent-${domainRequestId}`);
+ console.log("removing data")
+ addOrRemoveSessionBoolean(emailSentSessionVariableName, add=false)
}
- showReadonly(actionNeededEmail.parentElement)
}
+
+ if (sessionStorage.getItem(emailSentSessionVariableName) !== null) {
+ // Show the readonly field, hide the editable field
+ showReadonly(actionNeededEmail.parentElement)
+ }else {
+ // No email was sent out -- show the editable field
+ hideReadonly(actionNeededEmail.parentElement)
+ }
+
}else {
// Show the no email message
hideElement(actionNeededEmail);
@@ -605,17 +622,16 @@ function initializeWidgetOnList(list, parentId) {
function showReadonly(actionNeededEmailParent) {
let readonlyView = document.querySelector("#action-needed-reason-email-readonly")
if (readonlyView) {
- hideElement(readonlyView)
- showElement(actionNeededEmailParent)
+ showElement(readonlyView)
+ hideElement(actionNeededEmailParent)
}
}
function hideReadonly(actionNeededEmailParent) {
let readonlyView = document.querySelector("#action-needed-reason-email-readonly")
if (readonlyView) {
- showElement(readonlyView)
- hideElement(actionNeededEmailParent)
+ hideElement(readonlyView)
+ showElement(actionNeededEmailParent)
}
}
-
})();
From 7364db4e247ece3f7fafab94bfd62579677f84e2 Mon Sep 17 00:00:00 2001
From: Rebecca Hsieh
Date: Mon, 15 Jul 2024 09:00:44 -0700
Subject: [PATCH 53/71] Add fix for Domain as well
---
src/registrar/admin.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 7a09255b0..90f393a6e 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1383,7 +1383,7 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin):
for name, data in fieldsets:
fields = data.get("fields", [])
fields = tuple(field for field in fields if field not in DomainInformationAdmin.superuser_only_fields)
- modified_fieldsets.append((name, {"fields": fields}))
+ modified_fieldsets.append((name, {**data, "fields": fields}))
return modified_fieldsets
return fieldsets
From b68fe5558449f6898ee8c2978a38f2b768087318 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 15 Jul 2024 11:30:38 -0600
Subject: [PATCH 54/71] Further refinement
need to fix unit test
---
src/registrar/admin.py | 26 ++++++++++++++++--------
src/registrar/assets/js/get-gov-admin.js | 3 ---
src/registrar/models/domain_request.py | 2 +-
src/registrar/tests/test_admin.py | 8 +++++---
4 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index e15228534..5c6b480f2 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1736,16 +1736,21 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
# == Handle action_needed_reason == #
- default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason)
reason_changed = obj.action_needed_reason != original_obj.action_needed_reason
if reason_changed:
- # Track that we sent out an email
+ # Track the fact that we sent out an email
request.session["action_needed_email_sent"] = True
- # Set the action_needed_reason_email to the default.
- # Since this check occurs after save, if the user enters a value then
- # we won't update.
- if default_email and default_email == obj.action_needed_reason_email:
+ # Set the action_needed_reason_email to the default if nothing exists.
+ # Since this check occurs after save, if the user enters a value then we won't update.
+
+ default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason)
+ if obj.action_needed_reason_email:
+ emails = self.get_all_action_needed_reason_emails(obj)
+ is_custom_email = obj.action_needed_reason_email not in emails.values()
+ if not is_custom_email:
+ obj.action_needed_reason_email = default_email
+ else:
obj.action_needed_reason_email = default_email
# == Handle status == #
@@ -1953,7 +1958,8 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
# Initialize extra_context and add filtered entries
extra_context = extra_context or {}
extra_context["filtered_audit_log_entries"] = filtered_audit_log_entries
- extra_context["action_needed_reason_emails"] = self.get_all_action_needed_reason_emails_as_json(obj)
+ emails = self.get_all_action_needed_reason_emails(obj)
+ extra_context["action_needed_reason_emails"] = json.dumps(emails)
extra_context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
# Denote if an action needed email was sent or not
@@ -1965,16 +1971,18 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
# Call the superclass method with updated extra_context
return super().change_view(request, object_id, form_url, extra_context)
- def get_all_action_needed_reason_emails_as_json(self, domain_request):
+ def get_all_action_needed_reason_emails(self, domain_request):
"""Returns a json dictionary of every action needed reason and its associated email
for this particular domain request."""
+
emails = {}
for action_needed_reason in domain_request.ActionNeededReasons:
# Map the action_needed_reason to its default email
emails[action_needed_reason.value] = self._get_action_needed_reason_default_email(
domain_request, action_needed_reason.value
)
- return json.dumps(emails)
+
+ return emails
def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason):
"""Returns the default email associated with the given action needed reason"""
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index 503055a89..bfee12e79 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -563,11 +563,9 @@ function initializeWidgetOnList(list, parentId) {
if (sessionStorage.getItem(emailSentSessionVariableName) !== null) {
// Show the readonly field, hide the editable field
showReadonly(actionNeededEmail.parentElement)
- console.log("adding data")
}else {
// No email was sent out -- show the editable field
hideReadonly(actionNeededEmail.parentElement)
- console.log("removing data")
}
});
}
@@ -593,7 +591,6 @@ function initializeWidgetOnList(list, parentId) {
if (oldDropdownValue !== actionNeededReasonDropdown.value || oldEmailValue !== actionNeededEmail.value) {
let emailSent = sessionStorage.getItem(emailSentSessionVariableName)
if (emailSent !== null){
- console.log("removing data")
addOrRemoveSessionBoolean(emailSentSessionVariableName, add=false)
}
}
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index c8ec643e6..c7609c8c9 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -597,7 +597,6 @@ class DomainRequest(TimeStampedModel):
def _cache_status_and_action_needed_reason(self):
"""Maintains a cache of properties so we can avoid a DB call"""
self._cached_action_needed_reason = self.action_needed_reason
- self._cached_action_needed_reason_email = self.action_needed_reason_email
self._cached_status = self.status
def __init__(self, *args, **kwargs):
@@ -625,6 +624,7 @@ class DomainRequest(TimeStampedModel):
was_already_action_needed = self._cached_status == self.DomainRequestStatus.ACTION_NEEDED
reason_exists = self._cached_action_needed_reason is not None and self.action_needed_reason is not None
reason_changed = self._cached_action_needed_reason != self.action_needed_reason
+ print(f"was_already_action_needed {was_already_action_needed} reason_exists {reason_exists} and {reason_changed}")
if was_already_action_needed and reason_exists and reason_changed:
# We don't send emails out in state "other"
if self.action_needed_reason != self.ActionNeededReasons.OTHER:
diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py
index 34d64190f..4500546f8 100644
--- a/src/registrar/tests/test_admin.py
+++ b/src/registrar/tests/test_admin.py
@@ -1385,6 +1385,9 @@ class TestDomainRequestAdmin(MockEppLib):
# Create a mock request
request = self.factory.post("/admin/registrar/domainrequest/{}/change/".format(domain_request.pk))
+ # Create a fake session to hook to
+ request.session = {}
+
# Modify the domain request's properties
domain_request.status = status
@@ -1450,6 +1453,7 @@ class TestDomainRequestAdmin(MockEppLib):
# Test the email sent out for already_has_domains
already_has_domains = DomainRequest.ActionNeededReasons.ALREADY_HAS_DOMAINS
self.transition_state_and_send_email(domain_request, action_needed, action_needed_reason=already_has_domains)
+
self.assert_email_is_accurate("ORGANIZATION ALREADY HAS A .GOV DOMAIN", 0, EMAIL, bcc_email_address=BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
@@ -1493,6 +1497,7 @@ class TestDomainRequestAdmin(MockEppLib):
action_needed_reason_email="custom email content",
)
+ domain_request.refresh_from_db()
self.assert_email_is_accurate("custom email content", 4, EMAIL, bcc_email_address=BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 5)
@@ -1510,9 +1515,6 @@ class TestDomainRequestAdmin(MockEppLib):
# Set the request back to in review
domain_request.in_review()
- # no email was sent, so no email should be stored
- self.assertEqual(domain_request.action_needed_reason_email, None)
-
# Try sending another email when changing states AND including content
self.transition_state_and_send_email(
domain_request,
From c2d8c0eadb5ee49efc3e8759d4ea43850ee6005c Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 15 Jul 2024 11:42:05 -0600
Subject: [PATCH 55/71] fix test
---
src/registrar/models/domain_request.py | 1 -
src/registrar/tests/test_admin.py | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index c7609c8c9..aac356e38 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -624,7 +624,6 @@ class DomainRequest(TimeStampedModel):
was_already_action_needed = self._cached_status == self.DomainRequestStatus.ACTION_NEEDED
reason_exists = self._cached_action_needed_reason is not None and self.action_needed_reason is not None
reason_changed = self._cached_action_needed_reason != self.action_needed_reason
- print(f"was_already_action_needed {was_already_action_needed} reason_exists {reason_exists} and {reason_changed}")
if was_already_action_needed and reason_exists and reason_changed:
# We don't send emails out in state "other"
if self.action_needed_reason != self.ActionNeededReasons.OTHER:
diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py
index 4500546f8..3ee5eb4f9 100644
--- a/src/registrar/tests/test_admin.py
+++ b/src/registrar/tests/test_admin.py
@@ -1519,7 +1519,7 @@ class TestDomainRequestAdmin(MockEppLib):
self.transition_state_and_send_email(
domain_request,
action_needed,
- action_needed_reason=questionable_so,
+ action_needed_reason=eligibility_unclear,
action_needed_reason_email="custom content when starting anew",
)
self.assert_email_is_accurate("custom content when starting anew", 5, EMAIL, bcc_email_address=BCC_EMAIL)
From ea1e8aa5101b93a132526c7d65cb7bb22e1879ca Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 15 Jul 2024 11:52:16 -0600
Subject: [PATCH 56/71] lint
---
src/registrar/admin.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 5c6b480f2..efb662859 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1981,7 +1981,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
emails[action_needed_reason.value] = self._get_action_needed_reason_default_email(
domain_request, action_needed_reason.value
)
-
+
return emails
def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason):
From 4aa816cfdf7955f3dae7a06b5439346c4dc02ca0 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 15 Jul 2024 12:14:07 -0600
Subject: [PATCH 57/71] Update test_admin.py
---
src/registrar/tests/test_admin.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py
index 3ee5eb4f9..957fb5509 100644
--- a/src/registrar/tests/test_admin.py
+++ b/src/registrar/tests/test_admin.py
@@ -2449,6 +2449,8 @@ class TestDomainRequestAdmin(MockEppLib):
request = self.factory.post("/admin/registrar/domainrequest/{}/change/".format(domain_request.pk))
request.user = self.superuser
+ request.session = {}
+
# Define a custom implementation for is_active
def custom_is_active(self):
return domain_is_active # Override to return True
From bd55995e1c4f297673951cf7f2d9c42ecf7db3dd Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Mon, 15 Jul 2024 12:29:12 -0600
Subject: [PATCH 58/71] Update detail_table_fieldset.html
---
.../templates/django/admin/includes/detail_table_fieldset.html | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
index a23cd8f55..5f451766f 100644
--- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
+++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
@@ -145,6 +145,7 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% block field_other %}
{% if field.field.name == "action_needed_reason_email" %}
+