-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New management command - Manually move "submitted" report to dissemin…
…ation (#4351) * Create move_to_disseminated.py New management command file for attempting to move a SAC to dissemination. This is the first commit on this feature. Command is: `python manage.py move_to_disseminated --report_id ID_GOES_HERE`. This will look for a SAC with the `report_id` that you entered, and attempt to move it to the `disseminated` status - ONLY if it is stuck as `submitted`. * Linting * Comments for potential enhancements to management command * Enhance management command - Replaced logs with print statements to avoid bloating NR. - Now checking for validation errors (similar to cross-validation step) before proceeding to attempt dissemination. - New viewflow routine for transitioning a SAC from `submitted` to `auditee_certified`. This is only ran in the event there are errors with validation OR dissemination. * Fix test - submission_status_transitions * Linting * Curation library and dissemination fixes - Updated some error codes and logging more responses in `move_to_disseminated`. - Brought in a new application for enabling/disabling audit tracking from `jadudm/curation-api`, which creates a table `curation.record_version` as well as functions to manipulate it, for tracking the changelog of SACs. - Now tracking the changelog of the SAC when running `move_to_dissemination`. - Added a condition in `remove_workbook_artifacts.py` when logging after bulk deletion of S3 files to ensure the key is not null. - Added a new routine in `IntakeToDissemination` which takes a status and finds the first occurring date of that status for a SAC. `fac_acceptance_date` moving forward will now be based off of the first time a SAC was `submitted`, rather than the most recent time a SAC was `submitted`. * Feedback from jadud - New class `CurationTracking`, which allows us to wrap the audit trailing using a `with`. See the changelog below for reference. - Tracking `sac_reverted_from_submitted` in our curation table. - Now using `else` in dissemination validation check. - Calling `--disable` on `curation_audit_tracking` on startup of the application. * Update curation_audit_tracking_init.sh * Attempted fix - disable audit tracking on startup fails * Move curation after migrations * Update init_curation_auditing.sql
- Loading branch information
Showing
20 changed files
with
528 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
backend/audit/management/commands/move_to_disseminated.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
""" | ||
Allows the manual transition of an audit to dissemination. | ||
""" | ||
|
||
from audit.models import ( | ||
SingleAuditChecklist, | ||
) | ||
from audit.models.models import STATUS | ||
from audit.models.viewflow import sac_revert_from_submitted, sac_transition | ||
from curation.curationlib.curation_audit_tracking import CurationTracking | ||
from dissemination.remove_workbook_artifacts import remove_workbook_artifacts | ||
from django.core.management.base import BaseCommand | ||
from django.db import transaction | ||
import logging | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Command(BaseCommand): | ||
""" | ||
Django management command for disseminating an audit. | ||
""" | ||
|
||
def add_arguments(self, parser): | ||
parser.add_argument( | ||
"--report_id", | ||
type=str, | ||
help="The ID of the SAC.", | ||
default=None, | ||
) | ||
|
||
def handle(self, *args, **options): | ||
report_id = options.get("report_id") | ||
|
||
# no parameter passed. | ||
if report_id is None: | ||
logger.info( | ||
"No report_id supplied. (move_to_disseminated --report_id ID_OF_REPORT)" | ||
) | ||
exit(-1) | ||
|
||
try: | ||
sac = SingleAuditChecklist.objects.get(report_id=report_id) | ||
except SingleAuditChecklist.DoesNotExist: | ||
logger.info(f"No report with report_id found: {report_id}") | ||
exit(-1) | ||
|
||
# must be stuck as 'submitted'. | ||
if sac.submission_status != STATUS.SUBMITTED: | ||
logger.info( | ||
f"Unable to disseminate report that is not in submitted state: {report_id}" | ||
) | ||
exit(-1) | ||
|
||
# check for validation errors. | ||
errors = sac.validate_full() | ||
if errors: | ||
logger.info( | ||
f"Unable to disseminate report with validation errors: {report_id}." | ||
) | ||
logger.info(errors["errors"]) | ||
|
||
# return to auditee_certified. | ||
sac_revert_from_submitted(sac) | ||
logger.info(f"Returned report to auditee_certified state: {report_id}") | ||
exit(0) | ||
|
||
with CurationTracking(): | ||
# BEGIN ATOMIC BLOCK | ||
with transaction.atomic(): | ||
disseminated = sac.disseminate() | ||
# `disseminated` is None if there were no errors. | ||
if disseminated is None: | ||
sac_transition(None, sac, transition_to=STATUS.DISSEMINATED) | ||
# END ATOMIC BLOCK | ||
|
||
# IF THE DISSEMINATION SUCCEEDED | ||
# `disseminated` is None if there were no errors. | ||
if disseminated is None: | ||
# Remove workbook artifacts after the report has been disseminated. | ||
# We do this outside of the atomic block. No race between | ||
# two instances of the FAC should be able to get to this point. | ||
# If we do, something will fail. | ||
remove_workbook_artifacts(sac) | ||
|
||
# IF THE DISSEMINATION FAILED | ||
# If disseminated has a value, it is an error | ||
# object returned from `sac.disseminate()` | ||
else: | ||
logger.info( | ||
"{} is a `not None` value report_id[{}] for `disseminated`".format( | ||
disseminated, report_id | ||
) | ||
) | ||
|
||
# return to auditee_certified. | ||
sac_revert_from_submitted(sac) | ||
exit(0) | ||
|
||
logger.info(f"DISSEMINATED REPORT: {report_id}") | ||
exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -130,6 +130,7 @@ | |
"dissemination", | ||
"census_historical_migration", | ||
"support", | ||
"curation", | ||
] | ||
|
||
MIDDLEWARE = [ | ||
|
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class CurationConfig(AppConfig): | ||
default_auto_field = "django.db.models.BigAutoField" | ||
name = "curation" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from dissemination import api_versions | ||
|
||
SQL_PATH = "curation/sql" | ||
|
||
|
||
class CurationTracking: | ||
""" | ||
Wraps "audit-tracking" around any block of logic. | ||
This guarantees that any DB writes within the block will be recorded. | ||
""" | ||
|
||
def __enter__(self): | ||
enable_audit_curation() | ||
return None | ||
|
||
def __exit__(self, exc_type, exc_value, tb): | ||
disable_audit_curation() | ||
|
||
|
||
def init_audit_curation(): | ||
api_versions.exec_sql_at_path(SQL_PATH, "init_curation_auditing.sql") | ||
|
||
|
||
def enable_audit_curation(): | ||
api_versions.exec_sql_at_path(SQL_PATH, "enable_curation_auditing.sql") | ||
|
||
|
||
def disable_audit_curation(): | ||
api_versions.exec_sql_at_path(SQL_PATH, "disable_curation_auditing.sql") |
28 changes: 28 additions & 0 deletions
28
backend/curation/management/commands/curation_audit_tracking.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from django.core.management.base import BaseCommand | ||
|
||
# These are pulled from a library so they can be used | ||
# elsewhere in the code. | ||
from curation.curationlib.curation_audit_tracking import ( | ||
init_audit_curation, | ||
enable_audit_curation, | ||
disable_audit_curation, | ||
) | ||
|
||
|
||
class Command(BaseCommand): | ||
help = """ | ||
Runs sql scripts to recreate access tables for the postgrest API. | ||
""" | ||
|
||
def add_arguments(self, parser): | ||
parser.add_argument("-i", "--init", action="store_true", default=False) | ||
parser.add_argument("-e", "--enable", action="store_true", default=False) | ||
parser.add_argument("-d", "--disable", action="store_true", default=False) | ||
|
||
def handle(self, *args, **options): | ||
if options["init"]: | ||
init_audit_curation() | ||
elif options["enable"]: | ||
enable_audit_curation() | ||
elif options["disable"]: | ||
disable_audit_curation() |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
select curation.disable_tracking('public.audit_singleauditchecklist'::regclass); | ||
select curation.disable_tracking('public.support_cognizantassignment'::regclass); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
select curation.enable_tracking('public.audit_singleauditchecklist'::regclass); | ||
select curation.enable_tracking('public.support_cognizantassignment'::regclass); |
Oops, something went wrong.