Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2023-12-16 | MAIN --> PROD | DEV (e8aa48e) --> STAGING #3015

Merged
merged 5 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading