From bffd8e209060431593e6b85d3fdeb1b94d0916c4 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Tue, 25 Mar 2025 13:28:50 -0500 Subject: [PATCH 01/27] fix tests --- .../templates/emails/includes/domain_request_summary.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/registrar/templates/emails/includes/domain_request_summary.txt b/src/registrar/templates/emails/includes/domain_request_summary.txt index b5f216e03..c58aef5e1 100644 --- a/src/registrar/templates/emails/includes/domain_request_summary.txt +++ b/src/registrar/templates/emails/includes/domain_request_summary.txt @@ -41,6 +41,7 @@ Alternative domains: {% endfor %}{% endif %} Purpose of your domain: {{ domain_request.purpose }} + Your contact information: {% spaceless %}{% include "emails/includes/contact.txt" with contact=recipient %}{% endspaceless %} @@ -48,8 +49,7 @@ Other employees from your organization:{% for other in domain_request.other_cont {% spaceless %}{% include "emails/includes/contact.txt" with contact=other %}{% endspaceless %} {% empty %} {{ domain_request.no_other_contacts_rationale }} -{% endfor %} -{% if domain_request.anything_else %} - Anything else? - {{ domain_request.anything_else }} +{% endfor %}{% if domain_request.anything_else %} +Anything else? +{{ domain_request.anything_else }} {% endif %} \ No newline at end of file From 20d4923e8711e67bc27be20388690a3484062674 Mon Sep 17 00:00:00 2001 From: Matt-Spence Date: Tue, 25 Mar 2025 15:21:10 -0500 Subject: [PATCH 02/27] Update src/registrar/views/domain_request.py Co-authored-by: zandercymatics <141044360+zandercymatics@users.noreply.github.com> --- src/registrar/views/domain_request.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 13ff9e264..ddd8ddf7d 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -1178,8 +1178,6 @@ class PortfolioDomainRequestStatusViewOnly(DetailView): context["Step"] = PortfolioDomainRequestStep.__members__ context["steps"] = request_step_list(wizard, PortfolioDomainRequestStep) context["form_titles"] = wizard.titles - logger.debug(self.object.is_feb()) - logger.debug(flag_is_active_for_user(self.request.user, "organization_feature")) context["requires_feb_questions"] = self.object.is_feb() and flag_is_active_for_user( self.request.user, "organization_feature" ) From 968a68f248f1cbc0e8958300f6ee21b1820bd272 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 11:17:21 -0500 Subject: [PATCH 03/27] review fixes --- src/registrar/admin.py | 16 +--------------- src/registrar/models/domain_request.py | 19 ++++++++++--------- .../portfolio_domain_request_summary.txt | 2 +- .../portfolio_request_review_steps.html | 10 ++-------- src/registrar/views/domain_request.py | 3 +-- 5 files changed, 15 insertions(+), 35 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index bff9b86cb..dcb92c145 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -2737,23 +2737,15 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): def feb_naming_requirements_details(self, obj): return obj.feb_naming_requirements_details if obj.feb_naming_requirements else "" - feb_naming_requirements_details.short_description = "Domain Name Rationale:" # type: ignore - def feb_purpose_choice(self, obj): return obj.feb_purpose_choice if obj.feb_purpose_choice else "" - feb_purpose_choice.short_description = "Purpose type:" # type: ignore - def time_frame_details(self, obj): return obj.time_frame_details if obj.has_timeframe else "" - time_frame_details.short_description = "Target time frame:" # type: ignore - def interagency_initiative_details(self, obj): return obj.interagency_initiative_details if obj.is_interagency_initiative else "" - interagency_initiative_details.short_description = "Interagency Initiative:" # type: ignore - def eop_stakeholder_first_name(self, obj): return obj.eop_stakeholder_first_name if obj.eop_stakeholder_first_name else "" @@ -2762,11 +2754,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): def eop_stakeholder_email(self, obj): return obj.eop_stakeholder_email if obj.eop_stakeholder_email else "" - - eop_stakeholder_first_name.short_description = "EOP Stakeholder First Name" # type: ignore - eop_stakeholder_last_name.short_description = "EOP Stakeholder Last Name" # type: ignore - eop_stakeholder_email.short_description = "EOP Stakeholder Email" # type: ignore - + # This is just a placeholder. This field will be populated in the detail_table_fieldset view. # This is not a field that exists on the model. def status_history(self, obj): @@ -3107,8 +3095,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): "eop_stakeholder_email", ] ) - # This makes .gov domain collapsable underneath Requested By - fieldsets[2][1]["classes"] = ["collapse--dgfieldset"] modified_fieldsets = [] for name, data in fieldsets: fields = data.get("fields", []) diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py index 8a64aad63..d13fde518 100644 --- a/src/registrar/models/domain_request.py +++ b/src/registrar/models/domain_request.py @@ -55,19 +55,17 @@ class DomainRequest(TimeStampedModel): return cls(status_name).label if status_name else None class FEBPurposeChoices(models.TextChoices): - WEBSITE = "website" - REDIRECT = "redirect" - OTHER = "other" + WEBSITE = "website", "Used for a new website" + REDIRECT = "redirect", "Used as a redirect for an existing website" + OTHER = "other", "Not for a website" @classmethod def get_purpose_label(cls, purpose_name: str): """Returns the associated label for a given purpose name""" - if purpose_name == cls.WEBSITE: - return "Used for a new website" - elif purpose_name == cls.REDIRECT: - return "Used as a redirect for an existing website" - else: - return "Not for a website" + logger.debug(f"purpose_name: {purpose_name}") + logger.debug(f"label: {cls(purpose_name).label}") + return cls(purpose_name).label if purpose_name else None + class StateTerritoryChoices(models.TextChoices): ALABAMA = "AL", "Alabama (AL)" @@ -520,6 +518,7 @@ class DomainRequest(TimeStampedModel): feb_naming_requirements = models.BooleanField( null=True, blank=True, + verbose_name="Meets Naming Requirements", ) feb_naming_requirements_details = models.TextField( @@ -1030,12 +1029,14 @@ class DomainRequest(TimeStampedModel): has_organization_feature_flag = flag_is_active_for_user(recipient, "organization_feature") is_org_user = has_organization_feature_flag and recipient.has_view_portfolio_permission(self.portfolio) requires_feb_questions = self.is_feb() and is_org_user + purpose_label = DomainRequest.FEBPurposeChoices.get_purpose_label(self.purpose) context = { "domain_request": self, # This is the user that we refer to in the email "recipient": recipient, "is_org_user": is_org_user, "requires_feb_questions": requires_feb_questions, + "purpose_label": purpose_label, } if custom_email_content: diff --git a/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt b/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt index 66b0a0970..42d75e4b2 100644 --- a/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt +++ b/src/registrar/templates/emails/includes/portfolio_domain_request_summary.txt @@ -23,7 +23,7 @@ Alternative domains: {% endfor %}{% endif %} Purpose of your domain: {% if requires_feb_questions %} -{{ domain_request.feb_purpose_choice }} +{{ purpose_label }} {{ domain_request.purpose }} Target time frame: {% if domain_request.has_target_time_frame %} diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html index 14706275d..98f951d9c 100644 --- a/src/registrar/templates/includes/portfolio_request_review_steps.html +++ b/src/registrar/templates/includes/portfolio_request_review_steps.html @@ -72,14 +72,8 @@ {% endwith %} {% if requires_feb_questions %}

