diff --git a/src/registrar/admin.py b/src/registrar/admin.py index d724a91fd..5cfacc172 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -836,7 +836,7 @@ class DomainApplicationAdminForm(forms.ModelForm): # Check if an investigator is assigned. No approval is possible without one. if investigator is not None: if not investigator.is_staff: - # Investigators must be staff users. + # Investigators must be staff users. # This is handled elsewhere, but we should check here as a precaution. error_message = ApplicationStatusError.get_error_message(FSMErrorCodes.APPROVE_INVESTIGATOR_NOT_STAFF) elif investigator != current_user and not is_superuser: @@ -847,7 +847,7 @@ class DomainApplicationAdminForm(forms.ModelForm): ) else: error_message = ApplicationStatusError.get_error_message(FSMErrorCodes.APPROVE_NO_INVESTIGATOR) - + # Add the error if error_message is not None: self.add_error("investigator", error_message) @@ -1003,14 +1003,14 @@ class DomainApplicationAdmin(ListHeaderAdmin): """ # Call the superclass's get_form method to get the form class da_form = super().get_form(request, obj, **kwargs) - + # Define a wrapper class for the form that includes the request in its initialization. # This is needed such that we can inject request without otherwise altering it. class DomainApplicationFormWrapper(da_form): def __new__(cls, *args, **form_kwargs): form_kwargs["request"] = request return da_form(*args, **form_kwargs) - + return DomainApplicationFormWrapper # Trigger action when a fieldset is changed @@ -1030,7 +1030,7 @@ class DomainApplicationAdmin(ListHeaderAdmin): ) return None - + if change: # Get the original application from the database original_obj = models.DomainApplication.objects.get(pk=obj.pk) diff --git a/src/registrar/models/domain_application.py b/src/registrar/models/domain_application.py index 5f4ce8a01..19f82101e 100644 --- a/src/registrar/models/domain_application.py +++ b/src/registrar/models/domain_application.py @@ -743,7 +743,7 @@ class DomainApplication(TimeStampedModel): if self.investigator is None: raise ApplicationStatusError(code=FSMErrorCodes.APPROVE_NO_INVESTIGATOR) - # Investigators must be staff users. + # Investigators must be staff users. # This is handled elsewhere, but we should check here as a precaution. if not self.investigator.is_staff: raise ApplicationStatusError(code=FSMErrorCodes.APPROVE_INVESTIGATOR_NOT_STAFF) diff --git a/src/registrar/tests/common.py b/src/registrar/tests/common.py index 17833d689..35c093ad5 100644 --- a/src/registrar/tests/common.py +++ b/src/registrar/tests/common.py @@ -530,6 +530,7 @@ def completed_application( user=False, submitter=False, name="city.gov", + investigator=None, ): """A completed domain application.""" if not user: @@ -574,6 +575,7 @@ def completed_application( submitter=submitter, creator=user, status=status, + investigator=investigator, ) if has_about_your_organization: domain_application_kwargs["about_your_organization"] = "e-Government" diff --git a/src/registrar/tests/test_models.py b/src/registrar/tests/test_models.py index cb7906d7a..433ad98ab 100644 --- a/src/registrar/tests/test_models.py +++ b/src/registrar/tests/test_models.py @@ -27,29 +27,30 @@ from django_fsm import TransitionNotAllowed @boto3_mocking.patching class TestDomainApplication(TestCase): def setUp(self): + user, _ = User.objects.get_or_create(username="testpancakesyrup", is_staff=True) self.started_application = completed_application( - status=DomainApplication.ApplicationStatus.STARTED, name="started.gov" + status=DomainApplication.ApplicationStatus.STARTED, name="started.gov", investigator=user ) self.submitted_application = completed_application( - status=DomainApplication.ApplicationStatus.SUBMITTED, name="submitted.gov" + status=DomainApplication.ApplicationStatus.SUBMITTED, name="submitted.gov", investigator=user ) self.in_review_application = completed_application( - status=DomainApplication.ApplicationStatus.IN_REVIEW, name="in-review.gov" + status=DomainApplication.ApplicationStatus.IN_REVIEW, name="in-review.gov", investigator=user ) self.action_needed_application = completed_application( - status=DomainApplication.ApplicationStatus.ACTION_NEEDED, name="action-needed.gov" + status=DomainApplication.ApplicationStatus.ACTION_NEEDED, name="action-needed.gov", investigator=user ) self.approved_application = completed_application( - status=DomainApplication.ApplicationStatus.APPROVED, name="approved.gov" + status=DomainApplication.ApplicationStatus.APPROVED, name="approved.gov", investigator=user ) self.withdrawn_application = completed_application( - status=DomainApplication.ApplicationStatus.WITHDRAWN, name="withdrawn.gov" + status=DomainApplication.ApplicationStatus.WITHDRAWN, name="withdrawn.gov", investigator=user ) self.rejected_application = completed_application( - status=DomainApplication.ApplicationStatus.REJECTED, name="rejected.gov" + status=DomainApplication.ApplicationStatus.REJECTED, name="rejected.gov", investigator=user ) self.ineligible_application = completed_application( - status=DomainApplication.ApplicationStatus.INELIGIBLE, name="ineligible.gov" + status=DomainApplication.ApplicationStatus.INELIGIBLE, name="ineligible.gov", investigator=user ) self.mock_client = MockSESClient() @@ -161,7 +162,7 @@ class TestDomainApplication(TestCase): application.submit() self.assertEqual(application.status, application.ApplicationStatus.SUBMITTED) - def check_email_sent(self, application, msg, action, expected_count): + def check_email_sent(self, application: DomainApplication, msg, action, expected_count): """Check if an email was sent after performing an action.""" with self.subTest(msg=msg, action=action): @@ -169,7 +170,14 @@ class TestDomainApplication(TestCase): with less_console_noise(): # Perform the specified action action_method = getattr(application, action) - action_method() + if action == "approve" and not application.investigator: + user, _ = User.objects.get_or_create(username="testwafflesyrup", is_staff=True) + application.investigator = user + application.save() + application.refresh_from_db() + action_method() + else: + action_method() # Check if an email was sent sent_emails = [ @@ -616,7 +624,10 @@ class TestPermissions(TestCase): def test_approval_creates_role(self): draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov") user, _ = User.objects.get_or_create() - application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain) + investigator, _ = User.objects.get_or_create(username="frenchtoast", is_staff=True) + application = DomainApplication.objects.create( + creator=user, requested_domain=draft_domain, investigator=investigator + ) with boto3_mocking.clients.handler_for("sesv2", self.mock_client): with less_console_noise(): @@ -650,7 +661,10 @@ class TestDomainInformation(TestCase): self.maxDiff = None draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov") user, _ = User.objects.get_or_create() - application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain, notes="test notes") + investigator, _ = User.objects.get_or_create(username="frenchtoast", is_staff=True) + application = DomainApplication.objects.create( + creator=user, requested_domain=draft_domain, notes="test notes", investigator=investigator + ) with boto3_mocking.clients.handler_for("sesv2", self.mock_client): with less_console_noise(): diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index 2bd581734..b59d548db 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -270,7 +270,10 @@ class TestDomainCreation(MockEppLib): """ draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov") user, _ = User.objects.get_or_create() - application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain) + investigator, _ = User.objects.get_or_create(username="frenchtoast", is_staff=True) + application = DomainApplication.objects.create( + creator=user, requested_domain=draft_domain, investigator=investigator + ) mock_client = MockSESClient() with boto3_mocking.clients.handler_for("sesv2", mock_client):