diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js index c68c31e15..0727c3401 100644 --- a/src/registrar/assets/js/get-gov.js +++ b/src/registrar/assets/js/get-gov.js @@ -2400,6 +2400,8 @@ document.addEventListener('DOMContentLoaded', function() { // Within the suborganization section, we also have a div that contains orgname, city, and stateterritory const suborganizationDetailsFieldset = document.querySelector("#requesting-entity-fieldset__suborganization__details"); + var isCustomSuborganization = document.querySelector("#id_portfolio_requesting_entity-is_custom_suborganization") + // Use a variable to determine which option has been selected on the yes/no form. // Don't do anything if we are missing crucial page elements @@ -2421,8 +2423,10 @@ document.addEventListener('DOMContentLoaded', function() { // We should hide the org name fields when we select the special other value if (subOrgSelect.value === "other") { showElement(suborganizationDetailsFieldset); + isCustomSuborganization.value = "True"; } else { hideElement(suborganizationDetailsFieldset); + isCustomSuborganization.value = "False"; } }; @@ -2434,6 +2438,10 @@ document.addEventListener('DOMContentLoaded', function() { subOrgSelect.add(fakeOption); } + if (isCustomSuborganization.value === "True") { + subOrgSelect.value = "other" + } + // Add event listener to is_suborganization radio buttons isSuborgRadios.forEach(radio => { // Run this here for initial display. diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py index a348029a9..d401360b8 100644 --- a/src/registrar/forms/domain_request_wizard.py +++ b/src/registrar/forms/domain_request_wizard.py @@ -61,6 +61,9 @@ class RequestingEntityForm(RegistrarForm): ) ) + # Add a hidden field to store that we are adding a custom suborg + is_custom_suborganization = forms.BooleanField(required=False, widget=forms.HiddenInput()) + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -68,52 +71,52 @@ class RequestingEntityForm(RegistrarForm): self.fields["sub_organization"].queryset = Suborganization.objects.filter(portfolio=self.domain_request.portfolio) def clean_sub_organization(self): - """Require something to be selected when this is a federal agency.""" - is_suborganization = self.cleaned_data.get("is_suborganization", None) - sub_organization = self.cleaned_data.get("sub_organization", None) - print(f"sub org is: {sub_organization} vs is_suborg: {is_suborganization}") - if is_suborganization and not sub_organization: - raise forms.ValidationError( - "Select a suborganization.", - code="required", - ) + sub_organization = self.cleaned_data.get("sub_organization") + is_custom = self.cleaned_data.get("is_custom_suborganization") + print(f"in clean: {sub_organization}") + if is_custom: + # If it's a custom suborganization, return None (equivalent to selecting nothing) + return None return sub_organization - def clean_requested_suborganization(self): - field = self.cleaned_data.get("requested_suborganization") - if self.is_custom_suborg() and not field: - raise forms.ValidationError( - "Enter details for your organization name.", - code="required", - ) - return field + def full_clean(self): + # Remove the custom other field before cleaning + data = self.data.copy() if self.data else None + suborganization = self.data.get('portfolio_requesting_entity-sub_organization') + is_suborganization = self.data.get("portfolio_requesting_entity-is_suborganization") + if suborganization: + if "other" in data['portfolio_requesting_entity-sub_organization']: + # Remove the 'other' value + data['portfolio_requesting_entity-sub_organization'] = "" + + # Set the modified data back to the form + self.data = data + + # Call the parent's full_clean method + super().full_clean() - def clean_suborganization_city(self): - field = self.cleaned_data.get("suborganization_city") - if self.is_custom_suborg(): - if not field: - raise forms.ValidationError( - "Enter details for your city.", - code="required", - ) - return field + def clean(self): + """Custom clean implementation to handle our desired logic flow for suborganization. + Given that these fields often corely on eachother, we need to do this in the parent function.""" + cleaned_data = super().clean() - def clean_suborganization_state_territory(self): - field = self.cleaned_data.get("suborganization_state_territory") - if self.is_custom_suborg(): - if not field: - raise forms.ValidationError( - "Enter details for your state or territory.", - code="required", - ) - return field - - def is_custom_suborg(self): - """Checks that the select suborg is 'other', which is a custom field indicating - that we should create a new suborganization.""" + suborganization = self.cleaned_data.get("sub_organization") is_suborganization = self.cleaned_data.get("is_suborganization") - sub_organization = self.cleaned_data.get("sub_organization") - return is_suborganization and sub_organization == "other" + is_custom_suborganization = self.cleaned_data.get("is_custom_suborganization") + if is_suborganization: + if is_custom_suborganization: + # Validate custom suborganization fields + if not cleaned_data.get("requested_suborganization"): + self.add_error("requested_suborganization", "Enter details for your organization name.") + if not cleaned_data.get("suborganization_city"): + self.add_error("suborganization_city", "Enter details for your city.") + if not cleaned_data.get("suborganization_state_territory"): + self.add_error("suborganization_state_territory", "Enter details for your state or territory.") + elif not suborganization: + self.add_error("sub_organization", "Select a suborganization.") + + cleaned_data = super().clean() + return cleaned_data class RequestingEntityYesNoForm(BaseYesNoForm): diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py index c19addd61..e9ba3d7bf 100644 --- a/src/registrar/models/domain_request.py +++ b/src/registrar/models/domain_request.py @@ -1210,6 +1210,12 @@ class DomainRequest(TimeStampedModel): return True return False + def is_custom_suborganization(self) -> bool: + if self.is_suborganization(): + return not self.sub_organization and self.has_information_required_to_make_suborganization() + else: + return False + def has_information_required_to_make_suborganization(self): """Checks if we have all the information we need to create a new suborganization object. Checks for a the existence of requested_suborganization, suborganization_city, suborganization_state_territory""" diff --git a/src/registrar/templates/domain_request_requesting_entity.html b/src/registrar/templates/domain_request_requesting_entity.html index 144ab77bf..70db337de 100644 --- a/src/registrar/templates/domain_request_requesting_entity.html +++ b/src/registrar/templates/domain_request_requesting_entity.html @@ -12,13 +12,17 @@

Who will use the domain you’re requesting?

+

+ Select one. * +

+ {# forms.0 is a small yes/no form that toggles the visibility of "requesting entity" formset #} {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} {% with attr_required=True %} {% input_with_errors forms.0.is_suborganization %} {% endwith %} {% endwith %} - + {% input_with_errors forms.1.is_custom_suborganization %}

Add suborganization information

diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index f0baa9828..f6f9b9373 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -602,15 +602,6 @@ class RequestingEntity(DomainRequestWizard): if is_suborganization and (sub_organization or requested_suborganization): # Cleanup the organization name field, as this isn't for suborganizations. self.domain_request.organization_name = None - - # Create or get the Suborganization. - # Then update the domain_request with the new or existing suborganization - if not sub_organization: - sub_organization, created = Suborganization.objects.get_or_create( - name=cleaned_data.get("requested_suborganization"), - portfolio=self.domain_request.portfolio, - ) - self.domain_request.sub_organization = sub_organization else: # If the user doesn't intend to create a suborg, simply don't make one and do some data cleanup