Purpose

- {% if domain_request.feb_purpose_choice == "website" %} -

Used for a new website

-

{{domain_request.purpose}}

- {% elif domain_request.feb_purpose_choice == "redirect" %} -

Used as a redirect for an existing website

-

{{domain_request.purpose}}

- {% elif domain_request.feb_purpose_choice == "other" %} -

Not for a website

+ {% if domain_request.feb_purpose_choice %} +

{{purpose_label}}

{{domain_request.purpose}}

{% else %}

Incomplete

diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 13ff9e264..f3deab36f 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -1178,11 +1178,10 @@ class PortfolioDomainRequestStatusViewOnly(DetailView): context["Step"] = PortfolioDomainRequestStep.__members__ context["steps"] = request_step_list(wizard, PortfolioDomainRequestStep) context["form_titles"] = wizard.titles - logger.debug(self.object.is_feb()) - logger.debug(flag_is_active_for_user(self.request.user, "organization_feature")) context["requires_feb_questions"] = self.object.is_feb() and flag_is_active_for_user( self.request.user, "organization_feature" ) + context["purpose_label"] = DomainRequest.FEBPurposeChoices.get_purpose_label(self.object.purpose) return context From 61cc84b67e128a2166d168655bf1c77eb80eed8a Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 11:24:42 -0500 Subject: [PATCH 04/27] hardwire FEB to true for testing --- src/registrar/views/domain_request.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index f3deab36f..90115e03a 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -183,7 +183,8 @@ class DomainRequestWizard(TemplateView): return PortfolioDomainRequestStep if self.is_portfolio else Step def requires_feb_questions(self) -> bool: - return self.domain_request.is_feb() and flag_is_active_for_user(self.request.user, "organization_feature") + # return self.domain_request.is_feb() and flag_is_active_for_user(self.request.user, "organization_feature") + return True @property def prefix(self): From 241f2b7d81e9d18809b55cdc751440e478409381 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 11:31:34 -0500 Subject: [PATCH 05/27] fix 500 error on additional details step --- .../templates/portfolio_domain_request_additional_details.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/templates/portfolio_domain_request_additional_details.html b/src/registrar/templates/portfolio_domain_request_additional_details.html index d7d53dd1a..98b33bf7f 100644 --- a/src/registrar/templates/portfolio_domain_request_additional_details.html +++ b/src/registrar/templates/portfolio_domain_request_additional_details.html @@ -58,7 +58,7 @@

