Skip to content

Commit

Permalink
Merge pull request #3015 from GSA-TTS/main
Browse files Browse the repository at this point in the history
  • Loading branch information
jadudm authored Dec 16, 2023
2 parents 6511c62 + e8aa48e commit ff80a8e
Show file tree
Hide file tree
Showing 33 changed files with 1,333 additions and 244 deletions.
15 changes: 15 additions & 0 deletions backend/audit/cross_validation/naming.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from types import new_class
from typing import NamedTuple

from audit.models.submission_event import SubmissionEvent

# We need a canonical source of the different versions of each name.


Expand All @@ -17,6 +19,7 @@ class SectionBabelFish(NamedTuple):
snake_case: str # Mostly used for the field names in SingleAuditChecklist.
url_tail: str | None # Hyphenated version of snake_case, mostly.
workbook_number: int | None # Our upload ordering of workbooks.
submission_event: str # The event type we log to the SubmissionEvents table when this section is updated


SECTION_NAMES = {
Expand All @@ -29,6 +32,7 @@ class SectionBabelFish(NamedTuple):
snake_case="additional_eins",
url_tail="additional-eins",
workbook_number=8,
submission_event=SubmissionEvent.EventType.ADDITIONAL_EINS_UPDATED,
),
"additional_ueis": SectionBabelFish(
all_caps="ADDITIONAL_UEIS",
Expand All @@ -39,6 +43,7 @@ class SectionBabelFish(NamedTuple):
snake_case="additional_ueis",
url_tail="additional-ueis",
workbook_number=6,
submission_event=SubmissionEvent.EventType.ADDITIONAL_UEIS_UPDATED,
),
"audit_information": SectionBabelFish(
all_caps="AUDIT_INFORMATION",
Expand All @@ -49,6 +54,7 @@ class SectionBabelFish(NamedTuple):
snake_case="audit_information",
url_tail="audit-information",
workbook_number=None,
submission_event=SubmissionEvent.EventType.AUDIT_INFORMATION_UPDATED,
),
"corrective_action_plan": SectionBabelFish(
all_caps="CORRECTIVE_ACTION_PLAN",
Expand All @@ -59,6 +65,7 @@ class SectionBabelFish(NamedTuple):
reverse_url="report_submission:CAP",
url_tail="cap",
workbook_number=5,
submission_event=SubmissionEvent.EventType.CORRECTIVE_ACTION_PLAN_UPDATED,
),
"federal_awards": SectionBabelFish(
all_caps="FEDERAL_AWARDS",
Expand All @@ -69,6 +76,7 @@ class SectionBabelFish(NamedTuple):
snake_case="federal_awards",
url_tail="federal-awards",
workbook_number=1,
submission_event=SubmissionEvent.EventType.FEDERAL_AWARDS_UPDATED,
),
"findings_text": SectionBabelFish(
all_caps="FINDINGS_TEXT",
Expand All @@ -79,6 +87,7 @@ class SectionBabelFish(NamedTuple):
snake_case="findings_text",
url_tail="audit-findings-text",
workbook_number=4,
submission_event=SubmissionEvent.EventType.FEDERAL_AWARDS_AUDIT_FINDINGS_TEXT_UPDATED,
),
"findings_uniform_guidance": SectionBabelFish(
all_caps="FINDINGS_UNIFORM_GUIDANCE",
Expand All @@ -89,6 +98,7 @@ class SectionBabelFish(NamedTuple):
snake_case="findings_uniform_guidance",
url_tail="audit-findings",
workbook_number=3,
submission_event=SubmissionEvent.EventType.FINDINGS_UNIFORM_GUIDANCE_UPDATED,
),
"general_information": SectionBabelFish(
all_caps="GENERAL_INFORMATION",
Expand All @@ -99,6 +109,7 @@ class SectionBabelFish(NamedTuple):
snake_case="general_information",
url_tail="general-information",
workbook_number=None,
submission_event=SubmissionEvent.EventType.GENERAL_INFORMATION_UPDATED,
),
"notes_to_sefa": SectionBabelFish(
all_caps="NOTES_TO_SEFA",
Expand All @@ -109,6 +120,7 @@ class SectionBabelFish(NamedTuple):
snake_case="notes_to_sefa",
url_tail="notes-to-sefa",
workbook_number=2,
submission_event=SubmissionEvent.EventType.NOTES_TO_SEFA_UPDATED,
),
"single_audit_report": SectionBabelFish(
all_caps="SINGLE_AUDIT_REPORT",
Expand All @@ -119,6 +131,7 @@ class SectionBabelFish(NamedTuple):
snake_case="single_audit_report",
url_tail="upload-report",
workbook_number=None,
submission_event=SubmissionEvent.EventType.AUDIT_REPORT_PDF_UPDATED,
),
"secondary_auditors": SectionBabelFish(
all_caps="SECONDARY_AUDITORS",
Expand All @@ -129,6 +142,7 @@ class SectionBabelFish(NamedTuple):
snake_case="secondary_auditors",
url_tail="secondary-auditors",
workbook_number=7,
submission_event=SubmissionEvent.EventType.SECONDARY_AUDITORS_UPDATED,
),
"tribal_data_consent": SectionBabelFish(
all_caps="TRIBAL_DATA_CONSENT",
Expand All @@ -139,6 +153,7 @@ class SectionBabelFish(NamedTuple):
snake_case="tribal_data_consent",
url_tail=None,
workbook_number=None,
submission_event=SubmissionEvent.EventType.TRIBAL_CONSENT_UPDATED,
),
}

