diff --git a/backend/audit/migrations/0015_alter_singleauditchecklist_submission_status_and_more.py b/backend/audit/migrations/0015_alter_singleauditchecklist_submission_status_and_more.py new file mode 100644 index 000000000..0b473f184 --- /dev/null +++ b/backend/audit/migrations/0015_alter_singleauditchecklist_submission_status_and_more.py @@ -0,0 +1,125 @@ +# Generated by Django 5.1.2 on 2024-12-17 16:56 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("audit", "0014_alter_sacvalidationwaiver_waiver_types"), + ] + + operations = [ + migrations.AlterField( + model_name="singleauditchecklist", + name="submission_status", + field=models.CharField( + choices=[ + ("in_progress", "In Progress"), + ("flagged_for_removal", "Flagged for Removal"), + ("ready_for_certification", "Ready for Certification"), + ("auditor_certified", "Auditor Certified"), + ("auditee_certified", "Auditee Certified"), + ("certified", "Certified"), + ("submitted", "Submitted"), + ("disseminated", "Disseminated"), + ], + default="in_progress", + ), + ), + migrations.AlterField( + model_name="singleauditchecklist", + name="transition_name", + field=django.contrib.postgres.fields.ArrayField( + base_field=models.CharField( + choices=[ + ("in_progress", "In Progress"), + ("flagged_for_removal", "Flagged for Removal"), + ("ready_for_certification", "Ready for Certification"), + ("auditor_certified", "Auditor Certified"), + ("auditee_certified", "Auditee Certified"), + ("certified", "Certified"), + ("submitted", "Submitted"), + ("disseminated", "Disseminated"), + ], + max_length=40, + ), + blank=True, + default=list, + null=True, + size=None, + ), + ), + migrations.AlterField( + model_name="submissionevent", + name="event", + field=models.CharField( + choices=[ + ("access-granted", "Access granted"), + ("additional-eins-updated", "Additional EINs updated"), + ("additional-eins-deleted", "Additional EINs deleted"), + ("additional-ueis-updated", "Additional UEIs updated"), + ("additional-ueis-deleted", "Additional UEIs deleted"), + ("audit-information-updated", "Audit information updated"), + ("audit-report-pdf-updated", "Audit report PDF updated"), + ( + "auditee-certification-completed", + "Auditee certification completed", + ), + ( + "auditor-certification-completed", + "Auditor certification completed", + ), + ( + "corrective-action-plan-updated", + "Corrective action plan updated", + ), + ( + "corrective-action-plan-deleted", + "Corrective action plan deleted", + ), + ("created", "Created"), + ("federal-awards-updated", "Federal awards updated"), + ( + "federal-awards-audit-findings-updated", + "Federal awards audit findings updated", + ), + ( + "federal-awards-audit-findings-deleted", + "Federal awards audit findings deleted", + ), + ( + "federal-awards-audit-findings-text-updated", + "Federal awards audit findings text updated", + ), + ( + "federal-awards-audit-findings-text-deleted", + "Federal awards audit findings text deleted", + ), + ( + "findings-uniform-guidance-updated", + "Findings uniform guidance updated", + ), + ( + "findings-uniform-guidance-deleted", + "Findings uniform guidance deleted", + ), + ("general-information-updated", "General information updated"), + ("locked-for-certification", "Locked for certification"), + ("unlocked-after-certification", "Unlocked after certification"), + ("notes-to-sefa-updated", "Notes to SEFA updated"), + ("secondary-auditors-updated", "Secondary auditors updated"), + ("secondary-auditors-deleted", "Secondary auditors deleted"), + ("submitted", "Submitted to the FAC for processing"), + ("disseminated", "Copied to dissemination tables"), + ("tribal-consent-updated", "Tribal audit consent updated"), + ( + "flagged-submission-for-removal", + "Flagged submission for removal", + ), + ("cancel-removal-flag", "Cancel removal flag"), + ] + ), + ), + ] diff --git a/backend/audit/models/models.py b/backend/audit/models/models.py index e35b1d06e..252d1a3f2 100644 --- a/backend/audit/models/models.py +++ b/backend/audit/models/models.py @@ -171,6 +171,7 @@ class STATUS: CERTIFIED = "certified" SUBMITTED = "submitted" DISSEMINATED = "disseminated" + FLAGGED_FOR_REMOVAL = "flagged_for_removal" class SingleAuditChecklist(models.Model, GeneralInformationMixin): # type: ignore @@ -303,6 +304,7 @@ def get_statuses(self) -> type[STATUS]: # Constants: STATUS_CHOICES = ( (STATUS.IN_PROGRESS, "In Progress"), + (STATUS.FLAGGED_FOR_REMOVAL, "Flagged for Removal"), (STATUS.READY_FOR_CERTIFICATION, "Ready for Certification"), (STATUS.AUDITOR_CERTIFIED, "Auditor Certified"), (STATUS.AUDITEE_CERTIFIED, "Auditee Certified"), diff --git a/backend/audit/models/submission_event.py b/backend/audit/models/submission_event.py index d4d675bb0..7db884718 100644 --- a/backend/audit/models/submission_event.py +++ b/backend/audit/models/submission_event.py @@ -42,6 +42,8 @@ class EventType: SUBMITTED = "submitted" DISSEMINATED = "disseminated" TRIBAL_CONSENT_UPDATED = "tribal-consent-updated" + FLAGGED_SUBMISSION_FOR_REMOVAL = "flagged-submission-for-removal" + CANCEL_REMOVAL_FLAG = "cancel-removal-flag" EVENT_TYPES = ( (EventType.ACCESS_GRANTED, _("Access granted")), @@ -96,6 +98,11 @@ class EventType: (EventType.SUBMITTED, _("Submitted to the FAC for processing")), (EventType.DISSEMINATED, _("Copied to dissemination tables")), (EventType.TRIBAL_CONSENT_UPDATED, _("Tribal audit consent updated")), + ( + EventType.FLAGGED_SUBMISSION_FOR_REMOVAL, + _("Flagged submission for removal"), + ), + (EventType.CANCEL_REMOVAL_FLAG, _("Cancel removal flag")), ) sac = models.ForeignKey("audit.SingleAuditChecklist", on_delete=models.CASCADE) diff --git a/backend/audit/models/viewflow.py b/backend/audit/models/viewflow.py index 35e460f0a..1d12515b3 100644 --- a/backend/audit/models/viewflow.py +++ b/backend/audit/models/viewflow.py @@ -29,6 +29,41 @@ def sac_revert_from_submitted(sac): return False +def sac_revert_from_flagged_for_removal(sac, user): + """ + Transitions the submission_state for a SingleAuditChecklist back + to "in_progress" so the user can continue working on it. + This should be accessible to django admin. + """ + if sac.submission_status == STATUS.FLAGGED_FOR_REMOVAL: + flow = SingleAuditChecklistFlow(sac) + + flow.transition_to_in_progress_again() + + with CurationTracking(): + sac.save( + event_user=user, + event_type=SubmissionEvent.EventType.CANCEL_REMOVAL_FLAG, + ) + + +def sac_flag_for_removal(sac, user): + """ + Transitions the submission_state for a SingleAuditChecklist to "flagged_for_removal". + This should be accessible to django admin. + """ + if sac.submission_status == STATUS.IN_PROGRESS: + flow = SingleAuditChecklistFlow(sac) + + flow.transition_to_flagged_for_removal() + + with CurationTracking(): + sac.save( + event_user=user, + event_type=SubmissionEvent.EventType.FLAGGED_SUBMISSION_FOR_REMOVAL, + ) + + def sac_transition(request, sac, **kwargs): """ Transitions the submission_state for a SingleAuditChecklist (sac). @@ -54,6 +89,14 @@ def sac_transition(request, sac, **kwargs): ) return True + elif target == STATUS.FLAGGED_FOR_REMOVAL: + flow.transition_to_flagged_for_removal() + sac.save( + event_user=user, + event_type=SubmissionEvent.EventType.FLAGGED_SUBMISSION_FOR_REMOVAL, + ) + return True + elif target == STATUS.READY_FOR_CERTIFICATION: flow.transition_to_ready_for_certification() sac.save( @@ -127,11 +170,24 @@ def transition_to_ready_for_certification(self): self.sac.transition_name.append(STATUS.READY_FOR_CERTIFICATION) self.sac.transition_date.append(datetime.datetime.now(datetime.timezone.utc)) + @state.transition( + source=STATUS.IN_PROGRESS, + target=STATUS.FLAGGED_FOR_REMOVAL, + ) + def transition_to_flagged_for_removal(self): + """ + The permission checks verifying that the user attempting to do this has + the appropriate privileges will be done at the view level. + """ + self.sac.transition_name.append(STATUS.FLAGGED_FOR_REMOVAL) + self.sac.transition_date.append(datetime.datetime.now(datetime.timezone.utc)) + @state.transition( source=[ STATUS.READY_FOR_CERTIFICATION, STATUS.AUDITOR_CERTIFIED, STATUS.AUDITEE_CERTIFIED, + STATUS.FLAGGED_FOR_REMOVAL, ], target=STATUS.IN_PROGRESS, ) diff --git a/backend/audit/templates/audit/my_submissions.html b/backend/audit/templates/audit/my_submissions.html index b570b99fd..1ba43e74d 100644 --- a/backend/audit/templates/audit/my_submissions.html +++ b/backend/audit/templates/audit/my_submissions.html @@ -27,6 +27,8 @@
Are you sure you want to remove the following report?
+ +