diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 1bfda0b84..4034bf35b 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -884,14 +884,11 @@ class DomainApplicationAdmin(ListHeaderAdmin): if ( obj and original_obj.status == models.DomainApplication.ApplicationStatus.APPROVED - and ( - obj.status == models.DomainApplication.ApplicationStatus.REJECTED - or obj.status == models.DomainApplication.ApplicationStatus.INELIGIBLE - ) + and obj.status != models.DomainApplication.ApplicationStatus.APPROVED and not obj.domain_is_not_active() ): # If an admin tried to set an approved application to - # rejected or ineligible and the related domain is already + # another status and the related domain is already # active, shortcut the action and throw a friendly # error message. This action would still not go through # shortcut or not as the rules are duplicated on the model, diff --git a/src/registrar/assets/sass/_theme/_alerts.scss b/src/registrar/assets/sass/_theme/_alerts.scss index 9ee28a357..163f243d3 100644 --- a/src/registrar/assets/sass/_theme/_alerts.scss +++ b/src/registrar/assets/sass/_theme/_alerts.scss @@ -17,5 +17,8 @@ .usa-alert__body::before { left: 1rem !important; } - } + } + .usa-alert__body.margin-left-1 { + margin-left: 0.5rem!important; + } } diff --git a/src/registrar/assets/sass/_theme/_uswds-theme.scss b/src/registrar/assets/sass/_theme/_uswds-theme.scss index 0cdf6675e..a26f23508 100644 --- a/src/registrar/assets/sass/_theme/_uswds-theme.scss +++ b/src/registrar/assets/sass/_theme/_uswds-theme.scss @@ -116,6 +116,10 @@ in the form $setting: value, $theme-color-success-light: $dhs-green-30, $theme-color-success-lighter: $dhs-green-15, + /*--------------------------- + ## Emergency state + ----------------------------*/ + $theme-color-emergency: #FFC3F9, /*--------------------------- # Input settings diff --git a/src/registrar/fixtures_applications.py b/src/registrar/fixtures_applications.py index 92094b876..659a3040e 100644 --- a/src/registrar/fixtures_applications.py +++ b/src/registrar/fixtures_applications.py @@ -104,7 +104,7 @@ class DomainApplicationFixture: # Random choice of agency for selects, used as placeholders for testing. else random.choice(DomainApplication.AGENCIES) # nosec ) - + da.submission_date = fake.date() da.federal_type = ( app["federal_type"] if "federal_type" in app diff --git a/src/registrar/models/domain_application.py b/src/registrar/models/domain_application.py index 4c1a8e22c..f048bdb89 100644 --- a/src/registrar/models/domain_application.py +++ b/src/registrar/models/domain_application.py @@ -578,6 +578,19 @@ class DomainApplication(TimeStampedModel): return not self.approved_domain.is_active() return True + def delete_and_clean_up_domain(self, called_from): + try: + domain_state = self.approved_domain.state + # Only reject if it exists on EPP + if domain_state != Domain.State.UNKNOWN: + self.approved_domain.deletedInEpp() + self.approved_domain.save() + self.approved_domain.delete() + self.approved_domain = None + except Exception as err: + logger.error(err) + 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, send_email=True): """Send a status update email to the submitter. @@ -641,11 +654,15 @@ class DomainApplication(TimeStampedModel): self.submission_date = timezone.now().date() self.save() - self._send_status_update_email( - "submission confirmation", - "emails/submission_confirmation.txt", - "emails/submission_confirmation_subject.txt", - ) + # Limit email notifications to transitions from Started and Withdrawn + limited_statuses = [self.ApplicationStatus.STARTED, self.ApplicationStatus.WITHDRAWN] + + if self.status in limited_statuses: + self._send_status_update_email( + "submission confirmation", + "emails/submission_confirmation.txt", + "emails/submission_confirmation_subject.txt", + ) @transition( field="status", @@ -657,11 +674,19 @@ class DomainApplication(TimeStampedModel): ApplicationStatus.INELIGIBLE, ], target=ApplicationStatus.IN_REVIEW, + conditions=[domain_is_not_active], ) def in_review(self): """Investigate an application that has been submitted. - This action is logged.""" + This action is logged. + + As side effects this will delete the domain and domain_information + (will cascade) when they exist.""" + + if self.status == self.ApplicationStatus.APPROVED: + self.delete_and_clean_up_domain("in_review") + literal = DomainApplication.ApplicationStatus.IN_REVIEW # Check if the tuple exists, then grab its value in_review = literal if literal is not None else "In Review" @@ -676,11 +701,19 @@ class DomainApplication(TimeStampedModel): ApplicationStatus.INELIGIBLE, ], target=ApplicationStatus.ACTION_NEEDED, + conditions=[domain_is_not_active], ) def action_needed(self): """Send back an application that is under investigation or rejected. - This action is logged.""" + This action is logged. + + As side effects this will delete the domain and domain_information + (will cascade) when they exist.""" + + if self.status == self.ApplicationStatus.APPROVED: + self.delete_and_clean_up_domain("reject_with_prejudice") + literal = DomainApplication.ApplicationStatus.ACTION_NEEDED # Check if the tuple is setup correctly, then grab its value action_needed = literal if literal is not None else "Action Needed" @@ -735,6 +768,7 @@ class DomainApplication(TimeStampedModel): ) def withdraw(self): """Withdraw an application that has been submitted.""" + self._send_status_update_email( "withdraw", "emails/domain_request_withdrawn.txt", @@ -752,18 +786,9 @@ class DomainApplication(TimeStampedModel): As side effects this will delete the domain and domain_information (will cascade), and send an email notification.""" + if self.status == self.ApplicationStatus.APPROVED: - try: - domain_state = self.approved_domain.state - # Only reject if it exists on EPP - if domain_state != Domain.State.UNKNOWN: - self.approved_domain.deletedInEpp() - self.approved_domain.save() - self.approved_domain.delete() - self.approved_domain = None - except Exception as err: - logger.error(err) - logger.error("Can't query an approved domain while attempting a DA reject()") + self.delete_and_clean_up_domain("reject") self._send_status_update_email( "action needed", @@ -792,17 +817,7 @@ class DomainApplication(TimeStampedModel): and domain_information (will cascade) when they exist.""" if self.status == self.ApplicationStatus.APPROVED: - try: - domain_state = self.approved_domain.state - # Only reject if it exists on EPP - if domain_state != Domain.State.UNKNOWN: - self.approved_domain.deletedInEpp() - self.approved_domain.save() - self.approved_domain.delete() - self.approved_domain = None - except Exception as err: - logger.error(err) - logger.error("Can't query an approved domain while attempting a DA reject_with_prejudice()") + self.delete_and_clean_up_domain("reject_with_prejudice") self.creator.restrict_user() diff --git a/src/registrar/templates/admin/base_site.html b/src/registrar/templates/admin/base_site.html index c0884c912..f9ff23455 100644 --- a/src/registrar/templates/admin/base_site.html +++ b/src/registrar/templates/admin/base_site.html @@ -24,34 +24,57 @@ {% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} {% block extrastyle %}{{ block.super }} - + {% endblock %} -{% block branding %} -