diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 2d6559570..7bb3fb229 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -216,6 +216,7 @@ class DomainRequestAdminForm(forms.ModelForm): status = cleaned_data.get("status") investigator = cleaned_data.get("investigator") rejection_reason = cleaned_data.get("rejection_reason") + action_needed_reason = cleaned_data.get("action_needed_reason") # Get the old status initial_status = self.initial.get("status", None) @@ -239,6 +240,8 @@ class DomainRequestAdminForm(forms.ModelForm): # If the status is rejected, a rejection reason must exist if status == DomainRequest.DomainRequestStatus.REJECTED: self._check_for_valid_rejection_reason(rejection_reason) + elif status == DomainRequest.DomainRequestStatus.IN_REVIEW: + self._check_for_valid_action_needed_reason(action_needed_reason) return cleaned_data @@ -262,6 +265,23 @@ class DomainRequestAdminForm(forms.ModelForm): return is_valid + def _check_for_valid_action_needed_reason(self, action_needed_reason) -> bool: + """ + Checks if the action_needed_reason field is not none. + Adds form errors on failure. + """ + is_valid = False + error_message = None + if action_needed_reason is None or action_needed_reason == "": + error_message = FSMDomainRequestError.get_error_message(FSMErrorCodes.NO_ACTION_NEEDED_REASON) + else: + is_valid = True + + if error_message is not None: + self.add_error("action_needed_reason", error_message) + + return is_valid + def _check_for_valid_investigator(self, investigator) -> bool: """ Checks if the investigator field is not none, and is staff. @@ -1361,6 +1381,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): "fields": [ "status", "rejection_reason", + "action_needed_reason", "investigator", "creator", "submitter", diff --git a/src/registrar/migrations/0096_domainrequest_action_needed_reason.py b/src/registrar/migrations/0096_domainrequest_action_needed_reason.py new file mode 100644 index 000000000..c8f729f69 --- /dev/null +++ b/src/registrar/migrations/0096_domainrequest_action_needed_reason.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.10 on 2024-05-31 20:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("registrar", "0095_user_middle_name_user_title"), + ] + + operations = [ + migrations.AddField( + model_name="domainrequest", + name="action_needed_reason", + field=models.TextField( + blank=True, + choices=[ + ("eligibility_unclear", "Unclear organization eligibility"), + ("questionable_authorizing_official", "Questionable authorizing official"), + ("ALREADY_HAS_DOMAINS", "Already has domains"), + ("bad_name", "Doesn’t meet naming requirements"), + ("other", "Other (no auto-email sent)"), + ], + null=True, + ), + ), + ] diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py index 2501cdc87..4a970fb06 100644 --- a/src/registrar/models/domain_request.py +++ b/src/registrar/models/domain_request.py @@ -244,6 +244,14 @@ class DomainRequest(TimeStampedModel): ORGANIZATION_ELIGIBILITY = "org_not_eligible", "Org not eligible for a .gov domain" NAMING_REQUIREMENTS = "naming_not_met", "Naming requirements not met" OTHER = "other", "Other/Unspecified" + + class ActionNeededReasons(models.TextChoices): + """Defines common""" + ELIGIBILITY_UNCLEAR = ("eligibility_unclear", "Unclear organization eligibility") + QUESTIONABLE_AUTHORIZING_OFFICIAL = ("questionable_authorizing_official" , "Questionable authorizing official") + ALREADY_HAS_DOMAINS = ("ALREADY_HAS_DOMAINS", "Already has domains") + BAD_NAME = ("bad_name", "Doesn’t meet naming requirements") + OTHER = ("other", "Other (no auto-email sent)") # #### Internal fields about the domain request ##### status = FSMField( @@ -258,6 +266,12 @@ class DomainRequest(TimeStampedModel): blank=True, ) + action_needed_reason = models.TextField( + choices=ActionNeededReasons.choices, + null=True, + blank=True, + ) + federal_agency = models.ForeignKey( "registrar.FederalAgency", on_delete=models.PROTECT, diff --git a/src/registrar/utility/errors.py b/src/registrar/utility/errors.py index f00c59bd0..740651c04 100644 --- a/src/registrar/utility/errors.py +++ b/src/registrar/utility/errors.py @@ -79,6 +79,7 @@ class FSMErrorCodes(IntEnum): - 3 INVESTIGATOR_NOT_STAFF Investigator is a non-staff user - 4 INVESTIGATOR_NOT_SUBMITTER The form submitter is not the investigator - 5 NO_REJECTION_REASON No rejection reason is specified + - 6 NO_ACTION_NEEDED_REASON No action needed reason is specified """ APPROVE_DOMAIN_IN_USE = 1 @@ -86,6 +87,7 @@ class FSMErrorCodes(IntEnum): INVESTIGATOR_NOT_STAFF = 3 INVESTIGATOR_NOT_SUBMITTER = 4 NO_REJECTION_REASON = 5 + NO_ACTION_NEEDED_REASON = 6 class FSMDomainRequestError(Exception): @@ -100,6 +102,7 @@ class FSMDomainRequestError(Exception): FSMErrorCodes.INVESTIGATOR_NOT_STAFF: ("Investigator is not a staff user."), FSMErrorCodes.INVESTIGATOR_NOT_SUBMITTER: ("Only the assigned investigator can make this change."), FSMErrorCodes.NO_REJECTION_REASON: ("A rejection reason is required."), + FSMErrorCodes.NO_ACTION_NEEDED_REASON: ("A action needed reason is required."), } def __init__(self, *args, code=None, **kwargs):