This question is optional.

{% with attr_maxlength=2000 add_label_class="usa-sr-only" %} - {% input_with_errors forms.0.anything_else %} + {% input_with_errors forms.3.anything_else %} {% endwith %}
{% endif %} From 15795dd333e0e446310355615bd446ec2795c558 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 11:46:21 -0500 Subject: [PATCH 06/27] review fixes --- src/registrar/forms/feb.py | 7 ++----- src/registrar/models/domain_request.py | 4 ++-- src/registrar/views/domain_request.py | 3 ++- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/registrar/forms/feb.py b/src/registrar/forms/feb.py index 2dabbff0d..fbb11a6ea 100644 --- a/src/registrar/forms/feb.py +++ b/src/registrar/forms/feb.py @@ -1,6 +1,7 @@ from django import forms from django.core.validators import MaxLengthValidator from registrar.forms.utility.wizard_form_helper import BaseDeletableRegistrarForm, BaseYesNoForm +from registrar.models.domain_request import DomainRequest class ExecutiveNamingRequirementsYesNoForm(BaseYesNoForm, BaseDeletableRegistrarForm): @@ -41,11 +42,7 @@ class FEBPurposeOptionsForm(BaseDeletableRegistrarForm): field_name = "feb_purpose_choice" - form_choices = ( - ("new", "Used for a new website"), - ("redirect", "Used as a redirect for an existing website"), - ("other", "Not for a website"), - ) + form_choices = DomainRequest.FEBPurposeChoices.choices feb_purpose_choice = forms.ChoiceField( required=True, diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py index d13fde518..f2560aae9 100644 --- a/src/registrar/models/domain_request.py +++ b/src/registrar/models/domain_request.py @@ -55,7 +55,7 @@ class DomainRequest(TimeStampedModel): return cls(status_name).label if status_name else None class FEBPurposeChoices(models.TextChoices): - WEBSITE = "website", "Used for a new website" + WEBSITE = "new", "Used for a new website" REDIRECT = "redirect", "Used as a redirect for an existing website" OTHER = "other", "Not for a website" @@ -1029,7 +1029,7 @@ class DomainRequest(TimeStampedModel): has_organization_feature_flag = flag_is_active_for_user(recipient, "organization_feature") is_org_user = has_organization_feature_flag and recipient.has_view_portfolio_permission(self.portfolio) requires_feb_questions = self.is_feb() and is_org_user - purpose_label = DomainRequest.FEBPurposeChoices.get_purpose_label(self.purpose) + purpose_label = DomainRequest.FEBPurposeChoices.get_purpose_label(self.feb_purpose_choice) context = { "domain_request": self, # This is the user that we refer to in the email diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 90115e03a..9b11dc104 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -966,6 +966,7 @@ class Review(DomainRequestWizard): context["Step"] = self.get_step_enum().__members__ context["domain_request"] = self.domain_request context["requires_feb_questions"] = self.requires_feb_questions() + context["purpose_label"] = DomainRequest.FEBPurposeChoices.get_purpose_label(self.domain_request.feb_purpose_choice) return context def goto_next_step(self): @@ -1182,7 +1183,7 @@ class PortfolioDomainRequestStatusViewOnly(DetailView): context["requires_feb_questions"] = self.object.is_feb() and flag_is_active_for_user( self.request.user, "organization_feature" ) - context["purpose_label"] = DomainRequest.FEBPurposeChoices.get_purpose_label(self.object.purpose) + context["purpose_label"] = DomainRequest.FEBPurposeChoices.get_purpose_label(self.object.feb_purpose_choice) return context From 8888131b38a96c5c3b0364ce336421daab5948f6 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 11:52:32 -0500 Subject: [PATCH 07/27] linter fixes --- src/registrar/admin.py | 2 +- src/registrar/models/domain_request.py | 5 +---- src/registrar/views/domain_request.py | 4 +++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index dcb92c145..61bb151d5 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -2754,7 +2754,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): def eop_stakeholder_email(self, obj): return obj.eop_stakeholder_email if obj.eop_stakeholder_email else "" - + # This is just a placeholder. This field will be populated in the detail_table_fieldset view. # This is not a field that exists on the model. def status_history(self, obj): diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py index f2560aae9..415c7f30b 100644 --- a/src/registrar/models/domain_request.py +++ b/src/registrar/models/domain_request.py @@ -60,13 +60,10 @@ class DomainRequest(TimeStampedModel): OTHER = "other", "Not for a website" @classmethod - def get_purpose_label(cls, purpose_name: str): + def get_purpose_label(cls, purpose_name: str | None): """Returns the associated label for a given purpose name""" - logger.debug(f"purpose_name: {purpose_name}") - logger.debug(f"label: {cls(purpose_name).label}") return cls(purpose_name).label if purpose_name else None - class StateTerritoryChoices(models.TextChoices): ALABAMA = "AL", "Alabama (AL)" ALASKA = "AK", "Alaska (AK)" diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 9b11dc104..784b1118c 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -966,7 +966,9 @@ class Review(DomainRequestWizard): context["Step"] = self.get_step_enum().__members__ context["domain_request"] = self.domain_request context["requires_feb_questions"] = self.requires_feb_questions() - context["purpose_label"] = DomainRequest.FEBPurposeChoices.get_purpose_label(self.domain_request.feb_purpose_choice) + context["purpose_label"] = DomainRequest.FEBPurposeChoices.get_purpose_label( + self.domain_request.feb_purpose_choice + ) return context def goto_next_step(self): From 607ec28765d760f01bb367e5d4892d63a7d202c5 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 12:22:41 -0500 Subject: [PATCH 08/27] small review fix --- .../includes/portfolio_request_review_steps.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html index 98f951d9c..43f214a4b 100644 --- a/src/registrar/templates/includes/portfolio_request_review_steps.html +++ b/src/registrar/templates/includes/portfolio_request_review_steps.html @@ -67,10 +67,10 @@ {% endif %} {% if step == Step.PURPOSE %} - {% with title=form_titles|get_item:step value=domain_request.purpose|default:"Incomplete"|safe %} - {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %} - {% endwith %} {% if requires_feb_questions %} + {% with title=form_titles|get_item:step %} + {% include "includes/summary_item.html" with title=title value=" " heading_level=heading_level editable=is_editable edit_link=domain_request_url %} + {% endwith %}

Purpose

{% if domain_request.feb_purpose_choice %}

{{purpose_label}}

@@ -94,6 +94,10 @@ {% else %}

No

{% endif %} + {% else %} + {% with title=form_titles|get_item:step value=domain_request.purpose|default:"Incomplete"|safe %} + {% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=is_editable edit_link=domain_request_url %} + {% endwith %} {% endif %} {% endif %} From ce69d129986ae70826569875a3ce51a7bf813c81 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 12:35:54 -0500 Subject: [PATCH 09/27] add fixture and remove hardcoded feb func --- src/registrar/fixtures/fixtures_users.py | 7 +++++++ src/registrar/views/domain_request.py | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/registrar/fixtures/fixtures_users.py b/src/registrar/fixtures/fixtures_users.py index fdaa1c135..a89d63cce 100644 --- a/src/registrar/fixtures/fixtures_users.py +++ b/src/registrar/fixtures/fixtures_users.py @@ -22,6 +22,13 @@ class UserFixture: """ ADMINS = [ + { + "username": "4aa78480-6272-42f9-ac29-a034ebdd9231", + "first_name": "Kaitlin", + "last_name": "Abbitt", + "email": "kaitlin.abbitt@cisa.dhs.gov", + "title": "Captain pirate", + }, { "username": "aad084c3-66cc-4632-80eb-41cdf5c5bcbf", "first_name": "Aditi", diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 784b1118c..4b5abf598 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -183,8 +183,7 @@ class DomainRequestWizard(TemplateView): return PortfolioDomainRequestStep if self.is_portfolio else Step def requires_feb_questions(self) -> bool: - # return self.domain_request.is_feb() and flag_is_active_for_user(self.request.user, "organization_feature") - return True + return self.domain_request.is_feb() and flag_is_active_for_user(self.request.user, "organization_feature") @property def prefix(self): From 926aefbd05789a72b1a87035f6d4363d728c7ec6 Mon Sep 17 00:00:00 2001 From: Matt-Spence Date: Wed, 26 Mar 2025 14:10:57 -0500 Subject: [PATCH 10/27] Update src/registrar/admin.py Co-authored-by: zandercymatics <141044360+zandercymatics@users.noreply.github.com> --- src/registrar/admin.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index df87cfee3..eaa0310fa 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -2741,26 +2741,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): portfolio_urbanization.short_description = "Urbanization" # type: ignore # ------ FEB fields ------ - def feb_naming_requirements_details(self, obj): - return obj.feb_naming_requirements_details if obj.feb_naming_requirements else "" - - def feb_purpose_choice(self, obj): - return obj.feb_purpose_choice if obj.feb_purpose_choice else "" - - def time_frame_details(self, obj): - return obj.time_frame_details if obj.has_timeframe else "" - - def interagency_initiative_details(self, obj): - return obj.interagency_initiative_details if obj.is_interagency_initiative else "" - - def eop_stakeholder_first_name(self, obj): - return obj.eop_stakeholder_first_name if obj.eop_stakeholder_first_name else "" - - def eop_stakeholder_last_name(self, obj): - return obj.eop_stakeholder_last_name if obj.eop_stakeholder_last_name else "" - - def eop_stakeholder_email(self, obj): - return obj.eop_stakeholder_email if obj.eop_stakeholder_email else "" # This is just a placeholder. This field will be populated in the detail_table_fieldset view. # This is not a field that exists on the model. From cb75ec84c36d385455282e1d27d6c25ee31dc7dc Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Wed, 26 Mar 2025 15:03:12 -0500 Subject: [PATCH 11/27] review fixes --- src/registrar/admin.py | 2 - src/registrar/forms/feb.py | 18 ---- ...nrequest_eop_stakeholder_email_and_more.py | 56 ++++++++++ src/registrar/models/domain_request.py | 6 -- .../templates/domain_request_purpose.html | 5 +- .../portfolio_request_review_steps.html | 1 - ...lio_domain_request_additional_details.html | 102 +++++++++--------- src/registrar/tests/test_admin_request.py | 1 - src/registrar/tests/test_views_request.py | 2 - src/registrar/utility/csv_export.py | 1 - src/registrar/views/domain_request.py | 5 + 11 files changed, 112 insertions(+), 87 deletions(-) create mode 100644 src/registrar/migrations/0145_remove_domainrequest_eop_stakeholder_email_and_more.py diff --git a/src/registrar/admin.py b/src/registrar/admin.py index eaa0310fa..4fb0dfb37 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -2845,7 +2845,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): "cisa_representative_email", "eop_stakeholder_first_name", "eop_stakeholder_last_name", - "eop_stakeholder_email", ] }, ), @@ -3079,7 +3078,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): "interagency_initiative_details", "eop_stakeholder_first_name", "eop_stakeholder_last_name", - "eop_stakeholder_email", ] ) modified_fieldsets = [] diff --git a/src/registrar/forms/feb.py b/src/registrar/forms/feb.py index fbb11a6ea..97b9b1ef4 100644 --- a/src/registrar/forms/feb.py +++ b/src/registrar/forms/feb.py @@ -153,29 +153,12 @@ class EOPContactForm(BaseDeletableRegistrarForm): error_messages={"required": "Enter the last name / family name of this contact."}, required=True, ) - email = forms.EmailField( - label="Email", - max_length=None, - error_messages={ - "required": ("Enter an email address in the required format, like name@example.com."), - "invalid": ("Enter an email address in the required format, like name@example.com."), - }, - validators=[ - MaxLengthValidator( - 320, - message="Response must be less than 320 characters.", - ) - ], - required=True, - help_text="Enter an email address in the required format, like name@example.com.", - ) @classmethod def from_database(cls, obj): return { "first_name": obj.eop_stakeholder_first_name, "last_name": obj.eop_stakeholder_last_name, - "email": obj.eop_stakeholder_email, } def to_database(self, obj): @@ -189,7 +172,6 @@ class EOPContactForm(BaseDeletableRegistrarForm): return obj.eop_stakeholder_first_name = self.cleaned_data["first_name"] obj.eop_stakeholder_last_name = self.cleaned_data["last_name"] - obj.eop_stakeholder_email = self.cleaned_data["email"] obj.save() diff --git a/src/registrar/migrations/0145_remove_domainrequest_eop_stakeholder_email_and_more.py b/src/registrar/migrations/0145_remove_domainrequest_eop_stakeholder_email_and_more.py new file mode 100644 index 000000000..303ff7698 --- /dev/null +++ b/src/registrar/migrations/0145_remove_domainrequest_eop_stakeholder_email_and_more.py @@ -0,0 +1,56 @@ +# Generated by Django 4.2.20 on 2025-03-26 19:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("registrar", "0144_domainrequest_eop_stakeholder_email_and_more"), + ] + + operations = [ + migrations.RemoveField( + model_name="domainrequest", + name="eop_stakeholder_email", + ), + migrations.AlterField( + model_name="domainrequest", + name="feb_naming_requirements", + field=models.BooleanField(blank=True, null=True, verbose_name="Meets Naming Requirements"), + ), + migrations.AlterField( + model_name="domainrequest", + name="feb_naming_requirements_details", + field=models.TextField( + blank=True, + help_text="Required if requested domain that doesn't meet naming requirements", + null=True, + verbose_name="Domain name rationale", + ), + ), + migrations.AlterField( + model_name="domainrequest", + name="feb_purpose_choice", + field=models.CharField( + blank=True, + choices=[ + ("new", "Used for a new website"), + ("redirect", "Used as a redirect for an existing website"), + ("other", "Not for a website"), + ], + null=True, + verbose_name="Purpose type", + ), + ), + migrations.AlterField( + model_name="domainrequest", + name="interagency_initiative_details", + field=models.TextField(blank=True, null=True, verbose_name="Interagency initiative"), + ), + migrations.AlterField( + model_name="domainrequest", + name="time_frame_details", + field=models.TextField(blank=True, null=True, verbose_name="Target time frame"), + ), + ] diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py index 415c7f30b..11cc53a7f 100644 --- a/src/registrar/models/domain_request.py +++ b/src/registrar/models/domain_request.py @@ -549,12 +549,6 @@ class DomainRequest(TimeStampedModel): verbose_name="EOP Stakeholder Last Name", ) - eop_stakeholder_email = models.EmailField( - null=True, - blank=True, - verbose_name="EOP Stakeholder Email", - ) - # This field is alternately used for generic domain purpose explanations # and for explanations of the specific purpose chosen with feb_purpose_choice purpose = models.TextField( diff --git a/src/registrar/templates/domain_request_purpose.html b/src/registrar/templates/domain_request_purpose.html index 9c6754f22..3893e51ec 100644 --- a/src/registrar/templates/domain_request_purpose.html +++ b/src/registrar/templates/domain_request_purpose.html @@ -34,7 +34,6 @@ {% with add_label_class="usa-sr-only" attr_required="required" attr_maxlength="2000" %} {% input_with_errors forms.1.purpose %} {% endwith %} -

Maximum 2000 characters allowed.

Do you have a target time frame for launching this domain?

@@ -52,7 +51,6 @@ {% with add_label_class="usa-sr-only" attr_required="required" attr_maxlength="2000" %} {% input_with_errors forms.3.time_frame_details %} {% endwith %} -

Maximum 2000 characters allowed.

Will the domain name be used for an interagency initiative?

@@ -65,12 +63,11 @@

- Provide details below. * + Name the agencies that will be involved in this initiative. *

{% with add_label_class="usa-sr-only" attr_required="required" attr_maxlength="2000" %} {% input_with_errors forms.5.interagency_initiative_details %} {% endwith %} -

Maximum 2000 characters allowed.

{% else %} diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html index 43f214a4b..0855931b3 100644 --- a/src/registrar/templates/includes/portfolio_request_review_steps.html +++ b/src/registrar/templates/includes/portfolio_request_review_steps.html @@ -111,7 +111,6 @@

Incomplete

{% elif domain_request.working_with_eop %}

{{domain_request.eop_stakeholder_first_name}} {{domain_request.eop_stakeholder_last_name}}

-

{{domain_request.eop_stakeholder_email}}

{% else %}

No

{% endif %} diff --git a/src/registrar/templates/portfolio_domain_request_additional_details.html b/src/registrar/templates/portfolio_domain_request_additional_details.html index 98b33bf7f..84bf9ec83 100644 --- a/src/registrar/templates/portfolio_domain_request_additional_details.html +++ b/src/registrar/templates/portfolio_domain_request_additional_details.html @@ -6,60 +6,58 @@ {% endblock %} {% block form_fields %} - {% if requires_feb_questions %} + {% if requires_feb_questions %} +
+ {{forms.0.management_form}} + {{forms.1.management_form}} {{forms.2.management_form}} {{forms.3.management_form}} - {{forms.4.management_form}} - {{forms.5.management_form}} -
-

Are you working with someone in the Executive Office of the President (EOP) on this request?

- -

- Select one. * -

- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} - {% input_with_errors forms.0.working_with_eop %} - {% endwith %} +

Are you working with someone in the Executive Office of the President (EOP) on this request?

+

+ Select one. * +

+ {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} + {% input_with_errors forms.0.working_with_eop %} + {% endwith %} - - -

Is there anything else you'd like us to know about your domain request?

-

- Select one. * -

- {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} - {% input_with_errors forms.2.has_anything_else_text %} - {% endwith %} - - -
- {% else %} -
-

Is there anything else you’d like us to know about your domain request?

- -
- -
-

This question is optional.

- {% with attr_maxlength=2000 add_label_class="usa-sr-only" %} - {% input_with_errors forms.3.anything_else %} - {% endwith %} + - {% endif %} + +

Is there anything else you'd like us to know about your domain request?

+

+ Select one. * +

+ {% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} + {% input_with_errors forms.2.has_anything_else_text %} + {% endwith %} + + +
+ {% else %} +
+

Is there anything else you’d like us to know about your domain request?

+ +
+ +
+

This question is optional.

+ {% with attr_maxlength=2000 add_label_class="usa-sr-only" %} + {% input_with_errors forms.3.anything_else %} + {% endwith %} +
+ {% endif %} {% endblock %} diff --git a/src/registrar/tests/test_admin_request.py b/src/registrar/tests/test_admin_request.py index e6ad2ef3e..3e4f88c05 100644 --- a/src/registrar/tests/test_admin_request.py +++ b/src/registrar/tests/test_admin_request.py @@ -2063,7 +2063,6 @@ class TestDomainRequestAdmin(MockEppLib): "working_with_eop", "eop_stakeholder_first_name", "eop_stakeholder_last_name", - "eop_stakeholder_email", "purpose", "has_timeframe", "time_frame_details", diff --git a/src/registrar/tests/test_views_request.py b/src/registrar/tests/test_views_request.py index 914bb210d..da021491d 100644 --- a/src/registrar/tests/test_views_request.py +++ b/src/registrar/tests/test_views_request.py @@ -2648,7 +2648,6 @@ class DomainRequestTests(TestWithUser, WebTest): additional_details_form["portfolio_additional_details-working_with_eop"] = "True" additional_details_form["portfolio_additional_details-first_name"] = "TesterFirstName" additional_details_form["portfolio_additional_details-last_name"] = "TesterLastName" - additional_details_form["portfolio_additional_details-email"] = "testy@town.com" additional_details_form["portfolio_additional_details-has_anything_else_text"] = "True" additional_details_form["portfolio_additional_details-anything_else"] = "test" self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) @@ -2761,7 +2760,6 @@ class DomainRequestTests(TestWithUser, WebTest): # EOP Stakeholder self.assertContains(review_page, "EOP Stakeholder") self.assertContains(review_page, "TesterFirstName TesterLastName") - self.assertContains(review_page, "testy@town.com") @less_console_noise_decorator def test_domain_request_formsets(self): diff --git a/src/registrar/utility/csv_export.py b/src/registrar/utility/csv_export.py index 6d6a7325d..610fc5c4f 100644 --- a/src/registrar/utility/csv_export.py +++ b/src/registrar/utility/csv_export.py @@ -1898,7 +1898,6 @@ class DomainRequestExport(BaseExport): "Target time frame": model.get("time_frame_details", None), "Interagency initiative": model.get("interagency_initiative_details", None), "EOP stakeholder name": eop_stakeholder_name, - "EOP stakeholder email": model.get("eop_stakeholder_email", None), } row = [FIELDS.get(column, "") for column in columns] diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 4b5abf598..2e7ece60b 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -625,6 +625,11 @@ class PortfolioAdditionalDetails(DomainRequestWizard): 2: FEBAnythingElseYesNoForm 3: PortfolioAnythingElseForm """ + if not self.requires_feb_questions(): + for i in range(3): + forms[i].mark_form_for_deletion() + # If FEB questions aren't required, validate only the anything else form + return forms[3].is_valid() eop_forms_valid = True if not forms[0].is_valid(): # If the user isn't working with EOP, don't validate the EOP contact form From 00289f50811895d915cde424e120e6b4a8be78f0 Mon Sep 17 00:00:00 2001 From: matthewswspence Date: Thu, 27 Mar 2025 12:19:01 -0500 Subject: [PATCH 12/27] admin page fixes --- src/registrar/admin.py | 65 +++++++++++++---------- src/registrar/tests/test_views_request.py | 1 - 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 4fb0dfb37..078e80770 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -3057,36 +3057,45 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportRegistrarModelAdmin): def get_fieldsets(self, request, obj=None): fieldsets = super().get_fieldsets(request, obj) + excluded_fields = set() + feb_fields = [ + "feb_naming_requirements_details", + "feb_purpose_choice", + "time_frame_details", + "interagency_initiative_details", + "eop_stakeholder_first_name", + "eop_stakeholder_last_name", + ] + + org_fields = [ + "portfolio", + "sub_organization", + "requested_suborganization", + "suborganization_city", + "suborganization_state_territory", + ] + + org_flag = flag_is_active_for_user(request.user, "organization_requests") + # Hide FEB fields for non-FEB requests + if not (obj and obj.portfolio and obj.is_feb()): + logger.debug(f"obj: {obj}") + logger.debug(f"obj.portfolio: {obj.portfolio}") + logger.debug(f"obj.is_feb(): {obj.is_feb()}") + logger.debug(f"feb breakdown: {obj.portfolio.federal_type}") + excluded_fields.update(feb_fields) + # Hide certain portfolio and suborg fields behind the organization requests flag # if it is not enabled - if not flag_is_active_for_user(request.user, "organization_requests"): - excluded_fields = [ - "portfolio", - "sub_organization", - "requested_suborganization", - "suborganization_city", - "suborganization_state_territory", - ] - # Hide FEB fields behind the organization requests flag - # and only show them if the portfolio is executive - if not (obj and obj.portfolio and obj.portfolio.federal_type == BranchChoices.EXECUTIVE): - excluded_fields.extend( - [ - "feb_naming_requirements_details", - "feb_purpose_choice", - "time_frame_details", - "interagency_initiative_details", - "eop_stakeholder_first_name", - "eop_stakeholder_last_name", - ] - ) - modified_fieldsets = [] - for name, data in fieldsets: - fields = data.get("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 + if not org_flag: + excluded_fields.update(org_fields) + excluded_fields.update(feb_fields) + + modified_fieldsets = [] + for name, data in fieldsets: + fields = data.get("fields", []) + fields = tuple(field for field in fields if field not in excluded_fields) + modified_fieldsets.append((name, {**data, "fields": fields})) + return modified_fieldsets # Trigger action when a fieldset is changed def save_model(self, request, obj, form, change): diff --git a/src/registrar/tests/test_views_request.py b/src/registrar/tests/test_views_request.py index da021491d..6ede713d6 100644 --- a/src/registrar/tests/test_views_request.py +++ b/src/registrar/tests/test_views_request.py @@ -2719,7 +2719,6 @@ class DomainRequestTests(TestWithUser, WebTest): self.assertContains(additional_details_page, "eop-contact-container") self.assertContains(additional_details_page, "additional_details-first_name") self.assertContains(additional_details_page, "additional_details-last_name") - self.assertContains(additional_details_page, "additional_details-email") # Make sure the additional details form is present self.assertContains(additional_details_page, "additional_details-has_anything_else_text") From 9743bc1cab7d312075363694ae7f544d6d015165 Mon Sep 17 00:00:00 2001 From: CocoByte Date: Thu, 27 Mar 2025 12:59:59 -0600 Subject: [PATCH 13/27] Additional Detail page design changes --- .../portfolio_domain_request_additional_details.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/registrar/templates/portfolio_domain_request_additional_details.html b/src/registrar/templates/portfolio_domain_request_additional_details.html index 84bf9ec83..4107e7bc1 100644 --- a/src/registrar/templates/portfolio_domain_request_additional_details.html +++ b/src/registrar/templates/portfolio_domain_request_additional_details.html @@ -6,6 +6,7 @@ {% endblock %} {% block form_fields %} + {% include "includes/required_fields.html" %} {% if requires_feb_questions %}
{{forms.0.management_form}} @@ -13,6 +14,7 @@ {{forms.2.management_form}} {{forms.3.management_form}}

Are you working with someone in the Executive Office of the President (EOP) on this request?

+

Working with the EOP is not required to request a .gov domain.

Select one. *

@@ -21,8 +23,8 @@ {% endwith %}
@@ -114,23 +120,21 @@

OMB will review each request against the domain - naming requirements for executive branch agencies - . - Agency submissions are expected to meet each requirement. + naming requirements for executive branch agencies. Agency submissions are expected to meet each requirement. +

+

+ Select one. *

{% with add_class="usa-radio__input--tile" add_legend_class="usa-sr-only" %} {% input_with_errors forms.2.feb_naming_requirements %} {% endwith %} {# Conditional Details Field – only shown when the executive naming requirements radio is "False" #} -