Expand Down
48 changes: 42 additions & 6 deletions backend/audit/cross_validation/submission_progress_check.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from audit.cross_validation.naming import NC, find_section_by_name
from audit.models.submission_event import SubmissionEvent
from audit.validators import validate_general_information_complete_json
from django.core.exceptions import ValidationError

Expand Down Expand Up @@ -44,7 +45,7 @@ def submission_progress_check(sac, sar=None, crossval=True):
result = {k: None for k in sac["sf_sac_sections"]}

for key in sac["sf_sac_sections"]:
result = result | progress_check(sac["sf_sac_sections"], key)
result = result | progress_check(sac, sac["sf_sac_sections"], key)

incomplete_sections = []
for k in result:
Expand All @@ -66,7 +67,7 @@ def submission_progress_check(sac, sar=None, crossval=True):
]


def progress_check(sections, key):
def progress_check(sac, sections, key):
"""
Given the content of sf_sac_sections from sac_validation_shape (plus a
single_audit_report key) and a key, determine whether that key is required, and
Expand Down Expand Up @@ -111,20 +112,45 @@ def get_num_findings(award):

# The General Information has its own condition, as it can be partially completed.
if key == "general_information":
return general_information_progress_check(progress, general_info)
return general_information_progress_check(progress, general_info, sac)

# If it's not required, it's inactive:
if not conditions[key]:
return {key: progress | {"display": "inactive"}}

# If it is required, it should be present
if sections.get(key):
return {key: progress | {"display": "complete", "completed": True}}
completed_by, completed_date = section_completed_metadata(sac, key)

return {
key: progress
| {
"display": "complete",
"completed": True,
"completed_by": completed_by,
"completed_date": completed_date,
}
}

return {key: progress | {"display": "incomplete", "completed": False}}


def general_information_progress_check(progress, general_info):
def section_completed_metadata(sac, section_key):
try:
section = find_section_by_name(section_key)
event_type = section.submission_event

report_id = sac["sf_sac_meta"]["report_id"]
event = SubmissionEvent.objects.filter(
sac__report_id=report_id, event=event_type
).latest("timestamp")

return event.user.email, event.timestamp
except SubmissionEvent.DoesNotExist:
return None, None


def general_information_progress_check(progress, general_info, sac):
"""
Given a base "progress" dictionary and the general_info object from a submission,
run validations to determine its completeness. Then, return a dictionary with
Expand All @@ -138,8 +164,18 @@ def general_information_progress_check(progress, general_info):
is_general_info_complete = False

