Repository: cisagov/manage.get.gov

Issue:
Prevent users from submitting multiple applications (under certain circumstances)
### Story

As a domain applicant 
I want to be prohibited from submitting a new request when I have an request in the statuses of: _Submitted, In Review, or Action Needed_ and I have no approved requests.
so that non-verified users cannot have multiple applications.


### Acceptance Criteria

- [ ] (Condition 1) A user is _not_ permitted to **submit** a new domain request: if the user has no approved requests(s) **AND** they have a request in the _Submitted, In Review, or Action Needed_ status.
- [ ] A user in "condition 1" may always **start** a new request, which may be saved as a draft if it cannot be submitted, per these rules.
- [ ] A user in "condition 1" will see an alert, which persists on each of the pages of new requests, that informs the user that they cannot submit the request because they currently have a pending request. The pending request is identified in the alert and there will be a link in the alert to take you back to the dashboard.
- [ ] The final "Submit domain request" button on the final review page is replaced with an outlined button with the CTA 'Save and return to manage your domains.' This button takes you back to the Dashboard, and the draft is saved.
- [ ] Unit Tests are completed and up-to-date


### Additional Context


### Issue Links
[Figma prototype with alert messaging and final button copy/styling](https://www.figma.com/proto/aJbuDLJNNikqQObTuCNKQa/GetGov_Designs_ECS-Truss?page-id=4829%3A39692&type=design&node-id=754-29647&viewport=1151%2C-64%2C0.28&t=06tdmsLsE9S8vmBx-1&scaling=min-zoom&starting-point-node-id=754%3A29647&show-proto-sidebar=1&mode=design)

Relates to: check #896 


Discussion:
Reference: https://miro.com/app/board/uXjVM3jz3Bs=/?moveToWidget=3458764559100173150&cot=14
I think this one needs to move to a later sprint at least 33, thoughts @PaulKuykendall and @vickyszuchin . It doesn't meet priorities for the next two sprints, interested in thoughts though.
Pulled this out of Sprint 31, and to backlog. This will be reprioritized for a future slice/sprint.

Resolving patch:
diff --git a/src/registrar/views/application.py b/src/registrar/views/application.py
--- a/src/registrar/views/application.py
+++ b/src/registrar/views/application.py
@@ -3,6 +3,7 @@
 from django.http import Http404, HttpResponse, HttpResponseRedirect
 from django.shortcuts import redirect, render
 from django.urls import resolve, reverse
+from django.utils.safestring import mark_safe
 from django.utils.translation import gettext_lazy as _
 from django.views.generic import TemplateView
 from django.contrib import messages
@@ -218,6 +219,23 @@ def get(self, request, *args, **kwargs):
         self.steps.current = current_url
         context = self.get_context_data()
         context["forms"] = self.get_forms()
+
+        # if pending requests exist and user does not have approved domains,
+        # present message that domain application cannot be submitted
+        pending_requests = self.pending_requests()
+        if len(pending_requests) > 0:
+            message_header = "You cannot submit this request yet"
+            message_content = (
+                f"<h4 class='usa-alert__heading'>{message_header}</h4> "
+                "<p class='margin-bottom-0'>New domain requests cannot be submitted until we have finished "
+                f"reviewing your pending request: <strong>{pending_requests[0].requested_domain}</strong>. "
+                "You can continue to fill out this request and save it as a draft to be submitted later. "
+                f"<a class='usa-link' href='{reverse('home')}'>View your pending requests.</a></p>"
+            )
+            context["pending_requests_message"] = mark_safe(message_content)  # nosec
+
+        context["pending_requests_exist"] = len(pending_requests) > 0
+
         return render(request, self.template_name, context)
 
     def get_all_forms(self, **kwargs) -> list:
@@ -266,6 +284,37 @@ def get_forms(self, step=None, use_post=False, use_db=False, files=None):
 
         return instantiated
 
+    def pending_requests(self):
+        """return an array of pending requests if user has pending requests
+        and no approved requests"""
+        if self.approved_applications_exist() or self.approved_domains_exist():
+            return []
+        else:
+            return self.pending_applications()
+
+    def approved_applications_exist(self):
+        """Checks if user is creator of applications with APPROVED status"""
+        approved_application_count = DomainApplication.objects.filter(
+            creator=self.request.user, status=DomainApplication.APPROVED
+        ).count()
+        return approved_application_count > 0
+
+    def approved_domains_exist(self):
+        """Checks if user has permissions on approved domains
+
+        This additional check is necessary to account for domains which were migrated
+        and do not have an application"""
+        return self.request.user.permissions.count() > 0
+
+    def pending_applications(self):
+        """Returns a List of user's applications with one of the following states:
+        SUBMITTED, IN_REVIEW, ACTION_NEEDED"""
+        # if the current application has ACTION_NEEDED status, this check should not be performed
+        if self.application.status == DomainApplication.ACTION_NEEDED:
+            return []
+        check_statuses = [DomainApplication.SUBMITTED, DomainApplication.IN_REVIEW, DomainApplication.ACTION_NEEDED]
+        return DomainApplication.objects.filter(creator=self.request.user, status__in=check_statuses)
+
     def get_context_data(self):
         """Define context for access on all wizard pages."""
         return {
@@ -328,6 +377,10 @@ def post(self, request, *args, **kwargs) -> HttpResponse:
         if button == "save":
             messages.success(request, "Your progress has been saved!")
             return self.goto(self.steps.current)
+        # if user opted to save progress and return,
+        # return them to the home page
+        if button == "save_and_return":
+            return HttpResponseRedirect(reverse("home"))
         # otherwise, proceed as normal
         return self.goto_next_step()
 


Test patch:
diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py
--- a/src/registrar/tests/test_views.py
+++ b/src/registrar/tests/test_views.py
@@ -144,6 +144,18 @@ def test_application_form_empty_submit(self):
         result = page.form.submit()
         self.assertIn("What kind of U.S.-based government organization do you represent?", result)
 
+    def test_application_multiple_applications_exist(self):
+        """Test that an info message appears when user has multiple applications already"""
+        # create and submit an application
+        application = completed_application(user=self.user)
+        application.submit()
+        application.save()
+
+        # now, attempt to create another one
+        with less_console_noise():
+            page = self.app.get("/register/").follow()
+            self.assertContains(page, "You cannot submit this request yet")
+
     @boto3_mocking.patching
     def test_application_form_submission(self):
         """