diff --git a/src/registrar/admin.py b/src/registrar/admin.py index e46bc89fc..e93db9893 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -238,15 +238,11 @@ class DomainRequestAdminForm(forms.ModelForm): "current_websites": NoAutocompleteFilteredSelectMultiple("current_websites", False), "alternative_domains": NoAutocompleteFilteredSelectMultiple("alternative_domains", False), "other_contacts": NoAutocompleteFilteredSelectMultiple("other_contacts", False), - 'portfolio': AutocompleteSelectWithPlaceholder( - DomainRequest._meta.get_field('portfolio'), - admin.site, - attrs={'data-placeholder': '---------'} + "portfolio": AutocompleteSelectWithPlaceholder( + DomainRequest._meta.get_field("portfolio"), admin.site, attrs={"data-placeholder": "---------"} ), - 'sub_organization': AutocompleteSelectWithPlaceholder( - DomainRequest._meta.get_field('sub_organization'), - admin.site, - attrs={'data-placeholder': '---------'} + "sub_organization": AutocompleteSelectWithPlaceholder( + DomainRequest._meta.get_field("sub_organization"), admin.site, attrs={"data-placeholder": "---------"} ), } labels = { @@ -1740,40 +1736,68 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): custom_election_board.admin_order_field = "is_election_board" # type: ignore custom_election_board.short_description = "Election office" # type: ignore - # Define methods to display fields from the related portfolio def portfolio_senior_official(self, obj) -> Optional[SeniorOfficial]: return obj.portfolio.senior_official if obj.portfolio and obj.portfolio.senior_official else None + portfolio_senior_official.short_description = "Senior official" + def portfolio_organization_type(self, obj): - return DomainRequest.OrganizationChoices.get_org_label(obj.portfolio.organization_type) if obj.portfolio and obj.portfolio.organization_type else "-" + return ( + DomainRequest.OrganizationChoices.get_org_label(obj.portfolio.organization_type) + if obj.portfolio and obj.portfolio.organization_type + else "-" + ) + portfolio_organization_type.short_description = "Organization type" + def portfolio_federal_type(self, obj): - return BranchChoices.get_branch_label(obj.portfolio.federal_type) if obj.portfolio and obj.portfolio.federal_type else "-" + return ( + BranchChoices.get_branch_label(obj.portfolio.federal_type) + if obj.portfolio and obj.portfolio.federal_type + else "-" + ) + portfolio_federal_type.short_description = "Federal type" + def portfolio_organization_name(self, obj): return obj.portfolio.organization_name if obj.portfolio else "" + portfolio_organization_name.short_description = "Organization name" + def portfolio_federal_agency(self, obj): return obj.portfolio.federal_agency if obj.portfolio else "" + portfolio_federal_agency.short_description = "Federal agency" + def portfolio_state_territory(self, obj): return obj.portfolio.state_territory if obj.portfolio else "" + portfolio_state_territory.short_description = "State, territory, or military post" + def portfolio_address_line1(self, obj): return obj.portfolio.address_line1 if obj.portfolio else "" + portfolio_address_line1.short_description = "Address line 1" + def portfolio_address_line2(self, obj): return obj.portfolio.address_line2 if obj.portfolio else "" + portfolio_address_line2.short_description = "Address line 2" + def portfolio_city(self, obj): return obj.portfolio.city if obj.portfolio else "" + portfolio_city.short_description = "City" + def portfolio_zipcode(self, obj): return obj.portfolio.zipcode if obj.portfolio else "" + portfolio_zipcode.short_description = "Zip code" + def portfolio_urbanization(self, obj): return obj.portfolio.urbanization if obj.portfolio else "" + portfolio_urbanization.short_description = "Urbanization" # This is just a placeholder. This field will be populated in the detail_table_fieldset view. @@ -1830,7 +1854,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): "suborganization_state_territory", "creator", ] - } + }, ), (".gov domain", {"fields": ["requested_domain", "alternative_domains"]}), ( @@ -1903,7 +1927,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): "portfolio_organization_type", "portfolio_federal_type", ] - } + }, ), ( "Organization name and mailing address", diff --git a/src/registrar/tests/test_admin_request.py b/src/registrar/tests/test_admin_request.py index 57d7d9ac6..670d36363 100644 --- a/src/registrar/tests/test_admin_request.py +++ b/src/registrar/tests/test_admin_request.py @@ -1526,7 +1526,7 @@ class TestDomainRequestAdmin(MockEppLib): self.test_helper.assert_response_contains_distinct_values(response, expected_other_employees_fields) # Test for the copy link - self.assertContains(response, "copy-to-clipboard", count=4) + self.assertContains(response, "copy-to-clipboard", count=5) # Test that Creator counts display properly self.assertNotContains(response, "Approved domains") @@ -1626,6 +1626,17 @@ class TestDomainRequestAdmin(MockEppLib): readonly_fields = self.admin.get_readonly_fields(request, domain_request) expected_fields = [ + "portfolio_senior_official", + "portfolio_organization_type", + "portfolio_federal_type", + "portfolio_organization_name", + "portfolio_federal_agency", + "portfolio_state_territory", + "portfolio_address_line1", + "portfolio_address_line2", + "portfolio_city", + "portfolio_zipcode", + "portfolio_urbanization", "other_contacts", "current_websites", "alternative_domains", @@ -1691,6 +1702,17 @@ class TestDomainRequestAdmin(MockEppLib): readonly_fields = self.admin.get_readonly_fields(request) self.maxDiff = None expected_fields = [ + "portfolio_senior_official", + "portfolio_organization_type", + "portfolio_federal_type", + "portfolio_organization_name", + "portfolio_federal_agency", + "portfolio_state_territory", + "portfolio_address_line1", + "portfolio_address_line2", + "portfolio_city", + "portfolio_zipcode", + "portfolio_urbanization", "other_contacts", "current_websites", "alternative_domains", @@ -1723,6 +1745,17 @@ class TestDomainRequestAdmin(MockEppLib): readonly_fields = self.admin.get_readonly_fields(request) expected_fields = [ + "portfolio_senior_official", + "portfolio_organization_type", + "portfolio_federal_type", + "portfolio_organization_name", + "portfolio_federal_agency", + "portfolio_state_territory", + "portfolio_address_line1", + "portfolio_address_line2", + "portfolio_city", + "portfolio_zipcode", + "portfolio_urbanization", "other_contacts", "current_websites", "alternative_domains", diff --git a/src/registrar/utility/admin_helpers.py b/src/registrar/utility/admin_helpers.py index 6780ff011..2852cbadc 100644 --- a/src/registrar/utility/admin_helpers.py +++ b/src/registrar/utility/admin_helpers.py @@ -95,12 +95,14 @@ def get_field_links_as_list( else: links = "".join(links) return format_html(f'') if links else msg_for_none - + + class AutocompleteSelectWithPlaceholder(AutocompleteSelect): """Override of the default autoselect element. This is because by default, the autocomplete element clears data-placeholder""" + def build_attrs(self, base_attrs, extra_attrs=None): attrs = super().build_attrs(base_attrs, extra_attrs=extra_attrs) - if 'data-placeholder' in base_attrs: - attrs['data-placeholder'] = base_attrs['data-placeholder'] - return attrs \ No newline at end of file + if "data-placeholder" in base_attrs: + attrs["data-placeholder"] = base_attrs["data-placeholder"] + return attrs diff --git a/src/registrar/views/utility/api_views.py b/src/registrar/views/utility/api_views.py index aa8bfb30c..aedfa757a 100644 --- a/src/registrar/views/utility/api_views.py +++ b/src/registrar/views/utility/api_views.py @@ -6,7 +6,6 @@ from django.contrib.admin.views.decorators import staff_member_required from django.contrib.auth.decorators import login_required from registrar.utility.admin_helpers import get_action_needed_reason_default_email, get_rejection_reason_default_email from registrar.models.portfolio import Portfolio -from registrar.models.domain_request import DomainRequest from registrar.utility.constants import BranchChoices logger = logging.getLogger(__name__) @@ -63,16 +62,21 @@ def get_portfolio_json(request): portfolio_dict["id"] = portfolio.id # map portfolio federal type - portfolio_dict["federal_type"] = BranchChoices.get_branch_label(portfolio.federal_type) if portfolio.federal_type else "-" + portfolio_dict["federal_type"] = ( + BranchChoices.get_branch_label(portfolio.federal_type) if portfolio.federal_type else "-" + ) # map portfolio organization type - portfolio_dict["organization_type"] = DomainRequest.OrganizationChoices.get_org_label(portfolio.organization_type) if portfolio.organization_type else "-" - + portfolio_dict["organization_type"] = ( + DomainRequest.OrganizationChoices.get_org_label(portfolio.organization_type) + if portfolio.organization_type + else "-" + ) + # Add senior official information if it exists if portfolio.senior_official: senior_official = model_to_dict( - portfolio.senior_official, - fields=["id", "first_name", "last_name", "title", "phone", "email"] + portfolio.senior_official, fields=["id", "first_name", "last_name", "title", "phone", "email"] ) # The phone number field isn't json serializable, so we # convert this to a string first if it exists. @@ -84,13 +88,10 @@ def get_portfolio_json(request): # Add federal agency information if it exists if portfolio.federal_agency: - federal_agency = model_to_dict( - portfolio.federal_agency, - fields=["agency", "id"] - ) + federal_agency = model_to_dict(portfolio.federal_agency, fields=["agency", "id"]) portfolio_dict["federal_agency"] = federal_agency else: - portfolio_dict["federal_agency"] = '-' + portfolio_dict["federal_agency"] = "-" return JsonResponse(portfolio_dict) @@ -115,7 +116,7 @@ def get_suborganization_list_json(request): # Add suborganizations related to this portfolio suborganizations = portfolio.portfolio_suborganizations.all().values("id", "name") results = [{"id": sub["id"], "text": sub["name"]} for sub in suborganizations] - return JsonResponse({"results": results, "pagination": { "more": False }}) + return JsonResponse({"results": results, "pagination": {"more": False}}) @login_required