+
{% with attr_required=True %}
{% input_with_errors forms.1.requested_suborganization %}
{% endwith %}
diff --git a/src/registrar/templates/domain_request_status.html b/src/registrar/templates/domain_request_status.html
index d98220532..d332ce54e 100644
--- a/src/registrar/templates/domain_request_status.html
+++ b/src/registrar/templates/domain_request_status.html
@@ -6,9 +6,5 @@
{% block content %}
- {% if not portfolio %}
- {% include "includes/request_status_manage.html" %}
- {% else %}
- {% include "includes/portfolio_status_manage.html" %}
- {% endif %}
+ {% include "includes/request_status_manage.html" %}
{% endblock %}
diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html
index c2bdb18cc..ed727fee8 100644
--- a/src/registrar/templates/includes/portfolio_request_review_steps.html
+++ b/src/registrar/templates/includes/portfolio_request_review_steps.html
@@ -8,28 +8,24 @@
{% endif %}
{% if step == Step.REQUESTING_ENTITY %}
- {% if domain_request.portfolio and domain_request.organization_name == domain_request.portfolio.organization_name %}
- {% with title=form_titles|get_item:step value=domain_request.portfolio.organization_name %}
- {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %}
- {% endwith %}
+ {% with title=form_titles|get_item:step %}
+ {% if domain_request.sub_organization %}
+ {% include "includes/summary_item.html" with value=domain_request.sub_organization edit_link=domain_request_url %}
+ {% comment %} We don't have city or state_territory for suborganizations yet, so no data should display {% endcomment %}
+ {% elif domain_request.requesting_entity_is_suborganization %}
+ {% include "includes/summary_item.html" with value=domain_request.requested_suborganization edit_link=domain_request_url %}
+
{{domain_request.suborganization_city}}, {{domain_request.suborganization_state_territory}}
+ {% elif domain_request.requesting_entity_is_portfolio %}
+ {% include "includes/summary_item.html" with value=domain_request.portfolio.organization_name edit_link=domain_request_url %}
{% if domain_request.portfolio.city and domain_request.portfolio.state_territory %}
{{domain_request.portfolio.city}}, {{domain_request.portfolio.state_territory}}
{% endif %}
- {% elif domain_request.sub_organization %}
- {% with title=form_titles|get_item:step value=domain_request.sub_organization %}
- {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %}
- {% endwith %}
- {% comment %} We don't have city or state_territory for suborganizations yet, so no data should display {% endcomment %}
- {% elif domain_request.requested_suborganization and domain_request.suborganization_city and domain_request.suborganization_state_territory %}
- {% with title=form_titles|get_item:step value=domain_request.requested_suborganization %}
- {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %}
- {% endwith %}
-
{{domain_request.suborganization_city}}, {{domain_request.suborganization_state_territory}}
{% else %}
- {% with title=form_titles|get_item:step value="
Incomplete "|safe %}
- {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %}
+ {% with value="
Incomplete "|safe %}
+ {% include "includes/summary_item.html" with edit_link=domain_request_url %}
{% endwith %}
{% endif %}
+ {% endwith %}
{% endif %}
{% if step == Step.CURRENT_SITES %}
diff --git a/src/registrar/templates/includes/portfolio_status_manage.html b/src/registrar/templates/includes/portfolio_status_manage.html
deleted file mode 100644
index 120770156..000000000
--- a/src/registrar/templates/includes/portfolio_status_manage.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "includes/request_status_manage.html" %}
-{% load custom_filters %}
-{% load static url_helpers %}
-
-{% block request_summary %}
- {% include "includes/portfolio_request_review_steps.html" with is_editable=False domain_request=DomainRequest %}
-{% endblock request_summary %}
diff --git a/src/registrar/templates/includes/request_status_manage.html b/src/registrar/templates/includes/request_status_manage.html
index 2a254df4b..fc2fd8f12 100644
--- a/src/registrar/templates/includes/request_status_manage.html
+++ b/src/registrar/templates/includes/request_status_manage.html
@@ -145,92 +145,96 @@
{% endblock request_summary_header%}
{% block request_summary %}
- {% with heading_level='h3' %}
- {% with org_type=DomainRequest.get_generic_org_type_display %}
- {% include "includes/summary_item.html" with title='Type of organization' value=org_type heading_level=heading_level %}
- {% endwith %}
-
- {% if DomainRequest.tribe_name %}
- {% include "includes/summary_item.html" with title='Tribal government' value=DomainRequest.tribe_name heading_level=heading_level %}
-
- {% if DomainRequest.federally_recognized_tribe %}
-
Federally-recognized tribe
- {% endif %}
-
- {% if DomainRequest.state_recognized_tribe %}
-
State-recognized tribe
- {% endif %}
-
- {% endif %}
-
- {% if DomainRequest.get_federal_type_display %}
- {% include "includes/summary_item.html" with title='Federal government branch' value=DomainRequest.get_federal_type_display heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.is_election_board %}
- {% with value=DomainRequest.is_election_board|yesno:"Yes,No,Incomplete" %}
- {% include "includes/summary_item.html" with title='Election office' value=value heading_level=heading_level %}
- {% endwith %}
- {% endif %}
-
- {% if DomainRequest.organization_name %}
- {% include "includes/summary_item.html" with title='Organization' value=DomainRequest address='true' heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.about_your_organization %}
- {% include "includes/summary_item.html" with title='About your organization' value=DomainRequest.about_your_organization heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.senior_official %}
- {% include "includes/summary_item.html" with title='Senior official' value=DomainRequest.senior_official contact='true' heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.current_websites.all %}
- {% include "includes/summary_item.html" with title='Current websites' value=DomainRequest.current_websites.all list='true' heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.requested_domain %}
- {% include "includes/summary_item.html" with title='.gov domain' value=DomainRequest.requested_domain heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.alternative_domains.all %}
- {% include "includes/summary_item.html" with title='Alternative domains' value=DomainRequest.alternative_domains.all list='true' heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.purpose %}
- {% include "includes/summary_item.html" with title='Purpose of your domain' value=DomainRequest.purpose heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.creator %}
- {% include "includes/summary_item.html" with title='Your contact information' value=DomainRequest.creator contact='true' heading_level=heading_level %}
- {% endif %}
-
- {% if DomainRequest.other_contacts.all %}
- {% include "includes/summary_item.html" with title='Other employees from your organization' value=DomainRequest.other_contacts.all contact='true' list='true' heading_level=heading_level %}
+ {% if portfolio %}
+ {% include "includes/portfolio_request_review_steps.html" with is_editable=False domain_request=DomainRequest %}
{% else %}
- {% include "includes/summary_item.html" with title='Other employees from your organization' value=DomainRequest.no_other_contacts_rationale heading_level=heading_level %}
- {% endif %}
+ {% with heading_level='h3' %}
+ {% with org_type=DomainRequest.get_generic_org_type_display %}
+ {% include "includes/summary_item.html" with title='Type of organization' value=org_type heading_level=heading_level %}
+ {% endwith %}
- {# We always show this field even if None #}
- {% if DomainRequest %}
-
-
-
-
- {% if DomainRequest.anything_else %}
- {{DomainRequest.anything_else}}
- {% else %}
- No
+
+ {% if DomainRequest.state_recognized_tribe %}
+ State-recognized tribe
{% endif %}
-
- {% endif %}
- {% endwith %}
+
+ {% endif %}
+
+ {% if DomainRequest.get_federal_type_display %}
+ {% include "includes/summary_item.html" with title='Federal government branch' value=DomainRequest.get_federal_type_display heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.is_election_board %}
+ {% with value=DomainRequest.is_election_board|yesno:"Yes,No,Incomplete" %}
+ {% include "includes/summary_item.html" with title='Election office' value=value heading_level=heading_level %}
+ {% endwith %}
+ {% endif %}
+
+ {% if DomainRequest.organization_name %}
+ {% include "includes/summary_item.html" with title='Organization' value=DomainRequest address='true' heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.about_your_organization %}
+ {% include "includes/summary_item.html" with title='About your organization' value=DomainRequest.about_your_organization heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.senior_official %}
+ {% include "includes/summary_item.html" with title='Senior official' value=DomainRequest.senior_official contact='true' heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.current_websites.all %}
+ {% include "includes/summary_item.html" with title='Current websites' value=DomainRequest.current_websites.all list='true' heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.requested_domain %}
+ {% include "includes/summary_item.html" with title='.gov domain' value=DomainRequest.requested_domain heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.alternative_domains.all %}
+ {% include "includes/summary_item.html" with title='Alternative domains' value=DomainRequest.alternative_domains.all list='true' heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.purpose %}
+ {% include "includes/summary_item.html" with title='Purpose of your domain' value=DomainRequest.purpose heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.creator %}
+ {% include "includes/summary_item.html" with title='Your contact information' value=DomainRequest.creator contact='true' heading_level=heading_level %}
+ {% endif %}
+
+ {% if DomainRequest.other_contacts.all %}
+ {% include "includes/summary_item.html" with title='Other employees from your organization' value=DomainRequest.other_contacts.all contact='true' list='true' heading_level=heading_level %}
+ {% else %}
+ {% include "includes/summary_item.html" with title='Other employees from your organization' value=DomainRequest.no_other_contacts_rationale heading_level=heading_level %}
+ {% endif %}
+
+ {# We always show this field even if None #}
+ {% if DomainRequest %}
+
+
+ {% if DomainRequest.cisa_representative_first_name %}
+ {{ DomainRequest.get_formatted_cisa_rep_name }}
+ {% else %}
+ No
+ {% endif %}
+
+
+
+ {% if DomainRequest.anything_else %}
+ {{DomainRequest.anything_else}}
+ {% else %}
+ No
+ {% endif %}
+
+ {% endif %}
+ {% endwith %}
+ {% endif %}
{% endblock request_summary%}
\ No newline at end of file
diff --git a/src/registrar/templatetags/custom_filters.py b/src/registrar/templatetags/custom_filters.py
index 50ff6c842..bd977d581 100644
--- a/src/registrar/templatetags/custom_filters.py
+++ b/src/registrar/templatetags/custom_filters.py
@@ -268,17 +268,17 @@ def display_requesting_entity(domain_request):
Boise, ID
"""
display = ""
- if domain_request.portfolio and domain_request.organization_name == domain_request.portfolio.organization_name:
- display = (
- f"{domain_request.portfolio.organization_name}\n"
- f"{domain_request.portfolio.city}, {domain_request.portfolio.state_territory}"
- )
- elif domain_request.sub_organization:
+ if domain_request.sub_organization:
display = domain_request.sub_organization
- elif domain_request.has_information_required_to_make_suborganization():
+ elif domain_request.requesting_entity_is_suborganization():
display = (
f"{domain_request.requested_suborganization}\n"
f"{domain_request.suborganization_city}, {domain_request.suborganization_state_territory}"
)
+ elif domain_request.requesting_entity_is_portfolio():
+ display = (
+ f"{domain_request.portfolio.organization_name}\n"
+ f"{domain_request.portfolio.city}, {domain_request.portfolio.state_territory}"
+ )
return display
diff --git a/src/registrar/tests/test_views_portfolio.py b/src/registrar/tests/test_views_portfolio.py
index 2469653bf..1ca2d2bcd 100644
--- a/src/registrar/tests/test_views_portfolio.py
+++ b/src/registrar/tests/test_views_portfolio.py
@@ -1685,9 +1685,9 @@ class TestRequestingEntity(WebTest):
form = response.forms[0]
# Test selecting an existing suborg
- form["portfolio_requesting_entity-is_suborganization"] = True
+ form["portfolio_requesting_entity-requesting_entity_is_suborganization"] = True
form["portfolio_requesting_entity-sub_organization"] = f"{self.suborganization.id}"
- form["portfolio_requesting_entity-is_custom_suborganization"] = False
+ form["portfolio_requesting_entity-is_requesting_new_suborganization"] = False
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
@@ -1718,8 +1718,8 @@ class TestRequestingEntity(WebTest):
form = response.forms[0]
# Test selecting an existing suborg
- form["portfolio_requesting_entity-is_suborganization"] = True
- form["portfolio_requesting_entity-is_custom_suborganization"] = True
+ form["portfolio_requesting_entity-requesting_entity_is_suborganization"] = True
+ form["portfolio_requesting_entity-is_requesting_new_suborganization"] = True
form["portfolio_requesting_entity-sub_organization"] = ""
form["portfolio_requesting_entity-requested_suborganization"] = "moon"
@@ -1759,7 +1759,7 @@ class TestRequestingEntity(WebTest):
form = response.forms[0]
# Test selecting an existing suborg
- form["portfolio_requesting_entity-is_suborganization"] = False
+ form["portfolio_requesting_entity-requesting_entity_is_suborganization"] = False
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
@@ -1784,7 +1784,7 @@ class TestRequestingEntity(WebTest):
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
# Test missing suborganization selection
- form["portfolio_requesting_entity-is_suborganization"] = True
+ form["portfolio_requesting_entity-requesting_entity_is_suborganization"] = True
form["portfolio_requesting_entity-sub_organization"] = ""
response = form.submit()
@@ -1792,7 +1792,7 @@ class TestRequestingEntity(WebTest):
self.assertContains(response, "Select a suborganization.", status_code=200)
# Test missing custom suborganization details
- form["portfolio_requesting_entity-is_custom_suborganization"] = True
+ form["portfolio_requesting_entity-is_requesting_new_suborganization"] = True
response = form.submit()
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
self.assertContains(response, "Enter details for your organization name.", status_code=200)
diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py
index d39833fab..16ca7a69f 100644
--- a/src/registrar/views/domain_request.py
+++ b/src/registrar/views/domain_request.py
@@ -596,13 +596,13 @@ class RequestingEntity(DomainRequestWizard):
if the user selects one."""
requesting_entity_form = forms[1]
cleaned_data = requesting_entity_form.cleaned_data
- is_suborganization = cleaned_data.get("is_suborganization")
+ requesting_entity_is_suborganization = cleaned_data.get("requesting_entity_is_suborganization")
sub_organization = cleaned_data.get("sub_organization")
requested_suborganization = cleaned_data.get("requested_suborganization")
# If no suborganization presently exists but the user filled out
# org information then create a suborg automatically.
- if is_suborganization and (sub_organization or requested_suborganization):
+ if requesting_entity_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
self.domain_request.sub_organization = sub_organization
From ee71ba4c48d55648dfbbabb6763fe8aeb6d57deb Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 11:59:24 -0600
Subject: [PATCH 40/68] cleanup
---
src/registrar/assets/js/get-gov.js | 6 +-
src/registrar/forms/domain_request_wizard.py | 19 +-
...tion_requested_suborganization_and_more.py | 180 ------------------
src/registrar/views/domain_request.py | 2 -
4 files changed, 13 insertions(+), 194 deletions(-)
delete mode 100644 src/registrar/migrations/0135_domaininformation_requested_suborganization_and_more.py
diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js
index 6182bc828..81bb30e38 100644
--- a/src/registrar/assets/js/get-gov.js
+++ b/src/registrar/assets/js/get-gov.js
@@ -22,8 +22,7 @@ var SUCCESS = "success";
*
*/
const hideElement = (element) => {
- if (element && !element.classList.contains("display-none"))
- element.classList.add('display-none');
+ element.classList.add('display-none');
};
/**
@@ -31,8 +30,7 @@ const hideElement = (element) => {
*
*/
const showElement = (element) => {
- if (element && element.classList.contains("display-none"))
- element.classList.remove('display-none');
+ element.classList.remove('display-none');
};
/**
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index e6188eb33..2bc31fc37 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -27,21 +27,21 @@ class RequestingEntityForm(RegistrarForm):
All of these fields are not required by default, but as we use javascript to conditionally show
and hide some of these, they then become required in certain circumstances."""
- # Add a hidden field to store if the user is requesting a new suborganization
+ # Add a hidden field to store if the user is requesting a new suborganization.
+ # This hidden boolean is used for our javascript to communicate to us and to it.
+ # If true, the suborganization form will auto select a js value "Other".
+ # If this selection is made on the form (tracked by js), then it will toggle the form value of this.
+ # In other words, this essentially tracks if the suborganization field == "Other".
+ # "Other" is just an imaginary value that is otherwise invalid.
+ # Note the logic in `def clean` and line 2744 in get-gov.js
is_requesting_new_suborganization = forms.BooleanField(required=False, widget=forms.HiddenInput())
sub_organization = forms.ModelChoiceField(
label="Suborganization name",
- # not required because this field won't be filled out unless
- # it is a federal agency. Use clean to check programatically
- # if it has been filled in when required.
required=False,
queryset=Suborganization.objects.none(),
empty_label="--Select--",
)
-
- # We are using the current sub_organization naming convention here.
- # We may want to refactor this to suborganization eventually.
requested_suborganization = forms.CharField(
label="Requested suborganization",
required=False,
@@ -147,7 +147,10 @@ class RequestingEntityYesNoForm(BaseYesNoForm):
@property
def form_is_checked(self):
"""
- Determines the initial checked state of the form based on the domain_request's attributes.
+ Determines if the requesting entity is a suborganization, or a portfolio.
+ For suborganizations, users have the ability to request a new one if the
+ desired suborg doesn't exist. We expose additional fields that denote this,
+ like `requested_suborganization`. So we also check on those.
"""
if self.domain_request.requesting_entity_is_suborganization():
diff --git a/src/registrar/migrations/0135_domaininformation_requested_suborganization_and_more.py b/src/registrar/migrations/0135_domaininformation_requested_suborganization_and_more.py
deleted file mode 100644
index b82619c78..000000000
--- a/src/registrar/migrations/0135_domaininformation_requested_suborganization_and_more.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# Generated by Django 4.2.10 on 2024-10-24 16:30
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- (
- "registrar",
- "0134_rename_portfolio_additional_permissions_portfolioinvitation_additional_permissions_and_more",
- ),
- ]
-
- operations = [
- migrations.AddField(
- model_name="domaininformation",
- name="requested_suborganization",
- field=models.CharField(blank=True, null=True),
- ),
- migrations.AddField(
- model_name="domaininformation",
- name="suborganization_city",
- field=models.CharField(blank=True, null=True),
- ),
- migrations.AddField(
- model_name="domaininformation",
- name="suborganization_state_territory",
- field=models.CharField(
- blank=True,
- choices=[
- ("AL", "Alabama (AL)"),
- ("AK", "Alaska (AK)"),
- ("AS", "American Samoa (AS)"),
- ("AZ", "Arizona (AZ)"),
- ("AR", "Arkansas (AR)"),
- ("CA", "California (CA)"),
- ("CO", "Colorado (CO)"),
- ("CT", "Connecticut (CT)"),
- ("DE", "Delaware (DE)"),
- ("DC", "District of Columbia (DC)"),
- ("FL", "Florida (FL)"),
- ("GA", "Georgia (GA)"),
- ("GU", "Guam (GU)"),
- ("HI", "Hawaii (HI)"),
- ("ID", "Idaho (ID)"),
- ("IL", "Illinois (IL)"),
- ("IN", "Indiana (IN)"),
- ("IA", "Iowa (IA)"),
- ("KS", "Kansas (KS)"),
- ("KY", "Kentucky (KY)"),
- ("LA", "Louisiana (LA)"),
- ("ME", "Maine (ME)"),
- ("MD", "Maryland (MD)"),
- ("MA", "Massachusetts (MA)"),
- ("MI", "Michigan (MI)"),
- ("MN", "Minnesota (MN)"),
- ("MS", "Mississippi (MS)"),
- ("MO", "Missouri (MO)"),
- ("MT", "Montana (MT)"),
- ("NE", "Nebraska (NE)"),
- ("NV", "Nevada (NV)"),
- ("NH", "New Hampshire (NH)"),
- ("NJ", "New Jersey (NJ)"),
- ("NM", "New Mexico (NM)"),
- ("NY", "New York (NY)"),
- ("NC", "North Carolina (NC)"),
- ("ND", "North Dakota (ND)"),
- ("MP", "Northern Mariana Islands (MP)"),
- ("OH", "Ohio (OH)"),
- ("OK", "Oklahoma (OK)"),
- ("OR", "Oregon (OR)"),
- ("PA", "Pennsylvania (PA)"),
- ("PR", "Puerto Rico (PR)"),
- ("RI", "Rhode Island (RI)"),
- ("SC", "South Carolina (SC)"),
- ("SD", "South Dakota (SD)"),
- ("TN", "Tennessee (TN)"),
- ("TX", "Texas (TX)"),
- ("UM", "United States Minor Outlying Islands (UM)"),
- ("UT", "Utah (UT)"),
- ("VT", "Vermont (VT)"),
- ("VI", "Virgin Islands (VI)"),
- ("VA", "Virginia (VA)"),
- ("WA", "Washington (WA)"),
- ("WV", "West Virginia (WV)"),
- ("WI", "Wisconsin (WI)"),
- ("WY", "Wyoming (WY)"),
- ("AA", "Armed Forces Americas (AA)"),
- ("AE", "Armed Forces Africa, Canada, Europe, Middle East (AE)"),
- ("AP", "Armed Forces Pacific (AP)"),
- ],
- max_length=2,
- null=True,
- verbose_name="state, territory, or military post",
- ),
- ),
- migrations.AddField(
- model_name="domainrequest",
- name="requested_suborganization",
- field=models.CharField(blank=True, null=True),
- ),
- migrations.AddField(
- model_name="domainrequest",
- name="suborganization_city",
- field=models.CharField(blank=True, null=True),
- ),
- migrations.AddField(
- model_name="domainrequest",
- name="suborganization_state_territory",
- field=models.CharField(
- blank=True,
- choices=[
- ("AL", "Alabama (AL)"),
- ("AK", "Alaska (AK)"),
- ("AS", "American Samoa (AS)"),
- ("AZ", "Arizona (AZ)"),
- ("AR", "Arkansas (AR)"),
- ("CA", "California (CA)"),
- ("CO", "Colorado (CO)"),
- ("CT", "Connecticut (CT)"),
- ("DE", "Delaware (DE)"),
- ("DC", "District of Columbia (DC)"),
- ("FL", "Florida (FL)"),
- ("GA", "Georgia (GA)"),
- ("GU", "Guam (GU)"),
- ("HI", "Hawaii (HI)"),
- ("ID", "Idaho (ID)"),
- ("IL", "Illinois (IL)"),
- ("IN", "Indiana (IN)"),
- ("IA", "Iowa (IA)"),
- ("KS", "Kansas (KS)"),
- ("KY", "Kentucky (KY)"),
- ("LA", "Louisiana (LA)"),
- ("ME", "Maine (ME)"),
- ("MD", "Maryland (MD)"),
- ("MA", "Massachusetts (MA)"),
- ("MI", "Michigan (MI)"),
- ("MN", "Minnesota (MN)"),
- ("MS", "Mississippi (MS)"),
- ("MO", "Missouri (MO)"),
- ("MT", "Montana (MT)"),
- ("NE", "Nebraska (NE)"),
- ("NV", "Nevada (NV)"),
- ("NH", "New Hampshire (NH)"),
- ("NJ", "New Jersey (NJ)"),
- ("NM", "New Mexico (NM)"),
- ("NY", "New York (NY)"),
- ("NC", "North Carolina (NC)"),
- ("ND", "North Dakota (ND)"),
- ("MP", "Northern Mariana Islands (MP)"),
- ("OH", "Ohio (OH)"),
- ("OK", "Oklahoma (OK)"),
- ("OR", "Oregon (OR)"),
- ("PA", "Pennsylvania (PA)"),
- ("PR", "Puerto Rico (PR)"),
- ("RI", "Rhode Island (RI)"),
- ("SC", "South Carolina (SC)"),
- ("SD", "South Dakota (SD)"),
- ("TN", "Tennessee (TN)"),
- ("TX", "Texas (TX)"),
- ("UM", "United States Minor Outlying Islands (UM)"),
- ("UT", "Utah (UT)"),
- ("VT", "Vermont (VT)"),
- ("VI", "Virgin Islands (VI)"),
- ("VA", "Virginia (VA)"),
- ("WA", "Washington (WA)"),
- ("WV", "West Virginia (WV)"),
- ("WI", "Wisconsin (WI)"),
- ("WY", "Wyoming (WY)"),
- ("AA", "Armed Forces Americas (AA)"),
- ("AE", "Armed Forces Africa, Canada, Europe, Middle East (AE)"),
- ("AP", "Armed Forces Pacific (AP)"),
- ],
- max_length=2,
- null=True,
- verbose_name="state, territory, or military post",
- ),
- ),
- ]
diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py
index 16ca7a69f..209a6c100 100644
--- a/src/registrar/views/domain_request.py
+++ b/src/registrar/views/domain_request.py
@@ -600,8 +600,6 @@ class RequestingEntity(DomainRequestWizard):
sub_organization = cleaned_data.get("sub_organization")
requested_suborganization = cleaned_data.get("requested_suborganization")
- # If no suborganization presently exists but the user filled out
- # org information then create a suborg automatically.
if requesting_entity_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
From a94a5b20759f8cb3a5f9094fd4b512e7a81fdf3f Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 11:59:53 -0600
Subject: [PATCH 41/68] Readd migration after merge
---
...tion_requested_suborganization_and_more.py | 177 ++++++++++++++++++
1 file changed, 177 insertions(+)
create mode 100644 src/registrar/migrations/0136_domaininformation_requested_suborganization_and_more.py
diff --git a/src/registrar/migrations/0136_domaininformation_requested_suborganization_and_more.py b/src/registrar/migrations/0136_domaininformation_requested_suborganization_and_more.py
new file mode 100644
index 000000000..dc6ec9d5d
--- /dev/null
+++ b/src/registrar/migrations/0136_domaininformation_requested_suborganization_and_more.py
@@ -0,0 +1,177 @@
+# Generated by Django 4.2.10 on 2024-10-30 17:59
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("registrar", "0135_alter_federalagency_agency_and_more"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="domaininformation",
+ name="requested_suborganization",
+ field=models.CharField(blank=True, null=True),
+ ),
+ migrations.AddField(
+ model_name="domaininformation",
+ name="suborganization_city",
+ field=models.CharField(blank=True, null=True),
+ ),
+ migrations.AddField(
+ model_name="domaininformation",
+ name="suborganization_state_territory",
+ field=models.CharField(
+ blank=True,
+ choices=[
+ ("AL", "Alabama (AL)"),
+ ("AK", "Alaska (AK)"),
+ ("AS", "American Samoa (AS)"),
+ ("AZ", "Arizona (AZ)"),
+ ("AR", "Arkansas (AR)"),
+ ("CA", "California (CA)"),
+ ("CO", "Colorado (CO)"),
+ ("CT", "Connecticut (CT)"),
+ ("DE", "Delaware (DE)"),
+ ("DC", "District of Columbia (DC)"),
+ ("FL", "Florida (FL)"),
+ ("GA", "Georgia (GA)"),
+ ("GU", "Guam (GU)"),
+ ("HI", "Hawaii (HI)"),
+ ("ID", "Idaho (ID)"),
+ ("IL", "Illinois (IL)"),
+ ("IN", "Indiana (IN)"),
+ ("IA", "Iowa (IA)"),
+ ("KS", "Kansas (KS)"),
+ ("KY", "Kentucky (KY)"),
+ ("LA", "Louisiana (LA)"),
+ ("ME", "Maine (ME)"),
+ ("MD", "Maryland (MD)"),
+ ("MA", "Massachusetts (MA)"),
+ ("MI", "Michigan (MI)"),
+ ("MN", "Minnesota (MN)"),
+ ("MS", "Mississippi (MS)"),
+ ("MO", "Missouri (MO)"),
+ ("MT", "Montana (MT)"),
+ ("NE", "Nebraska (NE)"),
+ ("NV", "Nevada (NV)"),
+ ("NH", "New Hampshire (NH)"),
+ ("NJ", "New Jersey (NJ)"),
+ ("NM", "New Mexico (NM)"),
+ ("NY", "New York (NY)"),
+ ("NC", "North Carolina (NC)"),
+ ("ND", "North Dakota (ND)"),
+ ("MP", "Northern Mariana Islands (MP)"),
+ ("OH", "Ohio (OH)"),
+ ("OK", "Oklahoma (OK)"),
+ ("OR", "Oregon (OR)"),
+ ("PA", "Pennsylvania (PA)"),
+ ("PR", "Puerto Rico (PR)"),
+ ("RI", "Rhode Island (RI)"),
+ ("SC", "South Carolina (SC)"),
+ ("SD", "South Dakota (SD)"),
+ ("TN", "Tennessee (TN)"),
+ ("TX", "Texas (TX)"),
+ ("UM", "United States Minor Outlying Islands (UM)"),
+ ("UT", "Utah (UT)"),
+ ("VT", "Vermont (VT)"),
+ ("VI", "Virgin Islands (VI)"),
+ ("VA", "Virginia (VA)"),
+ ("WA", "Washington (WA)"),
+ ("WV", "West Virginia (WV)"),
+ ("WI", "Wisconsin (WI)"),
+ ("WY", "Wyoming (WY)"),
+ ("AA", "Armed Forces Americas (AA)"),
+ ("AE", "Armed Forces Africa, Canada, Europe, Middle East (AE)"),
+ ("AP", "Armed Forces Pacific (AP)"),
+ ],
+ max_length=2,
+ null=True,
+ verbose_name="state, territory, or military post",
+ ),
+ ),
+ migrations.AddField(
+ model_name="domainrequest",
+ name="requested_suborganization",
+ field=models.CharField(blank=True, null=True),
+ ),
+ migrations.AddField(
+ model_name="domainrequest",
+ name="suborganization_city",
+ field=models.CharField(blank=True, null=True),
+ ),
+ migrations.AddField(
+ model_name="domainrequest",
+ name="suborganization_state_territory",
+ field=models.CharField(
+ blank=True,
+ choices=[
+ ("AL", "Alabama (AL)"),
+ ("AK", "Alaska (AK)"),
+ ("AS", "American Samoa (AS)"),
+ ("AZ", "Arizona (AZ)"),
+ ("AR", "Arkansas (AR)"),
+ ("CA", "California (CA)"),
+ ("CO", "Colorado (CO)"),
+ ("CT", "Connecticut (CT)"),
+ ("DE", "Delaware (DE)"),
+ ("DC", "District of Columbia (DC)"),
+ ("FL", "Florida (FL)"),
+ ("GA", "Georgia (GA)"),
+ ("GU", "Guam (GU)"),
+ ("HI", "Hawaii (HI)"),
+ ("ID", "Idaho (ID)"),
+ ("IL", "Illinois (IL)"),
+ ("IN", "Indiana (IN)"),
+ ("IA", "Iowa (IA)"),
+ ("KS", "Kansas (KS)"),
+ ("KY", "Kentucky (KY)"),
+ ("LA", "Louisiana (LA)"),
+ ("ME", "Maine (ME)"),
+ ("MD", "Maryland (MD)"),
+ ("MA", "Massachusetts (MA)"),
+ ("MI", "Michigan (MI)"),
+ ("MN", "Minnesota (MN)"),
+ ("MS", "Mississippi (MS)"),
+ ("MO", "Missouri (MO)"),
+ ("MT", "Montana (MT)"),
+ ("NE", "Nebraska (NE)"),
+ ("NV", "Nevada (NV)"),
+ ("NH", "New Hampshire (NH)"),
+ ("NJ", "New Jersey (NJ)"),
+ ("NM", "New Mexico (NM)"),
+ ("NY", "New York (NY)"),
+ ("NC", "North Carolina (NC)"),
+ ("ND", "North Dakota (ND)"),
+ ("MP", "Northern Mariana Islands (MP)"),
+ ("OH", "Ohio (OH)"),
+ ("OK", "Oklahoma (OK)"),
+ ("OR", "Oregon (OR)"),
+ ("PA", "Pennsylvania (PA)"),
+ ("PR", "Puerto Rico (PR)"),
+ ("RI", "Rhode Island (RI)"),
+ ("SC", "South Carolina (SC)"),
+ ("SD", "South Dakota (SD)"),
+ ("TN", "Tennessee (TN)"),
+ ("TX", "Texas (TX)"),
+ ("UM", "United States Minor Outlying Islands (UM)"),
+ ("UT", "Utah (UT)"),
+ ("VT", "Vermont (VT)"),
+ ("VI", "Virgin Islands (VI)"),
+ ("VA", "Virginia (VA)"),
+ ("WA", "Washington (WA)"),
+ ("WV", "West Virginia (WV)"),
+ ("WI", "Wisconsin (WI)"),
+ ("WY", "Wyoming (WY)"),
+ ("AA", "Armed Forces Americas (AA)"),
+ ("AE", "Armed Forces Africa, Canada, Europe, Middle East (AE)"),
+ ("AP", "Armed Forces Pacific (AP)"),
+ ],
+ max_length=2,
+ null=True,
+ verbose_name="state, territory, or military post",
+ ),
+ ),
+ ]
From c465b7fb67c5ff2995a1cc30ecc4e062ba3a5acf Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:20:26 -0600
Subject: [PATCH 42/68] fix bug with form save
Since cleaned data was not being touched, the form was not resetting values correctly
---
src/registrar/assets/js/get-gov.js | 1 -
src/registrar/forms/domain_request_wizard.py | 4 ++-
src/registrar/tests/test_views_portfolio.py | 1 -
src/registrar/views/domain_request.py | 27 ++++++++++++--------
4 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js
index 81bb30e38..be658ad3e 100644
--- a/src/registrar/assets/js/get-gov.js
+++ b/src/registrar/assets/js/get-gov.js
@@ -2789,7 +2789,6 @@ document.addEventListener('DOMContentLoaded', function() {
subOrgSelect.add(fakeOption);
}
- console.log(isRequestingSuborganization.value)
if (isRequestingSuborganization.value === "True") {
subOrgSelect.value = "other"
}
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 2bc31fc37..b27a004c0 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -111,7 +111,9 @@ class RequestingEntityForm(RegistrarForm):
# Get the value of the yes/no checkbox from RequestingEntityYesNoForm.
# Since self.data stores this as a string, we need to convert "True" => True.
- requesting_entity_is_suborganization = self.data.get("portfolio_requesting_entity-requesting_entity_is_suborganization")
+ requesting_entity_is_suborganization = self.data.get(
+ "portfolio_requesting_entity-requesting_entity_is_suborganization"
+ )
if requesting_entity_is_suborganization == "True":
if is_requesting_new_suborganization:
# Validate custom suborganization fields
diff --git a/src/registrar/tests/test_views_portfolio.py b/src/registrar/tests/test_views_portfolio.py
index 1ca2d2bcd..45357cbf7 100644
--- a/src/registrar/tests/test_views_portfolio.py
+++ b/src/registrar/tests/test_views_portfolio.py
@@ -1717,7 +1717,6 @@ class TestRequestingEntity(WebTest):
self.assertContains(response, "Who will use the domain you’re requesting?")
form = response.forms[0]
- # Test selecting an existing suborg
form["portfolio_requesting_entity-requesting_entity_is_suborganization"] = True
form["portfolio_requesting_entity-is_requesting_new_suborganization"] = True
form["portfolio_requesting_entity-sub_organization"] = ""
diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py
index 209a6c100..7fb2d9b16 100644
--- a/src/registrar/views/domain_request.py
+++ b/src/registrar/views/domain_request.py
@@ -594,25 +594,32 @@ class RequestingEntity(DomainRequestWizard):
"""Override of save to clear or associate certain suborganization data
depending on what the user wishes to do. For instance, we want to add a suborganization
if the user selects one."""
+ yesno_form = forms[0]
requesting_entity_form = forms[1]
+
+ yesno_cleaned_data = yesno_form.cleaned_data
+ requesting_entity_is_suborganization = yesno_cleaned_data.get("requesting_entity_is_suborganization")
+
cleaned_data = requesting_entity_form.cleaned_data
- requesting_entity_is_suborganization = cleaned_data.get("requesting_entity_is_suborganization")
sub_organization = cleaned_data.get("sub_organization")
requested_suborganization = cleaned_data.get("requested_suborganization")
if requesting_entity_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
- self.domain_request.sub_organization = sub_organization
+ requesting_entity_form.cleaned_data.update({"organization_name": None})
else:
# If the user doesn't intend to create a suborg, simply don't make one and do some data cleanup
- if self.domain_request.portfolio:
- self.domain_request.organization_name = self.domain_request.portfolio.organization_name
-
- self.domain_request.sub_organization = None
- self.domain_request.requested_suborganization = None
- self.domain_request.suborganization_city = None
- self.domain_request.suborganization_state_territory = None
+ requesting_entity_form.cleaned_data.update(
+ {
+ "organization_name": (
+ self.domain_request.portfolio.organization_name if self.domain_request.portfolio else None
+ ),
+ "sub_organization": None,
+ "requested_suborganization": None,
+ "suborganization_city": None,
+ "suborganization_state_territory": None,
+ }
+ )
super().save(forms)
From dfb59a6a9d3ab4be10a941dbc32db390594f9a52 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:21:35 -0600
Subject: [PATCH 43/68] lint model
---
src/registrar/models/domain_request.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index a04cea526..96d98ed65 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -1152,7 +1152,9 @@ class DomainRequest(TimeStampedModel):
# If a suborganization already exists, it can't possibly be a new one
if self.sub_organization:
return False
- return bool(self.requested_suborganization and self.suborganization_city and self.suborganization_state_territory)
+ return bool(
+ self.requested_suborganization and self.suborganization_city and self.suborganization_state_territory
+ )
# ## Form unlocking steps ## #
#
From 4f1febf24820589b1339c5cb8b92bbbcef2b8eaa Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:27:04 -0600
Subject: [PATCH 44/68] Update domain_request.py
---
src/registrar/models/domain_request.py | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index 96d98ed65..c8c21ea33 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -1127,7 +1127,10 @@ class DomainRequest(TimeStampedModel):
def requesting_entity_is_portfolio(self) -> bool:
"""Determines if this record is requesting that a portfolio be their organization."""
- return self.portfolio and self.organization_name == self.portfolio.organization_name
+ if self.portfolio and self.organization_name == self.portfolio.organization_name:
+ return True
+ else:
+ return False
def requesting_entity_is_suborganization(self) -> bool:
"""Used to determine if this domain request is also requesting that it be tied to a suborganization.
@@ -1152,9 +1155,11 @@ class DomainRequest(TimeStampedModel):
# If a suborganization already exists, it can't possibly be a new one
if self.sub_organization:
return False
- return bool(
- self.requested_suborganization and self.suborganization_city and self.suborganization_state_territory
- )
+
+ if self.requested_suborganization and self.suborganization_city and self.suborganization_state_territory:
+ return True
+ else:
+ return False
# ## Form unlocking steps ## #
#
From bb9cb527d203ece5049135c4d59f437c8f86d567 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:33:30 -0600
Subject: [PATCH 45/68] Cleanup bool logic to be more concise
---
src/registrar/models/domain_request.py | 27 +++++++++++++-------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index c8c21ea33..48b9f23c7 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -1137,13 +1137,10 @@ class DomainRequest(TimeStampedModel):
Checks if this record has a suborganization or not by checking if a suborganization exists,
and if it doesn't, determining if properties like requested_suborganization exist.
"""
-
- if self.portfolio:
- if self.sub_organization:
- return True
- if self.is_requesting_new_suborganization():
- return True
- return False
+ if self.portfolio and (self.sub_organization or self.is_requesting_new_suborganization()):
+ return True
+ else:
+ return False
def is_requesting_new_suborganization(self) -> bool:
"""Used on the requesting entity form to determine if a user is trying to request
@@ -1152,11 +1149,15 @@ class DomainRequest(TimeStampedModel):
This only occurs when no suborganization is selected, but they've filled out
the requested_suborganization, suborganization_city, and suborganization_state_territory fields.
"""
- # If a suborganization already exists, it can't possibly be a new one
- if self.sub_organization:
- return False
- if self.requested_suborganization and self.suborganization_city and self.suborganization_state_territory:
+ # If a suborganization already exists, it can't possibly be a new one.
+ # As well, we need all required fields to exist.
+ required_fields = [
+ self.requested_suborganization,
+ self.suborganization_city,
+ self.suborganization_state_territory
+ ]
+ if not self.sub_organization and all(required_fields):
return True
else:
return False
@@ -1167,9 +1168,7 @@ class DomainRequest(TimeStampedModel):
def unlock_requesting_entity(self) -> bool:
"""Unlocks the requesting entity step"""
- if self.requesting_entity_is_suborganization():
- return True
- elif self.requesting_entity_is_portfolio():
+ if self.requesting_entity_is_suborganization() or self.requesting_entity_is_portfolio():
return True
else:
return False
From 98842c1aa0c5e71cb6d861c19314a3d9895e5a11 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 14:40:25 -0600
Subject: [PATCH 46/68] add comments
---
src/registrar/forms/domain_request_wizard.py | 3 ++-
src/registrar/views/domain_request.py | 7 +++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index b27a004c0..c188a7ab0 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -154,7 +154,8 @@ class RequestingEntityYesNoForm(BaseYesNoForm):
desired suborg doesn't exist. We expose additional fields that denote this,
like `requested_suborganization`. So we also check on those.
"""
-
+ # True means that the requesting entity is a suborganization,
+ # whereas False means that the requesting entity is a portfolio.
if self.domain_request.requesting_entity_is_suborganization():
return True
elif self.domain_request.requesting_entity_is_portfolio():
diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py
index 7fb2d9b16..41e9a07b8 100644
--- a/src/registrar/views/domain_request.py
+++ b/src/registrar/views/domain_request.py
@@ -594,16 +594,19 @@ class RequestingEntity(DomainRequestWizard):
"""Override of save to clear or associate certain suborganization data
depending on what the user wishes to do. For instance, we want to add a suborganization
if the user selects one."""
- yesno_form = forms[0]
- requesting_entity_form = forms[1]
+ # Get the yes/no dropdown value
+ yesno_form = forms[0]
yesno_cleaned_data = yesno_form.cleaned_data
requesting_entity_is_suborganization = yesno_cleaned_data.get("requesting_entity_is_suborganization")
+ # Get the suborg value, and the requested suborg value
+ requesting_entity_form = forms[1]
cleaned_data = requesting_entity_form.cleaned_data
sub_organization = cleaned_data.get("sub_organization")
requested_suborganization = cleaned_data.get("requested_suborganization")
+ # Do some data cleanup, depending on what option was checked
if requesting_entity_is_suborganization and (sub_organization or requested_suborganization):
# Cleanup the organization name field, as this isn't for suborganizations.
requesting_entity_form.cleaned_data.update({"organization_name": None})
From 603e2eb767a031df7d5705e9db1ae6d138fea771 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 15:28:05 -0600
Subject: [PATCH 47/68] simplify javascript (a lot)
---
src/registrar/assets/js/get-gov.js | 91 +++++++++++-------------------
1 file changed, 33 insertions(+), 58 deletions(-)
diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js
index be658ad3e..2bbcc781d 100644
--- a/src/registrar/assets/js/get-gov.js
+++ b/src/registrar/assets/js/get-gov.js
@@ -2742,78 +2742,53 @@ document.addEventListener('DOMContentLoaded', function() {
(function handleRequestingEntityFieldset() {
// Sadly, these ugly ids are the auto generated with this prefix
const formPrefix = "portfolio_requesting_entity"
-
- // This determines if we are on the requesting entity page or not.
- const isSubOrgFieldset = document.getElementById(`id_${formPrefix}-requesting_entity_is_suborganization__fieldset`);
- if (!isSubOrgFieldset) return;
-
- // Get the is_suborganization radio buttons
- const isSuborgRadios = isSubOrgFieldset.querySelectorAll(`input[name="${formPrefix}-requesting_entity_is_suborganization"]`);
- const subOrgSelect = document.getElementById(`id_${formPrefix}-sub_organization`);
-
- // The suborganization section is its own div
- // Within the suborganization section, we also have a div that contains orgname, city, and stateterritory.
+ const radioFieldset = document.getElementById(`id_${formPrefix}-requesting_entity_is_suborganization__fieldset`);
+ const radios = radioFieldset?.querySelectorAll(`input[name="${formPrefix}-requesting_entity_is_suborganization"]`);
+ const select = document.getElementById(`id_${formPrefix}-sub_organization`);
const suborganizationContainer = document.getElementById("suborganization-container");
const suborganizationDetailsContainer = document.getElementById("suborganization-container__details");
+ if (!radios || !select || !suborganizationContainer || !suborganizationDetailsContainer) return;
- // This variable determines if the user is trying to *create* a new suborganization or not.
- var isRequestingSuborganization = document.getElementById(`id_${formPrefix}-is_requesting_new_suborganization`)
+ // requestingSuborganization: This just broadly determines if they're requesting a suborg at all
+ // requestingNewSuborganization: This variable determines if the user is trying to *create* a new suborganization or not.
+ var requestingSuborganization = false;
+ var requestingNewSuborganization = document.getElementById(`id_${formPrefix}-is_requesting_new_suborganization`);
- // Don't do anything if we are missing crucial page elements
- if (!isSuborgRadios || !subOrgSelect || !suborganizationContainer || !suborganizationDetailsContainer) return;
-
- // Function to toggle suborganization based on is_suborganization selection
function toggleSuborganization(radio) {
- if (radio && radio.checked && radio.value === "True") {
+ requestingSuborganization = radio?.checked && radio.value === "True";
+ if (requestingSuborganization) {
showElement(suborganizationContainer);
-
- // Handle custom suborganizations
- if (subOrgSelect.value === "other") {
- showElement(suborganizationDetailsContainer);
- isRequestingSuborganization.value = "True";
- } else {
- hideElement(suborganizationDetailsContainer);
- isRequestingSuborganization.value = "False";
- }
- } else {
+ }else {
hideElement(suborganizationContainer);
- hideElement(suborganizationDetailsContainer);
}
- };
-
- // Add fake "other" option to sub_organization select
- if (subOrgSelect && !Array.from(subOrgSelect.options).some(option => option.value === "other")) {
- const fakeOption = document.createElement("option");
- fakeOption.value = "other";
- fakeOption.text = "Other (enter your organization manually)";
- subOrgSelect.add(fakeOption);
}
- if (isRequestingSuborganization.value === "True") {
- subOrgSelect.value = "other"
+ function toggleSuborganizationDetails() {
+ if (requestingSuborganization && select.value === "other") {
+ showElement(suborganizationDetailsContainer);
+ requestingNewSuborganization.value = "True";
+ }else {
+ hideElement(suborganizationDetailsContainer);
+ requestingNewSuborganization.value = "False";
+ }
}
- // Add event listener to is_suborganization radio buttons
- isSuborgRadios.forEach(radio => {
- // Run this here for initial display.
- // Since there are only two radio buttons and since this has (practically speaking) no performance impact, this is fine to do.
+ // Add fake "other" option to sub_organization select
+ if (select && !Array.from(select.options).some(option => option.value === "other")) {
+ select.add(new Option("Other (enter your organization manually)", "other"));
+ }
+
+ if (requestingNewSuborganization.value === "True") {
+ select.value = "other";
+ }
+
+ // Add event listener to is_suborganization radio buttons, and run for initial display
+ radios.forEach(radio => {
toggleSuborganization(radio);
-
- // Add an event listener to each to show/hide the relevant fields
- radio.addEventListener("click", () => {
- toggleSuborganization(radio);
- });
+ radio.addEventListener("click", () => toggleSuborganization(radio));
});
// Add event listener to the suborg dropdown to show/hide the suborg details section
- subOrgSelect.addEventListener("change", () => {
- // Handle the custom suborganization field
- if (subOrgSelect.value === "other") {
- showElement(suborganizationDetailsContainer);
- isRequestingSuborganization.value = "True";
- } else {
- hideElement(suborganizationDetailsContainer);
- isRequestingSuborganization.value = "False";
- }
- });
+ toggleSuborganizationDetails();
+ select.addEventListener("change", () => toggleSuborganizationDetails());
})();
From ba7de7c67815343623a73be5b376e2c87d1e1477 Mon Sep 17 00:00:00 2001
From: CocoByte
Date: Wed, 30 Oct 2024 15:40:00 -0600
Subject: [PATCH 48/68] Implemented PR feedback
---
src/registrar/assets/js/get-gov.js | 4 +-
src/registrar/forms/portfolio.py | 39 +++++++----
.../templates/portfolio_members_add_new.html | 4 +-
src/registrar/views/portfolios.py | 70 +------------------
4 files changed, 31 insertions(+), 86 deletions(-)
diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js
index 6f8ab2fa6..602d9cf79 100644
--- a/src/registrar/assets/js/get-gov.js
+++ b/src/registrar/assets/js/get-gov.js
@@ -337,7 +337,7 @@ function HookupRadioTogglerListener(radioButtonName, valueToElementMap) {
allElementIds.forEach(function (elementId) {
let element = document.getElementById(elementId);
if (element) {
- element.style.display = 'none';
+ hideElement(element);
}
});
@@ -345,7 +345,7 @@ function HookupRadioTogglerListener(radioButtonName, valueToElementMap) {
if (selectedValue && valueToElementMap[selectedValue]) {
let elementToShow = document.getElementById(valueToElementMap[selectedValue]);
if (elementToShow) {
- elementToShow.style.display = 'block';
+ showElement(elementToShow);
}
}
}
diff --git a/src/registrar/forms/portfolio.py b/src/registrar/forms/portfolio.py
index e99c2db71..4d6ec81cb 100644
--- a/src/registrar/forms/portfolio.py
+++ b/src/registrar/forms/portfolio.py
@@ -180,7 +180,7 @@ class NewMemberForm(forms.ModelForm):
widget=forms.RadioSelect,
required=True,
error_messages={
- "required": "Domain request permission is required",
+ "required": "Admin domain request permission is required",
},
)
admin_org_members_permissions = forms.ChoiceField(
@@ -189,7 +189,7 @@ class NewMemberForm(forms.ModelForm):
widget=forms.RadioSelect,
required=True,
error_messages={
- "required": "Member permission is required",
+ "required": "Admin member permission is required",
},
)
basic_org_domain_request_permissions = forms.ChoiceField(
@@ -202,7 +202,7 @@ class NewMemberForm(forms.ModelForm):
widget=forms.RadioSelect,
required=True,
error_messages={
- "required": "Member permission is required",
+ "required": "Basic member permission is required",
},
)
@@ -234,6 +234,11 @@ class NewMemberForm(forms.ModelForm):
if email_value:
cleaned_data["email"] = email_value.lower()
+
+ ##########################################
+ # TODO: future ticket
+ # (invite new member)
+ ##########################################
# Check for an existing user (if there isn't any, send an invite)
# if email_value:
# try:
@@ -241,21 +246,29 @@ class NewMemberForm(forms.ModelForm):
# except User.DoesNotExist:
# raise forms.ValidationError("User with this email does not exist.")
- # Get the grade and sport from POST data
- permission_level = cleaned_data.get("member_access_level")
- # permission_level = self.data.get('new_member-permission_level')
- if not permission_level:
+ member_access_level = cleaned_data.get("member_access_level")
+
+ # Intercept the error messages so that we don't validate hidden inputs
+ if not member_access_level:
+ # If no member access level has been selected, delete error messages
+ # for all hidden inputs (which is everything except the e-mail input
+ # and member access selection)
for field in self.fields:
if field in self.errors and field != "email" and field != "member_access_level":
del self.errors[field]
return cleaned_data
+
+ basic_dom_req_error = "basic_org_domain_request_permissions"
+ admin_dom_req_error = "admin_org_domain_request_permissions"
+ admin_member_error = "admin_org_members_permissions"
- # Validate the sport based on the selected grade
- if permission_level == "True":
+ if member_access_level == "admin" and basic_dom_req_error in self.errors:
# remove the error messages pertaining to basic permission inputs
- del self.errors["basic_org_domain_request_permissions"]
- else:
+ del self.errors[basic_dom_req_error]
+ elif member_access_level == "basic":
# remove the error messages pertaining to admin permission inputs
- del self.errors["admin_org_domain_request_permissions"]
- del self.errors["admin_org_members_permissions"]
+ if admin_dom_req_error in self.errors:
+ del self.errors[admin_dom_req_error]
+ if admin_member_error in self.errors:
+ del self.errors[admin_member_error]
return cleaned_data
diff --git a/src/registrar/templates/portfolio_members_add_new.html b/src/registrar/templates/portfolio_members_add_new.html
index 3a390a470..6d8e449f6 100644
--- a/src/registrar/templates/portfolio_members_add_new.html
+++ b/src/registrar/templates/portfolio_members_add_new.html
@@ -65,9 +65,9 @@
{{ radio.choice_label }}
{% if radio.choice_label == "Admin Access" %}
- Grants this member access to the organization-wide information on domains, domain requests, and members. Domain management can be assigned separately.
+ Grants this member access to the organization-wide information on domains, domain requests, and members. Domain management can be assigned separately.
{% else %}
- Grants this member access to the organization. They can be given extra permissions to view all organization domain requests and submit domain requests on behald of the organization. Basica access members can't view all members of an organization or manage them. Domain management can be assigned separacterly.
+ Grants this member access to the organization. They can be given extra permissions to view all organization domain requests and submit domain requests on behalf of the organization. Basic access members can’t view all members of an organization or manage them. Domain management can be assigned separately.
{% endif %}
diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py
index bd9a10dd8..ebb90cda1 100644
--- a/src/registrar/views/portfolios.py
+++ b/src/registrar/views/portfolios.py
@@ -388,13 +388,6 @@ class NewMemberView(PortfolioMembersPermissionView, FormMixin):
else:
return self.form_invalid(form)
- def form_valid(self, form):
- """Handle the case when the form is valid."""
- # self.object = form.save(commit=False)
- # self.object.creator = self.request.user
- # self.object.save()
- # messages.success(self.request, "The organization information for this portfolio has been updated.")
- return super().form_valid(form)
def form_invalid(self, form):
"""Handle the case when the form is invalid."""
@@ -405,7 +398,7 @@ class NewMemberView(PortfolioMembersPermissionView, FormMixin):
return reverse("members")
##########################################
- # TODO: future ticket
+ # TODO: future ticket #2854
# (save/invite new member)
##########################################
@@ -526,64 +519,3 @@ class NewMemberView(PortfolioMembersPermissionView, FormMixin):
# else:
# messages.success(self.request, f"Added user {requested_email}.")
# return redirect(self.get_success_url())
-
-
-# class NewMemberView(PortfolioMembersPermissionView, FormMixin):
-# form = portfolioForms.NewMemberForm
-# template_name = 'portfolio_members_add_new.html' # Assuming you have a template file for the form
-
-# # model = UserPortfolioPermission
-# # template_name = "portfolio_members_add_new.html"
-# # form_class = portfolioForms.NewMemberForm
-# # context_object_name = "userPortfolioPermission"
-
-# def get_success_url(self):
-# return reverse('success') # Redirect after successful submission
-
-# def get_context_data(self, **kwargs):
-# """Add additional context data to the template."""
-# #TODO: Add permissions to context
-# context = super().get_context_data(**kwargs)
-# portfolio = self.request.session.get("portfolio")
-# context["has_invite_members_permission"] = self.request.user.has_edit_members_portfolio_permission(portfolio)
-# return context
-
-# def form_valid(self, form):
-# # Get the cleaned data from the form
-# cleaned_data = form.cleaned_data
-# email = cleaned_data.get('email')
-# # grade = cleaned_data.get('grade')
-# # sport = cleaned_data.get('sport')
-
-# ##########################################
-# # TODO: future ticket
-# # (validate and save/invite new member here)
-# ##########################################
-
-# # Lookup member by email
-# # member = get_object_or_404(User, email=email)
-
-# # Check existing portfolio permissions
-# # TODO: future ticket -- check for existing portfolio permissions, multipe portfolio flags, etc.
-# # school = self.get_context_data()['school']
-
-# # Update student school information
-# # student.school = school
-# # student.save()
-
-# # Create or update the SportEnrollment for this student
-# # SportEnrollment.objects.create(
-# # student=student,
-# # grade=grade,
-# # sport=sport
-# # )
-
-# return super().form_valid(form)
-
-# def form_invalid(self, form):
-# # If the form is invalid, show errors
-# return self.render_to_response(self.get_context_data(form=form))
-
-
-# def get(self, request):
-# return render(request, "portfolio_members_add_new.html")
From 0153627a9e29fd4f7d72a18d34ef6344e907f565 Mon Sep 17 00:00:00 2001
From: CocoByte
Date: Wed, 30 Oct 2024 15:47:09 -0600
Subject: [PATCH 49/68] linted
---
src/registrar/forms/portfolio.py | 7 +++----
src/registrar/views/portfolios.py | 1 -
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/registrar/forms/portfolio.py b/src/registrar/forms/portfolio.py
index 4d6ec81cb..5309f7263 100644
--- a/src/registrar/forms/portfolio.py
+++ b/src/registrar/forms/portfolio.py
@@ -234,7 +234,6 @@ class NewMemberForm(forms.ModelForm):
if email_value:
cleaned_data["email"] = email_value.lower()
-
##########################################
# TODO: future ticket
# (invite new member)
@@ -257,7 +256,7 @@ class NewMemberForm(forms.ModelForm):
if field in self.errors and field != "email" and field != "member_access_level":
del self.errors[field]
return cleaned_data
-
+
basic_dom_req_error = "basic_org_domain_request_permissions"
admin_dom_req_error = "admin_org_domain_request_permissions"
admin_member_error = "admin_org_members_permissions"
@@ -267,8 +266,8 @@ class NewMemberForm(forms.ModelForm):
del self.errors[basic_dom_req_error]
elif member_access_level == "basic":
# remove the error messages pertaining to admin permission inputs
- if admin_dom_req_error in self.errors:
+ if admin_dom_req_error in self.errors:
del self.errors[admin_dom_req_error]
- if admin_member_error in self.errors:
+ if admin_member_error in self.errors:
del self.errors[admin_member_error]
return cleaned_data
diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py
index 9e4d2c5a6..1dbab2913 100644
--- a/src/registrar/views/portfolios.py
+++ b/src/registrar/views/portfolios.py
@@ -423,7 +423,6 @@ class NewMemberView(PortfolioMembersPermissionView, FormMixin):
else:
return self.form_invalid(form)
-
def form_invalid(self, form):
"""Handle the case when the form is invalid."""
return self.render_to_response(self.get_context_data(form=form))
From cf1e6aa9b791a8bd8f811c85dbc85b558f387d2b Mon Sep 17 00:00:00 2001
From: Matt-Spence
Date: Wed, 30 Oct 2024 16:55:38 -0500
Subject: [PATCH 50/68] Update clone-staging.yaml
---
.github/workflows/clone-staging.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/clone-staging.yaml b/.github/workflows/clone-staging.yaml
index 6466c7def..fbd55b6ee 100644
--- a/.github/workflows/clone-staging.yaml
+++ b/.github/workflows/clone-staging.yaml
@@ -40,7 +40,7 @@ jobs:
cf_password: ${{ secrets.CF_MS_PASSWORD }}
cf_org: cisa-dotgov
cf_space: ${{ env.SOURCE_ENVIRONMENT }}
- command: cg-manage-rds clone getgov-${{ env.SOURCE_ENVIRONMENT }}-database getgov-${{ env.DESTINATION_ENVIRONMENT }}-database
+ command: pip install git+https://github.com/cloud-gov/cg-manage-rds.git && cg-manage-rds clone getgov-${{ env.SOURCE_ENVIRONMENT }}-database getgov-${{ env.DESTINATION_ENVIRONMENT }}-database
- name: Unshare DB Service
uses: cloud-gov/cg-cli-tools@main
From b01e707b82a8de44e6781c41871bc2b59af895c2 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Wed, 30 Oct 2024 15:55:39 -0600
Subject: [PATCH 51/68] further simplify
---
src/registrar/assets/js/get-gov.js | 35 ++++++++++--------------------
1 file changed, 11 insertions(+), 24 deletions(-)
diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js
index 2bbcc781d..d462af5ac 100644
--- a/src/registrar/assets/js/get-gov.js
+++ b/src/registrar/assets/js/get-gov.js
@@ -2745,32 +2745,20 @@ document.addEventListener('DOMContentLoaded', function() {
const radioFieldset = document.getElementById(`id_${formPrefix}-requesting_entity_is_suborganization__fieldset`);
const radios = radioFieldset?.querySelectorAll(`input[name="${formPrefix}-requesting_entity_is_suborganization"]`);
const select = document.getElementById(`id_${formPrefix}-sub_organization`);
- const suborganizationContainer = document.getElementById("suborganization-container");
- const suborganizationDetailsContainer = document.getElementById("suborganization-container__details");
- if (!radios || !select || !suborganizationContainer || !suborganizationDetailsContainer) return;
+ const suborgContainer = document.getElementById("suborganization-container");
+ const suborgDetailsContainer = document.getElementById("suborganization-container__details");
+ if (!radios || !select || !suborgContainer || !suborgDetailsContainer) return;
// requestingSuborganization: This just broadly determines if they're requesting a suborg at all
// requestingNewSuborganization: This variable determines if the user is trying to *create* a new suborganization or not.
- var requestingSuborganization = false;
+ var requestingSuborganization = Array.from(radios).find(radio => radio.checked)?.value === "True";
var requestingNewSuborganization = document.getElementById(`id_${formPrefix}-is_requesting_new_suborganization`);
- function toggleSuborganization(radio) {
- requestingSuborganization = radio?.checked && radio.value === "True";
- if (requestingSuborganization) {
- showElement(suborganizationContainer);
- }else {
- hideElement(suborganizationContainer);
- }
- }
-
- function toggleSuborganizationDetails() {
- if (requestingSuborganization && select.value === "other") {
- showElement(suborganizationDetailsContainer);
- requestingNewSuborganization.value = "True";
- }else {
- hideElement(suborganizationDetailsContainer);
- requestingNewSuborganization.value = "False";
- }
+ function toggleSuborganization(radio=null) {
+ if (radio != null) requestingSuborganization = radio?.checked && radio.value === "True";
+ requestingSuborganization ? showElement(suborgContainer) : hideElement(suborgContainer);
+ requestingNewSuborganization.value = requestingSuborganization && select.value === "other" ? "True" : "False";
+ requestingNewSuborganization.value === "True" ? showElement(suborgDetailsContainer) : hideElement(suborgDetailsContainer);
}
// Add fake "other" option to sub_organization select
@@ -2783,12 +2771,11 @@ document.addEventListener('DOMContentLoaded', function() {
}
// Add event listener to is_suborganization radio buttons, and run for initial display
+ toggleSuborganization();
radios.forEach(radio => {
- toggleSuborganization(radio);
radio.addEventListener("click", () => toggleSuborganization(radio));
});
// Add event listener to the suborg dropdown to show/hide the suborg details section
- toggleSuborganizationDetails();
- select.addEventListener("change", () => toggleSuborganizationDetails());
+ select.addEventListener("change", () => toggleSuborganization());
})();
From f0ba59611e60e90f64e41c4a376a09907328d9ea Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Thu, 31 Oct 2024 08:14:37 -0600
Subject: [PATCH 52/68] Initial logic
---
src/registrar/models/domain_request.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index 48b9f23c7..c2a8df257 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -1155,7 +1155,7 @@ class DomainRequest(TimeStampedModel):
required_fields = [
self.requested_suborganization,
self.suborganization_city,
- self.suborganization_state_territory
+ self.suborganization_state_territory,
]
if not self.sub_organization and all(required_fields):
return True
From 4e3569d73d31d40fbf3a35172f36db2b9e60dc31 Mon Sep 17 00:00:00 2001
From: Matt-Spence
Date: Thu, 31 Oct 2024 10:28:39 -0500
Subject: [PATCH 53/68] Add tools and minor updates to cloning workflow
---
.github/workflows/clone-staging.yaml | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/clone-staging.yaml b/.github/workflows/clone-staging.yaml
index fbd55b6ee..df943f138 100644
--- a/.github/workflows/clone-staging.yaml
+++ b/.github/workflows/clone-staging.yaml
@@ -22,7 +22,16 @@ jobs:
CF_PASSWORD: CF_MS_PASSWORD
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
+
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.13'
+ cache: 'pip' # caching pip dependencies
+
+ - name: Install CG Tool
+ run: pip install git+https://github.com/cloud-gov/cg-manage-rds.git
- name: Share DB Service
uses: cloud-gov/cg-cli-tools@main
@@ -40,7 +49,7 @@ jobs:
cf_password: ${{ secrets.CF_MS_PASSWORD }}
cf_org: cisa-dotgov
cf_space: ${{ env.SOURCE_ENVIRONMENT }}
- command: pip install git+https://github.com/cloud-gov/cg-manage-rds.git && cg-manage-rds clone getgov-${{ env.SOURCE_ENVIRONMENT }}-database getgov-${{ env.DESTINATION_ENVIRONMENT }}-database
+ command: cg-manage-rds clone getgov-${{ env.SOURCE_ENVIRONMENT }}-database getgov-${{ env.DESTINATION_ENVIRONMENT }}-database
- name: Unshare DB Service
uses: cloud-gov/cg-cli-tools@main
From 510938430b2f389d148c8497fde0168faf4b3473 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Thu, 31 Oct 2024 10:05:28 -0600
Subject: [PATCH 54/68] Add some comments
---
src/registrar/forms/domain_request_wizard.py | 5 +++++
src/registrar/models/domain_request.py | 7 +++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index c188a7ab0..16e5b66ea 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -27,6 +27,8 @@ class RequestingEntityForm(RegistrarForm):
All of these fields are not required by default, but as we use javascript to conditionally show
and hide some of these, they then become required in certain circumstances."""
+ # IMPORTANT: This is tied to DomainRequest.is_requesting_new_suborganization().
+ # This is due to the from_database method on DomainRequestWizard.
# Add a hidden field to store if the user is requesting a new suborganization.
# This hidden boolean is used for our javascript to communicate to us and to it.
# If true, the suborganization form will auto select a js value "Other".
@@ -134,6 +136,9 @@ class RequestingEntityYesNoForm(BaseYesNoForm):
# This first option will change dynamically
form_choices = ((False, "Current Organization"), (True, "A suborganization. (choose from list)"))
+
+ # IMPORTANT: This is tied to DomainRequest.is_requesting_new_suborganization().
+ # This is due to the from_database method on DomainRequestWizard.
field_name = "requesting_entity_is_suborganization"
def __init__(self, *args, **kwargs):
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index c2a8df257..c3fc5335d 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -1126,7 +1126,8 @@ class DomainRequest(TimeStampedModel):
self.creator.restrict_user()
def requesting_entity_is_portfolio(self) -> bool:
- """Determines if this record is requesting that a portfolio be their organization."""
+ """Determines if this record is requesting that a portfolio be their organization.
+ Used for the RequestingEntity page."""
if self.portfolio and self.organization_name == self.portfolio.organization_name:
return True
else:
@@ -1136,6 +1137,7 @@ class DomainRequest(TimeStampedModel):
"""Used to determine if this domain request is also requesting that it be tied to a suborganization.
Checks if this record has a suborganization or not by checking if a suborganization exists,
and if it doesn't, determining if properties like requested_suborganization exist.
+ Used for the RequestingEntity page.
"""
if self.portfolio and (self.sub_organization or self.is_requesting_new_suborganization()):
return True
@@ -1148,6 +1150,7 @@ class DomainRequest(TimeStampedModel):
This only occurs when no suborganization is selected, but they've filled out
the requested_suborganization, suborganization_city, and suborganization_state_territory fields.
+ Used for the RequestingEntity page.
"""
# If a suborganization already exists, it can't possibly be a new one.
@@ -1167,7 +1170,7 @@ class DomainRequest(TimeStampedModel):
# These methods control the conditions in which we should unlock certain domain wizard steps.
def unlock_requesting_entity(self) -> bool:
- """Unlocks the requesting entity step"""
+ """Unlocks the requesting entity step. Used for the RequestingEntity page."""
if self.requesting_entity_is_suborganization() or self.requesting_entity_is_portfolio():
return True
else:
From 612b7b68be5f5d64883fdfebca7694c86a7ad629 Mon Sep 17 00:00:00 2001
From: CocoByte
Date: Thu, 31 Oct 2024 13:31:13 -0600
Subject: [PATCH 55/68] Implemented feedback (plus fixed bug where cancel
button validates form)
---
src/.pa11yci | 4 ++-
.../templates/includes/header_extended.html | 2 +-
.../templates/portfolio_members.html | 2 +-
.../templates/portfolio_members_add_new.html | 32 ++++++++-----------
4 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/src/.pa11yci b/src/.pa11yci
index c18704c07..c42597fb4 100644
--- a/src/.pa11yci
+++ b/src/.pa11yci
@@ -20,6 +20,8 @@
"http://localhost:8080/request/anything_else/",
"http://localhost:8080/request/requirements/",
"http://localhost:8080/request/finished/",
- "http://localhost:8080/user-profile/"
+ "http://localhost:8080/user-profile/",
+ "http://localhost:8080/members/",
+ "http://localhost:8080/members/new-member"
]
}
diff --git a/src/registrar/templates/includes/header_extended.html b/src/registrar/templates/includes/header_extended.html
index 23b7d1be3..7c0f55dc3 100644
--- a/src/registrar/templates/includes/header_extended.html
+++ b/src/registrar/templates/includes/header_extended.html
@@ -95,7 +95,7 @@
{% if has_organization_members_flag %}
-
+
Members
diff --git a/src/registrar/templates/portfolio_members.html b/src/registrar/templates/portfolio_members.html
index b13027c3d..3cd3aec44 100644
--- a/src/registrar/templates/portfolio_members.html
+++ b/src/registrar/templates/portfolio_members.html
@@ -21,7 +21,7 @@
{% if has_edit_members_portfolio_permission %}
-
Add a new member
diff --git a/src/registrar/templates/portfolio_members_add_new.html b/src/registrar/templates/portfolio_members_add_new.html
index 6d8e449f6..381a4548a 100644
--- a/src/registrar/templates/portfolio_members_add_new.html
+++ b/src/registrar/templates/portfolio_members_add_new.html
@@ -79,41 +79,37 @@
-
Admin access permissions
Member permissions available for admin-level acccess.
-
-
-
Organization domain requests
- {% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
- {% input_with_errors form.admin_org_domain_request_permissions %}
- {% endwith %}
-
Organization members
- {% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
- {% input_with_errors form.admin_org_members_permissions %}
- {% endwith %}
-
+
Organization domain requests
+ {% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
+ {% input_with_errors form.admin_org_domain_request_permissions %}
+ {% endwith %}
+
+
Organization members
+ {% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
+ {% input_with_errors form.admin_org_members_permissions %}
+ {% endwith %}
+
-
Basic member permissions
Member permissions available for basic-level access
{% input_with_errors form.basic_org_domain_request_permissions %}
-
-
- Cancel
-
+
Invite Member
From 8df16346e9676a96e7f933340a7bd4b3d1509e40 Mon Sep 17 00:00:00 2001
From: CocoByte
Date: Thu, 31 Oct 2024 15:16:54 -0600
Subject: [PATCH 56/68] Fixed error
---
src/registrar/models/domain_information.py | 67 +++++++++++++++++++
.../templates/portfolio_members_add_new.html | 4 +-
.../templates/portfolio_no_domains.html | 2 +-
3 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/src/registrar/models/domain_information.py b/src/registrar/models/domain_information.py
index 5f98197bd..7dadf26ac 100644
--- a/src/registrar/models/domain_information.py
+++ b/src/registrar/models/domain_information.py
@@ -425,3 +425,70 @@ class DomainInformation(TimeStampedModel):
return self.domain.get_state_display()
else:
return None
+
+ @property
+ def converted_organization_name(self):
+ if self.portfolio:
+ return self.portfolio.organization_name
+ return self.organization_name
+
+ # ----- Portfolio Properties -----
+ @property
+ def converted_generic_org_type(self):
+ if self.portfolio:
+ return self.portfolio.organization_type
+ return self.generic_org_type
+
+ @property
+ def converted_federal_agency(self):
+ if self.portfolio:
+ return self.portfolio.federal_agency
+ return self.federal_agency
+
+ @property
+ def converted_federal_type(self):
+ if self.portfolio:
+ return self.portfolio.federal_type
+ return self.federal_type
+
+ @property
+ def converted_senior_official(self):
+ if self.portfolio:
+ return self.portfolio.senior_official
+ return self.senior_official
+
+ @property
+ def converted_address_line1(self):
+ if self.portfolio:
+ return self.portfolio.address_line1
+ return self.address_line1
+
+ @property
+ def converted_address_line2(self):
+ if self.portfolio:
+ return self.portfolio.address_line2
+ return self.address_line2
+
+ @property
+ def converted_city(self):
+ if self.portfolio:
+ return self.portfolio.city
+ return self.city
+
+ @property
+ def converted_state_territory(self):
+ if self.portfolio:
+ return self.portfolio.state_territory
+ return self.state_territory
+
+ @property
+ def converted_zipcode(self):
+ if self.portfolio:
+ return self.portfolio.zipcode
+ return self.zipcode
+
+ @property
+ def converted_urbanization(self):
+ if self.portfolio:
+ return self.portfolio.urbanization
+ return self.urbanization
diff --git a/src/registrar/templates/portfolio_members_add_new.html b/src/registrar/templates/portfolio_members_add_new.html
index 381a4548a..fe9cb9752 100644
--- a/src/registrar/templates/portfolio_members_add_new.html
+++ b/src/registrar/templates/portfolio_members_add_new.html
@@ -20,7 +20,7 @@
- Members
+ Members
Add a new member
@@ -45,8 +45,6 @@
{% with group_classes="usa-form-editable usa-form-editable--no-border padding-top-0" %}
{% input_with_errors form.email %}
{% endwith %}
-
-
diff --git a/src/registrar/templates/portfolio_no_domains.html b/src/registrar/templates/portfolio_no_domains.html
index bc42a0e39..75ff3a91f 100644
--- a/src/registrar/templates/portfolio_no_domains.html
+++ b/src/registrar/templates/portfolio_no_domains.html
@@ -1,4 +1,4 @@
-{% extends 'portfolio_no_domains.html' %}
+{% extends 'portfolio_base.html' %}
{% load static %}
From 1d345987ca9b85e17c0d63298a766ea23ae936b1 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 08:49:32 -0600
Subject: [PATCH 57/68] PR suggestions (part 1)
---
src/registrar/forms/domain_request_wizard.py | 19 +++++-----
...tion_requested_suborganization_and_more.py | 25 +++++++++++++
src/registrar/models/domain_information.py | 18 ----------
src/registrar/models/domain_request.py | 35 ++++++++++---------
.../templates/includes/header_extended.html | 2 +-
.../portfolio_request_review_steps.html | 2 +-
src/registrar/views/domain_request.py | 10 +++++-
7 files changed, 62 insertions(+), 49 deletions(-)
create mode 100644 src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 16e5b66ea..f74622b51 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -35,7 +35,7 @@ class RequestingEntityForm(RegistrarForm):
# If this selection is made on the form (tracked by js), then it will toggle the form value of this.
# In other words, this essentially tracks if the suborganization field == "Other".
# "Other" is just an imaginary value that is otherwise invalid.
- # Note the logic in `def clean` and line 2744 in get-gov.js
+ # Note the logic in `def clean` and `handleRequestingEntityFieldset` in get-gov.js
is_requesting_new_suborganization = forms.BooleanField(required=False, widget=forms.HiddenInput())
sub_organization = forms.ModelChoiceField(
@@ -43,24 +43,22 @@ class RequestingEntityForm(RegistrarForm):
required=False,
queryset=Suborganization.objects.none(),
empty_label="--Select--",
+ error_messages={
+ "required": ("Requesting entity is required.")
+ },
)
requested_suborganization = forms.CharField(
label="Requested suborganization",
required=False,
- error_messages={"required": "Enter the name of your organization."},
)
suborganization_city = forms.CharField(
label="City",
required=False,
- error_messages={"required": "Enter the city where your organization is located."},
)
suborganization_state_territory = forms.ChoiceField(
label="State, territory, or military post",
required=False,
choices=[("", "--Select--")] + DomainRequest.StateTerritoryChoices.choices,
- error_messages={
- "required": ("Select the state, territory, or military post where your organization is located.")
- },
)
def __init__(self, *args, **kwargs):
@@ -147,17 +145,16 @@ class RequestingEntityYesNoForm(BaseYesNoForm):
if self.domain_request.portfolio:
self.form_choices = (
(False, self.domain_request.portfolio),
- (True, "A suborganization. (choose from list)"),
+ (True, "A suborganization (choose from list)"),
)
self.fields[self.field_name] = self.get_typed_choice_field()
@property
def form_is_checked(self):
"""
- Determines if the requesting entity is a suborganization, or a portfolio.
- For suborganizations, users have the ability to request a new one if the
- desired suborg doesn't exist. We expose additional fields that denote this,
- like `requested_suborganization`. So we also check on those.
+ Determines the initial checked state of the form.
+ Returns True (checked) if the requesting entity is a suborganization,
+ and False if it is a portfolio. Returns None if neither condition is met.
"""
# True means that the requesting entity is a suborganization,
# whereas False means that the requesting entity is a portfolio.
diff --git a/src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py b/src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py
new file mode 100644
index 000000000..dfa716ef4
--- /dev/null
+++ b/src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py
@@ -0,0 +1,25 @@
+# Generated by Django 4.2.10 on 2024-11-01 14:25
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("registrar", "0136_domaininformation_requested_suborganization_and_more"),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name="domaininformation",
+ name="requested_suborganization",
+ ),
+ migrations.RemoveField(
+ model_name="domaininformation",
+ name="suborganization_city",
+ ),
+ migrations.RemoveField(
+ model_name="domaininformation",
+ name="suborganization_state_territory",
+ ),
+ ]
diff --git a/src/registrar/models/domain_information.py b/src/registrar/models/domain_information.py
index 7dc257b22..7dadf26ac 100644
--- a/src/registrar/models/domain_information.py
+++ b/src/registrar/models/domain_information.py
@@ -75,24 +75,6 @@ class DomainInformation(TimeStampedModel):
verbose_name="Suborganization",
)
- requested_suborganization = models.CharField(
- null=True,
- blank=True,
- )
-
- suborganization_city = models.CharField(
- null=True,
- blank=True,
- )
-
- suborganization_state_territory = models.CharField(
- max_length=2,
- choices=StateTerritoryChoices.choices,
- null=True,
- blank=True,
- verbose_name="state, territory, or military post",
- )
-
domain_request = models.OneToOneField(
"registrar.DomainRequest",
on_delete=models.PROTECT,
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index c3fc5335d..2a0c65505 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -1127,30 +1127,30 @@ class DomainRequest(TimeStampedModel):
def requesting_entity_is_portfolio(self) -> bool:
"""Determines if this record is requesting that a portfolio be their organization.
- Used for the RequestingEntity page."""
+ Used for the RequestingEntity page.
+ Returns True if the portfolio exists and if organization_name matches portfolio.organization_name.
+ """
if self.portfolio and self.organization_name == self.portfolio.organization_name:
return True
- else:
- return False
+ return False
def requesting_entity_is_suborganization(self) -> bool:
"""Used to determine if this domain request is also requesting that it be tied to a suborganization.
- Checks if this record has a suborganization or not by checking if a suborganization exists,
- and if it doesn't, determining if properties like requested_suborganization exist.
- Used for the RequestingEntity page.
+ Returns True if portfolio exists and either sub_organization exists,
+ or if is_requesting_new_suborganization() is true.
+ Returns False otherwise.
"""
if self.portfolio and (self.sub_organization or self.is_requesting_new_suborganization()):
return True
- else:
- return False
+ return False
def is_requesting_new_suborganization(self) -> bool:
"""Used on the requesting entity form to determine if a user is trying to request
- a new suborganization using the domain request form.
+ a new suborganization using the domain request form, rather than one that already exists.
- This only occurs when no suborganization is selected, but they've filled out
- the requested_suborganization, suborganization_city, and suborganization_state_territory fields.
- Used for the RequestingEntity page.
+ Returns True if a sub_organization does not exist and if requested_suborganization,
+ suborganization_city, and suborganization_state_territory all exist.
+ Returns False otherwise.
"""
# If a suborganization already exists, it can't possibly be a new one.
@@ -1162,19 +1162,20 @@ class DomainRequest(TimeStampedModel):
]
if not self.sub_organization and all(required_fields):
return True
- else:
- return False
+ return False
# ## Form unlocking steps ## #
#
# These methods control the conditions in which we should unlock certain domain wizard steps.
def unlock_requesting_entity(self) -> bool:
- """Unlocks the requesting entity step. Used for the RequestingEntity page."""
+ """Unlocks the requesting entity step. Used for the RequestingEntity page.
+ Returns true if requesting_entity_is_suborganization() and requesting_entity_is_portfolio().
+ Returns False otherwise.
+ """
if self.requesting_entity_is_suborganization() or self.requesting_entity_is_portfolio():
return True
- else:
- return False
+ return False
# ## Form policies ## #
#
diff --git a/src/registrar/templates/includes/header_extended.html b/src/registrar/templates/includes/header_extended.html
index 7c0f55dc3..a954eb30f 100644
--- a/src/registrar/templates/includes/header_extended.html
+++ b/src/registrar/templates/includes/header_extended.html
@@ -93,7 +93,7 @@
{% endif %}
- {% if has_organization_members_flag %}
+ {% if has_organization_members_flag and not hide_members %}
Members
diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html
index ed727fee8..175a9bdc1 100644
--- a/src/registrar/templates/includes/portfolio_request_review_steps.html
+++ b/src/registrar/templates/includes/portfolio_request_review_steps.html
@@ -14,7 +14,7 @@
{% comment %} We don't have city or state_territory for suborganizations yet, so no data should display {% endcomment %}
{% elif domain_request.requesting_entity_is_suborganization %}
{% include "includes/summary_item.html" with value=domain_request.requested_suborganization edit_link=domain_request_url %}
- {{domain_request.suborganization_city}}, {{domain_request.suborganization_state_territory}}
+ {{domain_request.suborganization_city}}, {{domain_request.suborganization_state_territory}}
{% elif domain_request.requesting_entity_is_portfolio %}
{% include "includes/summary_item.html" with value=domain_request.portfolio.organization_name edit_link=domain_request_url %}
{% if domain_request.portfolio.city and domain_request.portfolio.state_territory %}
diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py
index 41e9a07b8..b1c5c9c89 100644
--- a/src/registrar/views/domain_request.py
+++ b/src/registrar/views/domain_request.py
@@ -319,7 +319,15 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
# Clear context so the prop getter won't create a request here.
# Creating a request will be handled in the post method for the
# intro page.
- return render(request, "domain_request_intro.html", {"hide_requests": True, "hide_domains": True})
+ return render(
+ request,
+ "domain_request_intro.html",
+ {
+ "hide_requests": True,
+ "hide_domains": True,
+ "hide_members": True,
+ },
+ )
else:
return self.goto(self.steps.first)
From 83720c359fd6448dc4647f610934bf5a126c7ef7 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 08:54:32 -0600
Subject: [PATCH 58/68] Update admin.py
---
src/registrar/admin.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index fdadde436..84609468f 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1484,9 +1484,6 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"fields": [
"portfolio",
"sub_organization",
- "requested_suborganization",
- "suborganization_city",
- "suborganization_state_territory",
"creator",
"domain_request",
"notes",
From b05a62ecd195bad8e7585c7cb7985bb298e4dad5 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 09:10:28 -0600
Subject: [PATCH 59/68] Rework readonly fields for analysts + hide when org
flag is off
---
src/registrar/admin.py | 25 +++++++++++++------------
src/registrar/models/domain_request.py | 6 ++++--
2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 84609468f..fe59c7d1f 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -28,6 +28,7 @@ from waffle.models import Sample, Switch
from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website, SeniorOfficial
from registrar.utility.constants import BranchChoices
from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes
+from registrar.utility.waffle import flag_is_active_for_user
from registrar.views.utility.mixins import OrderableFieldsMixin
from django.contrib.admin.views.main import ORDER_VAR
from registrar.widgets import NoAutocompleteFilteredSelectMultiple
@@ -1863,6 +1864,9 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"cisa_representative_first_name",
"cisa_representative_last_name",
"cisa_representative_email",
+ "requested_suborganization",
+ "suborganization_city",
+ "suborganization_state_territory",
]
autocomplete_fields = [
"approved_domain",
@@ -1882,24 +1886,21 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
change_form_template = "django/admin/domain_request_change_form.html"
- # While the organization feature is under development, we can gate some fields
- # from analysts for now. Remove this array and the get_fieldset overrides once this is done.
- # Not my code initially, credit to Nicolle. This was once removed and like a phoenix it has been reborn.
- superuser_only_fields = [
- "requested_suborganization",
- "suborganization_city",
- "suborganization_state_territory",
- ]
-
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)
- # Create a modified version of fieldsets to exclude certain fields
- if not request.user.has_perm("registrar.full_access_permission"):
+ # Hide certain suborg fields behind the organization feature flag
+ # if it is not enabled
+ if not flag_is_active_for_user(request.user, "organization_feature"):
+ excluded_fields = [
+ "requested_suborganization",
+ "suborganization_city",
+ "suborganization_state_territory",
+ ]
modified_fieldsets = []
for name, data in fieldsets:
fields = data.get("fields", [])
- fields = tuple(field for field in fields if field not in self.superuser_only_fields)
+ fields = tuple(field for field in fields if field not in excluded_fields)
modified_fieldsets.append((name, {**data, "fields": fields}))
return modified_fieldsets
return fieldsets
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index 2a0c65505..ca4b322be 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -1135,7 +1135,8 @@ class DomainRequest(TimeStampedModel):
return False
def requesting_entity_is_suborganization(self) -> bool:
- """Used to determine if this domain request is also requesting that it be tied to a suborganization.
+ """Determines if this record is also requesting that it be tied to a suborganization.
+ Used for the RequestingEntity page.
Returns True if portfolio exists and either sub_organization exists,
or if is_requesting_new_suborganization() is true.
Returns False otherwise.
@@ -1145,8 +1146,9 @@ class DomainRequest(TimeStampedModel):
return False
def is_requesting_new_suborganization(self) -> bool:
- """Used on the requesting entity form to determine if a user is trying to request
+ """Determines if a user is trying to request
a new suborganization using the domain request form, rather than one that already exists.
+ Used for the RequestingEntity page.
Returns True if a sub_organization does not exist and if requested_suborganization,
suborganization_city, and suborganization_state_territory all exist.
From 7cdfb7a35fcbae398a2786643068ec1a3272ad5f Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 10:15:40 -0600
Subject: [PATCH 60/68] fix test + lint
---
src/registrar/forms/domain_request_wizard.py | 14 ++++++--------
src/registrar/tests/test_admin_request.py | 5 ++++-
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index f74622b51..010890b04 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -43,9 +43,6 @@ class RequestingEntityForm(RegistrarForm):
required=False,
queryset=Suborganization.objects.none(),
empty_label="--Select--",
- error_messages={
- "required": ("Requesting entity is required.")
- },
)
requested_suborganization = forms.CharField(
label="Requested suborganization",
@@ -118,13 +115,13 @@ class RequestingEntityForm(RegistrarForm):
if is_requesting_new_suborganization:
# Validate custom suborganization fields
if not cleaned_data.get("requested_suborganization"):
- self.add_error("requested_suborganization", "Enter details for your organization name.")
+ self.add_error("requested_suborganization", "Organization name is required.")
if not cleaned_data.get("suborganization_city"):
- self.add_error("suborganization_city", "Enter details for your city.")
+ self.add_error("suborganization_city", "City is required.")
if not cleaned_data.get("suborganization_state_territory"):
- self.add_error("suborganization_state_territory", "Enter details for your state or territory.")
+ self.add_error("suborganization_state_territory", "State or territory is required.")
elif not suborganization:
- self.add_error("sub_organization", "Select a suborganization.")
+ self.add_error("sub_organization", "Suborganization is required.")
return cleaned_data
@@ -138,6 +135,7 @@ class RequestingEntityYesNoForm(BaseYesNoForm):
# IMPORTANT: This is tied to DomainRequest.is_requesting_new_suborganization().
# This is due to the from_database method on DomainRequestWizard.
field_name = "requesting_entity_is_suborganization"
+ required_error_message = "Requesting entity is required."
def __init__(self, *args, **kwargs):
"""Extend the initialization of the form from RegistrarForm __init__"""
@@ -153,7 +151,7 @@ class RequestingEntityYesNoForm(BaseYesNoForm):
def form_is_checked(self):
"""
Determines the initial checked state of the form.
- Returns True (checked) if the requesting entity is a suborganization,
+ Returns True (checked) if the requesting entity is a suborganization,
and False if it is a portfolio. Returns None if neither condition is met.
"""
# True means that the requesting entity is a suborganization,
diff --git a/src/registrar/tests/test_admin_request.py b/src/registrar/tests/test_admin_request.py
index 4b65c401d..57d7d9ac6 100644
--- a/src/registrar/tests/test_admin_request.py
+++ b/src/registrar/tests/test_admin_request.py
@@ -1689,7 +1689,7 @@ class TestDomainRequestAdmin(MockEppLib):
request.user = self.staffuser
readonly_fields = self.admin.get_readonly_fields(request)
-
+ self.maxDiff = None
expected_fields = [
"other_contacts",
"current_websites",
@@ -1709,6 +1709,9 @@ class TestDomainRequestAdmin(MockEppLib):
"cisa_representative_first_name",
"cisa_representative_last_name",
"cisa_representative_email",
+ "requested_suborganization",
+ "suborganization_city",
+ "suborganization_state_territory",
]
self.assertEqual(readonly_fields, expected_fields)
From c59289d2150498444d01244e78afaecf9670de7d Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 10:18:46 -0600
Subject: [PATCH 61/68] Update domain_request_wizard.py
---
src/registrar/forms/domain_request_wizard.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 010890b04..d9754c87e 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -115,13 +115,13 @@ class RequestingEntityForm(RegistrarForm):
if is_requesting_new_suborganization:
# Validate custom suborganization fields
if not cleaned_data.get("requested_suborganization"):
- self.add_error("requested_suborganization", "Organization name is required.")
+ self.add_error("requested_suborganization", "Enter details for your organization name.")
if not cleaned_data.get("suborganization_city"):
- self.add_error("suborganization_city", "City is required.")
+ self.add_error("suborganization_city", "Enter details for your city.")
if not cleaned_data.get("suborganization_state_territory"):
- self.add_error("suborganization_state_territory", "State or territory is required.")
+ self.add_error("suborganization_state_territory", "Enter details for your state or territory.")
elif not suborganization:
- self.add_error("sub_organization", "Suborganization is required.")
+ self.add_error("sub_organization", "Select a suborganization.")
return cleaned_data
From 7141eaed924ae2cd26b7382cd96e7312c0ea1ea9 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 11:02:16 -0600
Subject: [PATCH 62/68] consolidate migration
---
...est_requested_suborganization_and_more.py} | 84 +------------------
...tion_requested_suborganization_and_more.py | 25 ------
2 files changed, 1 insertion(+), 108 deletions(-)
rename src/registrar/migrations/{0136_domaininformation_requested_suborganization_and_more.py => 0136_domainrequest_requested_suborganization_and_more.py} (50%)
delete mode 100644 src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py
diff --git a/src/registrar/migrations/0136_domaininformation_requested_suborganization_and_more.py b/src/registrar/migrations/0136_domainrequest_requested_suborganization_and_more.py
similarity index 50%
rename from src/registrar/migrations/0136_domaininformation_requested_suborganization_and_more.py
rename to src/registrar/migrations/0136_domainrequest_requested_suborganization_and_more.py
index dc6ec9d5d..e1b130b4f 100644
--- a/src/registrar/migrations/0136_domaininformation_requested_suborganization_and_more.py
+++ b/src/registrar/migrations/0136_domainrequest_requested_suborganization_and_more.py
@@ -1,4 +1,4 @@
-# Generated by Django 4.2.10 on 2024-10-30 17:59
+# Generated by Django 4.2.10 on 2024-11-01 17:01
from django.db import migrations, models
@@ -10,88 +10,6 @@ class Migration(migrations.Migration):
]
operations = [
- migrations.AddField(
- model_name="domaininformation",
- name="requested_suborganization",
- field=models.CharField(blank=True, null=True),
- ),
- migrations.AddField(
- model_name="domaininformation",
- name="suborganization_city",
- field=models.CharField(blank=True, null=True),
- ),
- migrations.AddField(
- model_name="domaininformation",
- name="suborganization_state_territory",
- field=models.CharField(
- blank=True,
- choices=[
- ("AL", "Alabama (AL)"),
- ("AK", "Alaska (AK)"),
- ("AS", "American Samoa (AS)"),
- ("AZ", "Arizona (AZ)"),
- ("AR", "Arkansas (AR)"),
- ("CA", "California (CA)"),
- ("CO", "Colorado (CO)"),
- ("CT", "Connecticut (CT)"),
- ("DE", "Delaware (DE)"),
- ("DC", "District of Columbia (DC)"),
- ("FL", "Florida (FL)"),
- ("GA", "Georgia (GA)"),
- ("GU", "Guam (GU)"),
- ("HI", "Hawaii (HI)"),
- ("ID", "Idaho (ID)"),
- ("IL", "Illinois (IL)"),
- ("IN", "Indiana (IN)"),
- ("IA", "Iowa (IA)"),
- ("KS", "Kansas (KS)"),
- ("KY", "Kentucky (KY)"),
- ("LA", "Louisiana (LA)"),
- ("ME", "Maine (ME)"),
- ("MD", "Maryland (MD)"),
- ("MA", "Massachusetts (MA)"),
- ("MI", "Michigan (MI)"),
- ("MN", "Minnesota (MN)"),
- ("MS", "Mississippi (MS)"),
- ("MO", "Missouri (MO)"),
- ("MT", "Montana (MT)"),
- ("NE", "Nebraska (NE)"),
- ("NV", "Nevada (NV)"),
- ("NH", "New Hampshire (NH)"),
- ("NJ", "New Jersey (NJ)"),
- ("NM", "New Mexico (NM)"),
- ("NY", "New York (NY)"),
- ("NC", "North Carolina (NC)"),
- ("ND", "North Dakota (ND)"),
- ("MP", "Northern Mariana Islands (MP)"),
- ("OH", "Ohio (OH)"),
- ("OK", "Oklahoma (OK)"),
- ("OR", "Oregon (OR)"),
- ("PA", "Pennsylvania (PA)"),
- ("PR", "Puerto Rico (PR)"),
- ("RI", "Rhode Island (RI)"),
- ("SC", "South Carolina (SC)"),
- ("SD", "South Dakota (SD)"),
- ("TN", "Tennessee (TN)"),
- ("TX", "Texas (TX)"),
- ("UM", "United States Minor Outlying Islands (UM)"),
- ("UT", "Utah (UT)"),
- ("VT", "Vermont (VT)"),
- ("VI", "Virgin Islands (VI)"),
- ("VA", "Virginia (VA)"),
- ("WA", "Washington (WA)"),
- ("WV", "West Virginia (WV)"),
- ("WI", "Wisconsin (WI)"),
- ("WY", "Wyoming (WY)"),
- ("AA", "Armed Forces Americas (AA)"),
- ("AE", "Armed Forces Africa, Canada, Europe, Middle East (AE)"),
- ("AP", "Armed Forces Pacific (AP)"),
- ],
- max_length=2,
- null=True,
- verbose_name="state, territory, or military post",
- ),
- ),
migrations.AddField(
model_name="domainrequest",
name="requested_suborganization",
diff --git a/src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py b/src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py
deleted file mode 100644
index dfa716ef4..000000000
--- a/src/registrar/migrations/0137_remove_domaininformation_requested_suborganization_and_more.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Generated by Django 4.2.10 on 2024-11-01 14:25
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("registrar", "0136_domaininformation_requested_suborganization_and_more"),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name="domaininformation",
- name="requested_suborganization",
- ),
- migrations.RemoveField(
- model_name="domaininformation",
- name="suborganization_city",
- ),
- migrations.RemoveField(
- model_name="domaininformation",
- name="suborganization_state_territory",
- ),
- ]
From a1d37ee207e3d16b14a5c1d4dde486965cd01590 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 11:02:43 -0600
Subject: [PATCH 63/68] Update
src/registrar/templates/includes/portfolio_request_review_steps.html
Co-authored-by: Rachid Mrad <107004823+rachidatecs@users.noreply.github.com>
---
.../templates/includes/portfolio_request_review_steps.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html
index 175a9bdc1..d0bdd7ba0 100644
--- a/src/registrar/templates/includes/portfolio_request_review_steps.html
+++ b/src/registrar/templates/includes/portfolio_request_review_steps.html
@@ -18,7 +18,7 @@
{% elif domain_request.requesting_entity_is_portfolio %}
{% include "includes/summary_item.html" with value=domain_request.portfolio.organization_name edit_link=domain_request_url %}
{% if domain_request.portfolio.city and domain_request.portfolio.state_territory %}
- {{domain_request.portfolio.city}}, {{domain_request.portfolio.state_territory}}
+ {{domain_request.portfolio.city}}, {{domain_request.portfolio.state_territory}}
{% endif %}
{% else %}
{% with value="Incomplete "|safe %}
From 706dd4fe2e9dcc0076bb46aa39aaa0d204b5753a Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 11:17:38 -0600
Subject: [PATCH 64/68] error messages! @abroddrick
---
src/registrar/forms/domain_request_wizard.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index d9754c87e..0b560f19c 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -115,11 +115,11 @@ class RequestingEntityForm(RegistrarForm):
if is_requesting_new_suborganization:
# Validate custom suborganization fields
if not cleaned_data.get("requested_suborganization"):
- self.add_error("requested_suborganization", "Enter details for your organization name.")
+ self.add_error("requested_suborganization", "Requested suborganization is required")
if not cleaned_data.get("suborganization_city"):
- self.add_error("suborganization_city", "Enter details for your city.")
+ self.add_error("suborganization_city", "City is required")
if not cleaned_data.get("suborganization_state_territory"):
- self.add_error("suborganization_state_territory", "Enter details for your state or territory.")
+ self.add_error("suborganization_state_territory", "State, territory, or military post is required")
elif not suborganization:
self.add_error("sub_organization", "Select a suborganization.")
From e4c15ee28b30817d201130ed0e79384d78ff65e9 Mon Sep 17 00:00:00 2001
From: zandercymatics <141044360+zandercymatics@users.noreply.github.com>
Date: Fri, 1 Nov 2024 11:40:19 -0600
Subject: [PATCH 65/68] Fix unit test
---
src/registrar/forms/domain_request_wizard.py | 8 ++++----
src/registrar/tests/test_views_portfolio.py | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/registrar/forms/domain_request_wizard.py b/src/registrar/forms/domain_request_wizard.py
index 0b560f19c..bfbc22124 100644
--- a/src/registrar/forms/domain_request_wizard.py
+++ b/src/registrar/forms/domain_request_wizard.py
@@ -115,13 +115,13 @@ class RequestingEntityForm(RegistrarForm):
if is_requesting_new_suborganization:
# Validate custom suborganization fields
if not cleaned_data.get("requested_suborganization"):
- self.add_error("requested_suborganization", "Requested suborganization is required")
+ self.add_error("requested_suborganization", "Requested suborganization is required.")
if not cleaned_data.get("suborganization_city"):
- self.add_error("suborganization_city", "City is required")
+ self.add_error("suborganization_city", "City is required.")
if not cleaned_data.get("suborganization_state_territory"):
- self.add_error("suborganization_state_territory", "State, territory, or military post is required")
+ self.add_error("suborganization_state_territory", "State, territory, or military post is required.")
elif not suborganization:
- self.add_error("sub_organization", "Select a suborganization.")
+ self.add_error("sub_organization", "Suborganization is required.")
return cleaned_data
diff --git a/src/registrar/tests/test_views_portfolio.py b/src/registrar/tests/test_views_portfolio.py
index 45357cbf7..402d23b70 100644
--- a/src/registrar/tests/test_views_portfolio.py
+++ b/src/registrar/tests/test_views_portfolio.py
@@ -1788,15 +1788,15 @@ class TestRequestingEntity(WebTest):
response = form.submit()
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
- self.assertContains(response, "Select a suborganization.", status_code=200)
+ self.assertContains(response, "Suborganization is required.", status_code=200)
# Test missing custom suborganization details
form["portfolio_requesting_entity-is_requesting_new_suborganization"] = True
response = form.submit()
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
- self.assertContains(response, "Enter details for your organization name.", status_code=200)
- self.assertContains(response, "Enter details for your city.", status_code=200)
- self.assertContains(response, "Enter details for your state or territory.", status_code=200)
+ self.assertContains(response, "Requested suborganization is required.", status_code=200)
+ self.assertContains(response, "City is required.", status_code=200)
+ self.assertContains(response, "State, territory, or military post is required.", status_code=200)
@override_flag("organization_feature", active=True)
@override_flag("organization_requests", active=True)
From b66f746aaa56375879c752f620c85b4bf7ceb341 Mon Sep 17 00:00:00 2001
From: Matt-Spence
Date: Fri, 1 Nov 2024 15:35:20 -0500
Subject: [PATCH 66/68] refactor clone-staging.yaml
---
.github/workflows/clone-staging.yaml | 62 +++++++++++-----------------
1 file changed, 24 insertions(+), 38 deletions(-)
diff --git a/.github/workflows/clone-staging.yaml b/.github/workflows/clone-staging.yaml
index df943f138..5989d3286 100644
--- a/.github/workflows/clone-staging.yaml
+++ b/.github/workflows/clone-staging.yaml
@@ -21,41 +21,27 @@ jobs:
CF_USERNAME: CF_MS_USERNAME
CF_PASSWORD: CF_MS_PASSWORD
steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Setup Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.13'
- cache: 'pip' # caching pip dependencies
-
- - name: Install CG Tool
- run: pip install git+https://github.com/cloud-gov/cg-manage-rds.git
-
- - name: Share DB Service
- uses: cloud-gov/cg-cli-tools@main
- with:
- cf_username: ${{ secrets[env.CF_USERNAME] }}
- cf_password: ${{ secrets[env.CF_PASSWORD] }}
- cf_org: cisa-dotgov
- cf_space: ${{ env.DESTINATION_ENVIRONMENT }}
- cf_command: share-service getgov-${{ env.DESTINATION_ENVIRONMENT }}-database -s ${{ env.SOURCE_ENVIRONMENT }}
-
- - name: Clone Database
- uses: cloud-gov/cg-cli-tools@main
- with:
- cf_username: ${{ secrets.CF_MS_USERNAME }}
- cf_password: ${{ secrets.CF_MS_PASSWORD }}
- cf_org: cisa-dotgov
- cf_space: ${{ env.SOURCE_ENVIRONMENT }}
- command: cg-manage-rds clone getgov-${{ env.SOURCE_ENVIRONMENT }}-database getgov-${{ env.DESTINATION_ENVIRONMENT }}-database
-
- - name: Unshare DB Service
- uses: cloud-gov/cg-cli-tools@main
- with:
- cf_username: ${{ secrets.CF_MS_USERNAME }}
- cf_password: ${{ secrets.CF_MS_PASSWORD }}
- cf_org: cisa-dotgov
- cf_space: ${{ env.SOURCE_ENVIRONMENT }}
- cf_command: unshare-service getgov-${{ env.DESTINATION_ENVIRONMENT }}-database -s ${{ env.SOURCE_ENVIRONMENT }}
+ - name: Clone Database
+ run: |
+ # install cf cli
+ wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo gpg --dearmor -o /usr/share/keyrings/cli.cloudfoundry.org.gpg
+ echo "deb [signed-by=/usr/share/keyrings/cli.cloudfoundry.org.gpg] https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list
+
+ sudo apt-get update
+ sudo apt-get install cf8-cli
+ # install cg-manage-rds tool
+ pip install git+https://github.com/cloud-gov/cg-manage-rds.git
+
+ # Authenticate and target CF org and space.
+ cf api api.fr.cloud.gov
+ cf auth ${{ secrets[env.CF_USERNAME] }} ${{ secrets[env.CF_PASSWORD] }}
+ cf target -o cisa-dotgov -s ${{ env.DESTINATION_ENVIRONMENT }}
+
+ # share the target db with the source space
+ cf share-service getgov-${{ env.DESTINATION_ENVIRONMENT }}-database -s ${{ env.SOURCE_ENVIRONMENT }}
+
+ # clone from source to destination
+ cg-manage-rds clone getgov-${{ env.DESTINATION_ENVIRONMENT }}-database getgov-${{ env.SOURCE_ENVIRONMENT }}-database
+
+ # unshare the service
+ cf unshare-service getgov-${{ env.DESTINATION_ENVIRONMENT }}-database -s ${{ env.SOURCE_ENVIRONMENT }}
From 0f39a731958627583668a5bb889783b525b6df97 Mon Sep 17 00:00:00 2001
From: Matt-Spence
Date: Fri, 1 Nov 2024 16:03:03 -0500
Subject: [PATCH 67/68] Update clone-staging.yaml
---
.github/workflows/clone-staging.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/clone-staging.yaml b/.github/workflows/clone-staging.yaml
index 5989d3286..703c9bc44 100644
--- a/.github/workflows/clone-staging.yaml
+++ b/.github/workflows/clone-staging.yaml
@@ -23,12 +23,12 @@ jobs:
steps:
- name: Clone Database
run: |
- # install cf cli
+ # install cf cli and other tools
wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo gpg --dearmor -o /usr/share/keyrings/cli.cloudfoundry.org.gpg
echo "deb [signed-by=/usr/share/keyrings/cli.cloudfoundry.org.gpg] https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list
sudo apt-get update
- sudo apt-get install cf8-cli
+ sudo apt-get install cf8-cli postgresql-client
# install cg-manage-rds tool
pip install git+https://github.com/cloud-gov/cg-manage-rds.git
From 48eb586b922c84802b6db604abaa9cbd33293ea7 Mon Sep 17 00:00:00 2001
From: Matt-Spence
Date: Mon, 4 Nov 2024 10:52:49 -0600
Subject: [PATCH 68/68] Update clone-staging.yaml
---
.github/workflows/clone-staging.yaml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/clone-staging.yaml b/.github/workflows/clone-staging.yaml
index 703c9bc44..edfbffa05 100644
--- a/.github/workflows/clone-staging.yaml
+++ b/.github/workflows/clone-staging.yaml
@@ -18,8 +18,8 @@ jobs:
clone-database:
runs-on: ubuntu-latest
env:
- CF_USERNAME: CF_MS_USERNAME
- CF_PASSWORD: CF_MS_PASSWORD
+ CF_USERNAME: ${{ secrets[env.CF_USERNAME] }}
+ CF_PASSWORD: ${{ secrets[env.CF_PASSWORD] }}
steps:
- name: Clone Database
run: |
@@ -34,14 +34,14 @@ jobs:
# Authenticate and target CF org and space.
cf api api.fr.cloud.gov
- cf auth ${{ secrets[env.CF_USERNAME] }} ${{ secrets[env.CF_PASSWORD] }}
- cf target -o cisa-dotgov -s ${{ env.DESTINATION_ENVIRONMENT }}
+ cf auth $CF_USERNAME $CF_PASSWORD
+ cf target -o cisa-dotgov -s $DESTINATION_ENVIRONMENT
# share the target db with the source space
- cf share-service getgov-${{ env.DESTINATION_ENVIRONMENT }}-database -s ${{ env.SOURCE_ENVIRONMENT }}
+ cf share-service getgov-$DESTINATION_ENVIRONMENT-database -s $SOURCE_ENVIRONMENT
# clone from source to destination
- cg-manage-rds clone getgov-${{ env.DESTINATION_ENVIRONMENT }}-database getgov-${{ env.SOURCE_ENVIRONMENT }}-database
+ cg-manage-rds clone getgov-$DESTINATION_ENVIRONMENT-database getgov-$SOURCE_ENVIRONMENT-database
# unshare the service
- cf unshare-service getgov-${{ env.DESTINATION_ENVIRONMENT }}-database -s ${{ env.SOURCE_ENVIRONMENT }}
+ cf unshare-service getgov-$DESTINATION_ENVIRONMENT-database -s $SOURCE_ENVIRONMENT