mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-21 10:16:13 +02:00
Merge pull request #3008 from cisagov/za/2976-senior-official-federal-agency-changes
#2976: Senior Official and federal agency field changes for non federal agencies - [BACKUP]
This commit is contained in:
commit
edfc67649d
3 changed files with 87 additions and 9 deletions
|
@ -5,6 +5,7 @@ from django import forms
|
||||||
from django.db.models import Value, CharField, Q
|
from django.db.models import Value, CharField, Q
|
||||||
from django.db.models.functions import Concat, Coalesce
|
from django.db.models.functions import Concat, Coalesce
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from registrar.models.federal_agency import FederalAgency
|
||||||
from registrar.utility.admin_helpers import (
|
from registrar.utility.admin_helpers import (
|
||||||
get_action_needed_reason_default_email,
|
get_action_needed_reason_default_email,
|
||||||
get_rejection_reason_default_email,
|
get_rejection_reason_default_email,
|
||||||
|
@ -3243,6 +3244,14 @@ class PortfolioAdmin(ListHeaderAdmin):
|
||||||
# straightforward and the readonly_fields list can control their behavior
|
# straightforward and the readonly_fields list can control their behavior
|
||||||
readonly_fields.extend([field.name for field in self.model._meta.fields])
|
readonly_fields.extend([field.name for field in self.model._meta.fields])
|
||||||
|
|
||||||
|
# Make senior_official readonly for federal organizations
|
||||||
|
if obj and obj.organization_type == obj.OrganizationChoices.FEDERAL:
|
||||||
|
if "senior_official" not in readonly_fields:
|
||||||
|
readonly_fields.append("senior_official")
|
||||||
|
elif "senior_official" in readonly_fields:
|
||||||
|
# Remove senior_official from readonly_fields if org is non-federal
|
||||||
|
readonly_fields.remove("senior_official")
|
||||||
|
|
||||||
if request.user.has_perm("registrar.full_access_permission"):
|
if request.user.has_perm("registrar.full_access_permission"):
|
||||||
return readonly_fields
|
return readonly_fields
|
||||||
|
|
||||||
|
@ -3265,12 +3274,11 @@ class PortfolioAdmin(ListHeaderAdmin):
|
||||||
extra_context["domain_requests"] = obj.get_domain_requests(order_by=["requested_domain__name"])
|
extra_context["domain_requests"] = obj.get_domain_requests(order_by=["requested_domain__name"])
|
||||||
return super().change_view(request, object_id, form_url, extra_context)
|
return super().change_view(request, object_id, form_url, extra_context)
|
||||||
|
|
||||||
def save_model(self, request, obj, form, change):
|
def save_model(self, request, obj: Portfolio, form, change):
|
||||||
|
|
||||||
if hasattr(obj, "creator") is False:
|
if hasattr(obj, "creator") is False:
|
||||||
# ---- update creator ----
|
# ---- update creator ----
|
||||||
# Set the creator field to the current admin user
|
# Set the creator field to the current admin user
|
||||||
obj.creator = request.user if request.user.is_authenticated else None
|
obj.creator = request.user if request.user.is_authenticated else None # type: ignore
|
||||||
# ---- update organization name ----
|
# ---- update organization name ----
|
||||||
# org name will be the same as federal agency, if it is federal,
|
# org name will be the same as federal agency, if it is federal,
|
||||||
# otherwise it will be the actual org name. If nothing is entered for
|
# otherwise it will be the actual org name. If nothing is entered for
|
||||||
|
@ -3280,12 +3288,19 @@ class PortfolioAdmin(ListHeaderAdmin):
|
||||||
if is_federal and obj.organization_name is None:
|
if is_federal and obj.organization_name is None:
|
||||||
obj.organization_name = obj.federal_agency.agency
|
obj.organization_name = obj.federal_agency.agency
|
||||||
|
|
||||||
# Remove this line when senior_official is no longer readonly in /admin.
|
# Set the senior official field to the senior official on the federal agency
|
||||||
if obj.federal_agency:
|
# when federal - otherwise, clear the field.
|
||||||
if obj.federal_agency.so_federal_agency.exists():
|
if obj.organization_type == obj.OrganizationChoices.FEDERAL:
|
||||||
obj.senior_official = obj.federal_agency.so_federal_agency.first()
|
if obj.federal_agency:
|
||||||
else:
|
if obj.federal_agency.so_federal_agency.exists():
|
||||||
obj.senior_official = None
|
obj.senior_official = obj.federal_agency.so_federal_agency.first()
|
||||||
|
else:
|
||||||
|
obj.senior_official = None
|
||||||
|
else:
|
||||||
|
if obj.federal_agency and obj.federal_agency.agency != "Non-Federal Agency":
|
||||||
|
if obj.federal_agency.so_federal_agency.first() == obj.senior_official:
|
||||||
|
obj.senior_official = None
|
||||||
|
obj.federal_agency = FederalAgency.objects.filter(agency="Non-Federal Agency").first() # type: ignore
|
||||||
|
|
||||||
super().save_model(request, obj, form, change)
|
super().save_model(request, obj, form, change)
|
||||||
|
|
||||||
|
|
|
@ -966,6 +966,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
// This is the additional information that exists beneath the SO element.
|
// This is the additional information that exists beneath the SO element.
|
||||||
var contactList = document.querySelector(".field-senior_official .dja-address-contact-list");
|
var contactList = document.querySelector(".field-senior_official .dja-address-contact-list");
|
||||||
|
const federalAgencyContainer = document.querySelector(".field-federal_agency");
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
let isPortfolioPage = document.getElementById("portfolio_form");
|
let isPortfolioPage = document.getElementById("portfolio_form");
|
||||||
|
@ -1014,11 +1015,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
let selectedValue = organizationType.value;
|
let selectedValue = organizationType.value;
|
||||||
if (selectedValue === "federal") {
|
if (selectedValue === "federal") {
|
||||||
hideElement(organizationNameContainer);
|
hideElement(organizationNameContainer);
|
||||||
|
showElement(federalAgencyContainer);
|
||||||
if (federalType) {
|
if (federalType) {
|
||||||
showElement(federalType);
|
showElement(federalType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showElement(organizationNameContainer);
|
showElement(organizationNameContainer);
|
||||||
|
hideElement(federalAgencyContainer);
|
||||||
if (federalType) {
|
if (federalType) {
|
||||||
hideElement(federalType);
|
hideElement(federalType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2103,6 +2103,66 @@ class TestPortfolioAdmin(TestCase):
|
||||||
display_members = self.admin.display_members(self.portfolio)
|
display_members = self.admin.display_members(self.portfolio)
|
||||||
self.assertIn(f'<a href="{url}">2 members</a>', display_members)
|
self.assertIn(f'<a href="{url}">2 members</a>', display_members)
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
def test_senior_official_readonly_for_federal_org(self):
|
||||||
|
"""Test that senior_official field is readonly for federal organizations"""
|
||||||
|
request = self.factory.get("/")
|
||||||
|
request.user = self.superuser
|
||||||
|
|
||||||
|
# Create a federal portfolio
|
||||||
|
portfolio = Portfolio.objects.create(
|
||||||
|
organization_name="Test Federal Org",
|
||||||
|
organization_type=DomainRequest.OrganizationChoices.FEDERAL,
|
||||||
|
creator=self.superuser,
|
||||||
|
)
|
||||||
|
|
||||||
|
readonly_fields = self.admin.get_readonly_fields(request, portfolio)
|
||||||
|
self.assertIn("senior_official", readonly_fields)
|
||||||
|
|
||||||
|
# Change to non-federal org
|
||||||
|
portfolio.organization_type = DomainRequest.OrganizationChoices.CITY
|
||||||
|
readonly_fields = self.admin.get_readonly_fields(request, portfolio)
|
||||||
|
self.assertNotIn("senior_official", readonly_fields)
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
def test_senior_official_auto_assignment(self):
|
||||||
|
"""Test automatic senior official assignment based on organization type and federal agency"""
|
||||||
|
request = self.factory.get("/")
|
||||||
|
request.user = self.superuser
|
||||||
|
|
||||||
|
# Create a federal agency with a senior official
|
||||||
|
federal_agency = FederalAgency.objects.create(agency="Test Agency")
|
||||||
|
senior_official = SeniorOfficial.objects.create(
|
||||||
|
first_name="Test",
|
||||||
|
last_name="Official",
|
||||||
|
title="Some guy",
|
||||||
|
email="test@example.gov",
|
||||||
|
federal_agency=federal_agency,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a federal portfolio
|
||||||
|
portfolio = Portfolio.objects.create(
|
||||||
|
organization_name="Test Federal Org",
|
||||||
|
organization_type=DomainRequest.OrganizationChoices.FEDERAL,
|
||||||
|
creator=self.superuser,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test that the federal org gets senior official from agency when federal
|
||||||
|
portfolio.federal_agency = federal_agency
|
||||||
|
self.admin.save_model(request, portfolio, form=None, change=False)
|
||||||
|
self.assertEqual(portfolio.senior_official, senior_official)
|
||||||
|
|
||||||
|
# Test non-federal org clears senior official when not city
|
||||||
|
portfolio.organization_type = DomainRequest.OrganizationChoices.CITY
|
||||||
|
self.admin.save_model(request, portfolio, form=None, change=True)
|
||||||
|
self.assertIsNone(portfolio.senior_official)
|
||||||
|
self.assertEqual(portfolio.federal_agency.agency, "Non-Federal Agency")
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
senior_official.delete()
|
||||||
|
federal_agency.delete()
|
||||||
|
portfolio.delete()
|
||||||
|
|
||||||
|
|
||||||
class TestTransferUser(WebTest):
|
class TestTransferUser(WebTest):
|
||||||
"""User transfer custom admin page"""
|
"""User transfer custom admin page"""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue