From cf7bf4d30491d5894a0220dda5ea0cf94d709285 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:14:36 -0700 Subject: [PATCH] Add form level errors --- src/registrar/admin.py | 27 ++++++++++++++++++++++++++- src/registrar/utility/errors.py | 4 ++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index f58a481df..9c3b8075e 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -16,7 +16,7 @@ from dateutil.relativedelta import relativedelta # type: ignore from epplibwrapper.errors import ErrorCode, RegistryError from registrar.models import Contact, Domain, DomainApplication, DraftDomain, User, Website from registrar.utility import csv_export -from registrar.utility.errors import ApplicationStatusError +from registrar.utility.errors import ApplicationStatusError, FSMErrorCodes from registrar.views.utility.mixins import OrderableFieldsMixin from django.contrib.admin.views.main import ORDER_VAR from . import models @@ -808,6 +808,31 @@ class DomainApplicationAdminForm(forms.ModelForm): if not application.creator.is_restricted(): self.fields["status"].widget.choices = available_transitions + def clean(self): + # clean is called from clean_forms, which is called from is_valid + # after clean_fields. it is used to determine form level errors. + # is_valid is typically called from view during a post + cleaned_data = super().clean() + investigator = cleaned_data.get("investigator") + status = cleaned_data.get("status") + requested_domain = cleaned_data.get("requested_domain") + + # Check if an investigator is assigned. No approval is possible without one. + # TODO - add form level error + # TODO - maybe add modal if approver is not investigator as superuser + if investigator is None: + error_message = ApplicationStatusError.get_error_message(FSMErrorCodes.APPROVE_NO_INVESTIGATOR) + self.add_error("investigator", error_message) + else: + # Investigators must be staff users. + # This is handled elsewhere, but we should check here as a precaution. + if not investigator.is_staff: + error_message = ApplicationStatusError.get_error_message(FSMErrorCodes.APPROVE_INVESTIGATOR_NOT_STAFF) + self.add_error("investigator", error_message) + #if status == DomainApplication.ApplicationStatus.APPROVED and investigator != request.user: + #raise ValidationError("Only the assigned investigator can approve this application.") + + return cleaned_data class DomainApplicationAdmin(ListHeaderAdmin): """Custom domain applications admin class.""" diff --git a/src/registrar/utility/errors.py b/src/registrar/utility/errors.py index 1d82ea49a..8d77ecd2e 100644 --- a/src/registrar/utility/errors.py +++ b/src/registrar/utility/errors.py @@ -114,8 +114,8 @@ class ApplicationStatusError(Exception): return f"{self.message}" @classmethod - def get_error_message(self, code=None): - return self._error_mapping.get(code) + def get_error_message(cls, code=None): + return cls._error_mapping.get(code) class NameserverErrorCodes(IntEnum):