Use FSM instead

This commit is contained in:
zandercymatics 2024-02-26 10:50:38 -07:00
parent d416ea5138
commit 6542d03bc5
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
2 changed files with 48 additions and 13 deletions

View file

@ -49,6 +49,41 @@ function openInNewTab(el, removeAttribute = false){
}
createPhantomModalFormButtons();
document.addEventListener("DOMContentLoaded", function() {
const statusSelect = document.getElementById('id_status');
const investigatorSelect = document.getElementById('id_investigator'); // Adjust the ID based on your actual field name
function checkInvestigatorAndShowMessage() {
// Assuming the first option is the default "---------" or similar
const investigatorSelected = investigatorSelect.selectedIndex > 0;
// Remove existing messages to prevent duplicates
const existingMessage = document.querySelector('.no-investigator-exists');
if (existingMessage) {
existingMessage.remove();
}
const flexContainerParent = statusSelect.closest('.flex-container');
if (!investigatorSelected && flexContainerParent) {
const message = document.createElement("div");
message.classList.add("no-investigator-exists");
message.classList.add("padding-top-1")
message.classList.add("font-1")
message.textContent = '* An investigator must be added before other options will display.';
// Insert the message before the flex-container parent
flexContainerParent.insertAdjacentElement('afterend', message);
}
}
// Initial check in case the form is loaded with a selection already
checkInvestigatorAndShowMessage();
// Add event listener to re-check whenever the investigator selection changes
investigatorSelect.addEventListener('change', checkInvestigatorAndShowMessage);
});
})();
/** An IIFE for pages in DjangoAdmin which may need custom JS implementation.
* Currently only appends target="_blank" to the domain_form object,

View file

@ -619,6 +619,14 @@ class DomainApplication(TimeStampedModel):
except EmailSendingError:
logger.warning("Failed to send confirmation email", exc_info=True)
def investigator_exists_and_is_staff(self):
"""Checks if the current investigator is in a valid state for a state transition"""
is_valid = True
# Check if an investigator is assigned. No approval is possible without one.
if self.investigator is None or not self.investigator.is_staff:
is_valid = False
return is_valid
@transition(
field="status",
source=[
@ -669,7 +677,7 @@ class DomainApplication(TimeStampedModel):
ApplicationStatus.INELIGIBLE,
],
target=ApplicationStatus.IN_REVIEW,
conditions=[domain_is_not_active],
conditions=[domain_is_not_active, investigator_exists_and_is_staff],
)
def in_review(self):
"""Investigate an application that has been submitted.
@ -696,7 +704,7 @@ class DomainApplication(TimeStampedModel):
ApplicationStatus.INELIGIBLE,
],
target=ApplicationStatus.ACTION_NEEDED,
conditions=[domain_is_not_active],
conditions=[domain_is_not_active, investigator_exists_and_is_staff],
)
def action_needed(self):
"""Send back an application that is under investigation or rejected.
@ -723,6 +731,7 @@ class DomainApplication(TimeStampedModel):
ApplicationStatus.REJECTED,
],
target=ApplicationStatus.APPROVED,
conditions=[investigator_exists_and_is_staff]
)
def approve(self, send_email=True):
"""Approve an application that has been submitted.
@ -739,15 +748,6 @@ class DomainApplication(TimeStampedModel):
if Domain.objects.filter(name=self.requested_domain.name).exists():
raise ApplicationStatusError(code=FSMErrorCodes.APPROVE_DOMAIN_IN_USE)
# Check if an investigator is assigned. No approval is possible without one.
if self.investigator is None:
raise ApplicationStatusError(code=FSMErrorCodes.APPROVE_NO_INVESTIGATOR)
# Investigators must be staff users.
# This is handled elsewhere, but we should check here as a precaution.
if not self.investigator.is_staff:
raise ApplicationStatusError(code=FSMErrorCodes.APPROVE_INVESTIGATOR_NOT_STAFF)
# == Create the domain and related components == #
created_domain = Domain.objects.create(name=self.requested_domain.name)
self.approved_domain = created_domain
@ -788,7 +788,7 @@ class DomainApplication(TimeStampedModel):
field="status",
source=[ApplicationStatus.IN_REVIEW, ApplicationStatus.ACTION_NEEDED, ApplicationStatus.APPROVED],
target=ApplicationStatus.REJECTED,
conditions=[domain_is_not_active],
conditions=[domain_is_not_active, investigator_exists_and_is_staff],
)
def reject(self):
"""Reject an application that has been submitted.
@ -814,7 +814,7 @@ class DomainApplication(TimeStampedModel):
ApplicationStatus.REJECTED,
],
target=ApplicationStatus.INELIGIBLE,
conditions=[domain_is_not_active],
conditions=[domain_is_not_active, investigator_exists_and_is_staff],
)
def reject_with_prejudice(self):
"""The applicant is a bad actor, reject with prejudice.