Merge pull request #1012 from cisagov/dk/853-domain-app-admin-states

Dk/853 domain app admin states
This commit is contained in:
dave-kennedy-ecs 2023-09-13 10:34:07 -04:00 committed by GitHub
commit 4daec217d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 0 deletions

View file

@ -1,4 +1,6 @@
import logging import logging
from django import forms
from django_fsm import get_available_FIELD_transitions
from django.contrib import admin, messages from django.contrib import admin, messages
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -379,6 +381,37 @@ class DomainInformationAdmin(ListHeaderAdmin):
search_help_text = "Search by domain." search_help_text = "Search by domain."
class DomainApplicationAdminForm(forms.ModelForm):
"""Custom form to limit transitions to available transitions"""
class Meta:
model = models.DomainApplication
fields = "__all__"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
application = kwargs.get("instance")
if application and application.pk:
current_state = application.status
# first option in status transitions is current state
available_transitions = [(current_state, current_state)]
transitions = get_available_FIELD_transitions(
application, models.DomainApplication._meta.get_field("status")
)
for transition in transitions:
available_transitions.append((transition.target, transition.target))
# only set the available transitions if the user is not restricted
# from editing the domain application; otherwise, the form will be
# readonly and the status field will not have a widget
if not application.creator.is_restricted():
self.fields["status"].widget.choices = available_transitions
class DomainApplicationAdmin(ListHeaderAdmin): class DomainApplicationAdmin(ListHeaderAdmin):
"""Custom domain applications admin class.""" """Custom domain applications admin class."""
@ -410,6 +443,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
search_help_text = "Search by domain or submitter." search_help_text = "Search by domain or submitter."
# Detail view # Detail view
form = DomainApplicationAdminForm
fieldsets = [ fieldsets = [
(None, {"fields": ["status", "investigator", "creator"]}), (None, {"fields": ["status", "investigator", "creator"]}),
( (

View file

@ -5,6 +5,7 @@ from django.urls import reverse
from registrar.admin import ( from registrar.admin import (
DomainAdmin, DomainAdmin,
DomainApplicationAdmin, DomainApplicationAdmin,
DomainApplicationAdminForm,
ListHeaderAdmin, ListHeaderAdmin,
MyUserAdmin, MyUserAdmin,
AuditedAdmin, AuditedAdmin,
@ -92,6 +93,48 @@ class TestDomainAdmin(TestCase):
User.objects.all().delete() User.objects.all().delete()
class TestDomainApplicationAdminForm(TestCase):
def setUp(self):
# Create a test application with an initial state of started
self.application = completed_application()
def test_form_choices(self):
# Create a form instance with the test application
form = DomainApplicationAdminForm(instance=self.application)
# Verify that the form choices match the available transitions for started
expected_choices = [("started", "started"), ("submitted", "submitted")]
self.assertEqual(form.fields["status"].widget.choices, expected_choices)
def test_form_choices_when_no_instance(self):
# Create a form instance without an instance
form = DomainApplicationAdminForm()
# Verify that the form choices show all choices when no instance is provided;
# this is necessary to show all choices when creating a new domain
# application in django admin;
# note that FSM ensures that no domain application exists with invalid status,
# so don't need to test for invalid status
self.assertEqual(
form.fields["status"].widget.choices,
DomainApplication._meta.get_field("status").choices,
)
def test_form_choices_when_ineligible(self):
# Create a form instance with a domain application with ineligible status
ineligible_application = DomainApplication(status="ineligible")
# Attempt to create a form with the ineligible application
# The form should not raise an error, but choices should be the
# full list of possible choices
form = DomainApplicationAdminForm(instance=ineligible_application)
self.assertEqual(
form.fields["status"].widget.choices,
DomainApplication._meta.get_field("status").choices,
)
class TestDomainApplicationAdmin(TestCase): class TestDomainApplicationAdmin(TestCase):
def setUp(self): def setUp(self):
self.site = AdminSite() self.site = AdminSite()