if is_general_info_complete:
completed_by, completed_date = section_completed_metadata(
sac, "general_information"
)

return {
"general_information": progress | {"display": "complete", "completed": True}
"general_information": progress
| {
"display": "complete",
"completed": True,
"completed_by": completed_by,
"completed_date": completed_date,
}
}
return {
"general_information": progress | {"display": "incomplete", "completed": False}
Expand Down
38 changes: 25 additions & 13 deletions backend/audit/intake_to_dissemination.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ def omit(remove, d) -> dict:


class IntakeToDissemination(object):
def __init__(self, sac) -> None:
DISSEMINATION = "dissemination"
PRE_CERTIFICATION_REVIEW = "pre_certification_review"

def __init__(self, sac, mode=DISSEMINATION) -> None:
self.single_audit_checklist = sac
self.report_id = sac.report_id
audit_date = sac.general_information["auditee_fiscal_period_end"]
self.audit_year = int(audit_date.split("-")[0])
self.loaded_objects: dict[str, list] = {}
self.mode = mode

def load_all(self):
load_methods = {
Expand Down Expand Up @@ -280,18 +284,26 @@ def load_general(self):
dates_by_status = self._get_dates_from_sac()
status = self.single_audit_checklist.STATUS
ready_for_certification_date = dates_by_status[status.READY_FOR_CERTIFICATION]
auditor_certified_date = dates_by_status[status.AUDITOR_CERTIFIED]
auditee_certified_date = dates_by_status[status.AUDITEE_CERTIFIED]
submitted_date = self._convert_utc_to_american_samoa_zone(
dates_by_status[status.SUBMITTED]
)
fac_accepted_date = submitted_date
auditee_certify_name = auditee_certification["auditee_signature"][
"auditee_name"
]
auditee_certify_title = auditee_certification["auditee_signature"][
"auditee_title"
]
if self.mode == IntakeToDissemination.DISSEMINATION:
submitted_date = self._convert_utc_to_american_samoa_zone(
dates_by_status[status.SUBMITTED]
)
fac_accepted_date = submitted_date
auditee_certify_name = auditee_certification["auditee_signature"][
"auditee_name"
]
auditee_certify_title = auditee_certification["auditee_signature"][
"auditee_title"
]
auditor_certified_date = dates_by_status[status.AUDITOR_CERTIFIED]
auditee_certified_date = dates_by_status[status.AUDITEE_CERTIFIED]
elif self.mode == IntakeToDissemination.PRE_CERTIFICATION_REVIEW:
submitted_date = None
fac_accepted_date = submitted_date
auditee_certify_name = None
auditee_certify_title = None
auditor_certified_date = None
auditee_certified_date = None

total_amount_expended = self.single_audit_checklist.federal_awards[
"FederalAwards"
Expand Down
33 changes: 31 additions & 2 deletions backend/audit/templates/audit/auditee-certification-step-1.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,43 @@
{% extends "base.html" %}
{% load static %}
{% load sprite_helper %}
{% block content %}
<div class="grid-container margin-top-6">
<div class="grid-row">
<form class="grid-col-8 grid-offset-2"
<form class="tablet:grid-col-8 tablet:grid-offset-2"
id="auditee-certification-step-1"
method="post">
{% csrf_token %}
<fieldset class="usa-fieldset padding-bottom-2">
<legend class="usa-legend usa-legend--large" id="auditee-certification">Auditee certification checklist</legend>
<legend class="usa-legend usa-legend--large" id="auditee-certification">Auditee certification</legend>

<p>Download and review the SF-SAC and single audit report below. These files are for review only and can't be edited.</p>
<p>After reviewing, check the box next to each item to confirm your report meets the requirements.</p>

<div class="usa-button-group margin-top-2">
<a class="usa-button display-flex"
href="{% url 'audit:PredisseminationSummaryReportDownload' report_id=report_id %}"
target="_blank">
<svg class="usa-icon margin-right-1 flex-align-self-center"
aria-hidden="true"
role="img">
{% uswds_sprite "file_download" %}
</svg>
<p class="margin-0">Download SF-SAC</p>
</a>

<a class="usa-button display-flex margin-top-2 tablet:margin-top-0"
href="{% url 'audit:PredisseminationPdfDownload' report_id=report_id %}"
target="_blank">
<svg class="usa-icon margin-right-1 flex-align-self-center"
aria-hidden="true"
role="img">
{% uswds_sprite "file_download" %}
</svg>
<p class="margin-0">Download single audit report</p>
</a>
</div>

<h3>Check the box next to each item confirm your report meets the requirements.</h3>
<p class="text-base">You must check all boxes must be checked in order to certify your single audit.</p>
<div class="usa-checkbox margin-top-4">
Expand Down
37 changes: 33 additions & 4 deletions backend/audit/templates/audit/auditor-certification-step-1.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,43 @@
{% extends "base.html" %}
{% load static %}
{% load sprite_helper %}
{% block content %}
<div class="grid-container margin-top-6">
<div class="grid-row">
<form class="grid-col-8 grid-offset-2"
<form class="tablet:grid-col-8 tablet:grid-offset-2"
id="auditor-certification-step-1"
method="post">
{% csrf_token %}
<fieldset class="usa-fieldset padding-bottom-2">
<legend class="usa-legend usa-legend--large" id="auditor-certification">Auditor certification checklist</legend>
<legend class="usa-legend usa-legend--large" id="auditor-certification">Auditor certification</legend>

<p>Download and review the SF-SAC and single audit report below. These files are for review only and can't be edited.</p>
<p>After reviewing, check the box next to each item to confirm your report meets the requirements.</p>

<div class="usa-button-group margin-top-2">
<a class="usa-button display-flex"
href="{% url 'audit:PredisseminationSummaryReportDownload' report_id=report_id %}"
target="_blank">
<svg class="usa-icon margin-right-1 flex-align-self-center"
aria-hidden="true"
role="img">
{% uswds_sprite "file_download" %}
</svg>
<p class="margin-0">Download SF-SAC</p>
</a>

<a class="usa-button display-flex margin-top-2 tablet:margin-top-0"
href="{% url 'audit:PredisseminationPdfDownload' report_id=report_id %}"
target="_blank">
<svg class="usa-icon margin-right-1 flex-align-self-center"
aria-hidden="true"
role="img">
{% uswds_sprite "file_download" %}
</svg>
<p class="margin-0">Download single audit report</p>
</a>
</div>

<h3>Check the box next to each item confirm your report meets the requirements.</h3>
<p class="text-base">You must check all boxes in order to certify your single audit.</p>
<div class="usa-checkbox margin-top-4">
Expand Down Expand Up @@ -81,8 +110,8 @@ <h3>Check the box next to each item confirm your report meets the requirements.<
</fieldset>
<div class="grid-row margin-bottom-8 margin-top-10">
<button class="usa-button grid-col-5" id="continue">Agree to auditor certification</button>
<a class="usa-link margin-left-3 grid-col-2 flex-align-self-center"
href="/">Cancel</a>
<a class="usa-link margin-left-3 grid-col-2 flex-align-self-center" id="cancel-auditor-certification-link"
href="{% url 'audit:SubmissionProgress' report_id %}">Cancel</a>
</div>
</form>
</div>
Expand Down
2 changes: 1 addition & 1 deletion backend/audit/templates/audit/manage-submission.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
</table>
{% comment %}
Uncomment if/when we chose to keep the flags.
<p class="font-sans-xs">An asterisk (<strong>*</strong>) following an email address indicates that no user with this email address has logged in thus far.</p>
<p class="font-sans-xs">(<strong>*</strong>) Indicates user has not logged in to view this submission.</p>
{% endcomment %}
<a class="usa-button usa-button--outline margin-top-5"
href="{% url 'audit:SubmissionProgress' report_id %}"
Expand Down
Loading

0 comments on commit ff80a8e

Please sign in to comment.