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

Cross validation and waivers for prior references #4443

Merged
merged 24 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2a9987e
Adding check_finding_prior_references and tests
phildominguez-gsa Nov 8, 2024
b17c5b5
Cleanup
phildominguez-gsa Nov 8, 2024
c02637e
Adding test_get_prior_refs_no_repeat_prior_reference
phildominguez-gsa Nov 8, 2024
7c387ea
Removing unused fields
phildominguez-gsa Nov 8, 2024
a606d23
Changing EIN for UEI
phildominguez-gsa Nov 8, 2024
d8cf285
Replacing audit_year with auditee_fiscal_period_start and fixing erro…
phildominguez-gsa Nov 8, 2024
e732aea
Checking for prior refs earlier
phildominguez-gsa Nov 12, 2024
af203ef
Ignoring prior refs before 2022
phildominguez-gsa Nov 13, 2024
81b9172
Checking for reports from prior ref's year
phildominguez-gsa Nov 13, 2024
8e16196
Tests can now generate prior reports from priof ref numbers
phildominguez-gsa Nov 13, 2024
491cfc9
Reducing complexity; adding comments
phildominguez-gsa Nov 14, 2024
b95f789
Supporting validation waiver
phildominguez-gsa Nov 15, 2024
96f043f
Adding admin prior ref waiver creation case
phildominguez-gsa Nov 15, 2024
347427c
Lint
phildominguez-gsa Nov 15, 2024
21baea8
Querying all previous reports for prior refs
phildominguez-gsa Nov 21, 2024
a11b79d
Lint
phildominguez-gsa Nov 21, 2024
2510a29
Removing report_id exclusion
phildominguez-gsa Nov 21, 2024
0a8fd85
Updating cypress tests to use 2023 submission
phildominguez-gsa Nov 21, 2024
d015d94
Skipping validation for old prior refs
phildominguez-gsa Nov 22, 2024
6afdbad
Numeric string check
phildominguez-gsa Nov 22, 2024
e9d3327
Fixing test wb
phildominguez-gsa Nov 22, 2024
0db3780
Removing redundant N/A check
phildominguez-gsa Nov 25, 2024
bc36971
Reworking error message
phildominguez-gsa Nov 25, 2024
03672d6
Error message tweak
phildominguez-gsa Nov 25, 2024
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
11 changes: 11 additions & 0 deletions backend/audit/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ def save_model(self, request, obj, form, change):
logger.info(
f"Duplicate finding reference number waiver applied to SAC {sac.report_id} by user: {request.user.email}."
)
elif (
STATUS.IN_PROGRESS
and SacValidationWaiver.TYPES.PRIOR_REFERENCES in obj.waiver_types
):
logger.info(
f"User {request.user.email} is applying waiver for SAC with status: {sac.submission_status}"
)
super().save_model(request, obj, form, change)
logger.info(
f"Invalid prior reference waiver applied to SAC {sac.report_id} by user: {request.user.email}."
)
else:
messages.set_level(request, messages.WARNING)
messages.warning(
Expand Down
2 changes: 2 additions & 0 deletions backend/audit/cross_validation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
from .check_award_ref_declaration import check_award_ref_declaration
from .check_award_ref_existence import check_award_ref_existence
from .check_award_reference_uniqueness import check_award_reference_uniqueness
from .check_finding_prior_references import check_finding_prior_references
from .check_biennial_low_risk import check_biennial_low_risk
from .check_certifying_contacts import check_certifying_contacts
from .check_finding_reference_uniqueness import check_finding_reference_uniqueness
Expand All @@ -82,6 +83,7 @@
check_biennial_low_risk,
check_certifying_contacts,
check_finding_reference_uniqueness,
check_finding_prior_references,
check_findings_count_consistency,
check_has_federal_awards,
check_ref_number_in_cap,
Expand Down
122 changes: 122 additions & 0 deletions backend/audit/cross_validation/check_finding_prior_references.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
from .errors import (
err_prior_no_report,
err_bad_repeat_prior_reference,
err_prior_ref_not_found,
)
from dissemination.models import (
Finding,
General,
)

from datetime import date


def check_finding_prior_references(sac_dict, *_args, **_kwargs):
"""
Check that prior references numbers point to findings that actually exist
in a previously submitted report
"""
# Importing here to avoid circular import
from audit.models import SacValidationWaiver

if SacValidationWaiver.TYPES.PRIOR_REFERENCES in sac_dict.get("waiver_types", []):
return []

all_sections = sac_dict.get("sf_sac_sections")
findings_uniform_guidance_section = (
all_sections.get("findings_uniform_guidance") or {}
)
findings_uniform_guidance = findings_uniform_guidance_section.get(
"findings_uniform_guidance_entries", []
)
all_prior_refs = _get_prior_refs(findings_uniform_guidance)

# No prior reference numbers to validate
if not all_prior_refs:
return []

general_information = all_sections.get("general_information")
auditee_uei = general_information["auditee_uei"]
audit_year = date.fromisoformat(
general_information["auditee_fiscal_period_start"]
).year

# UEIs only become reliable as of 2022, so don't bother invalidating
# prior references before that
if audit_year < 2023:
return []

# Get the report_ids for previous reports
previous_report_ids = General.objects.filter(auditee_uei=auditee_uei).values_list(
"report_id", flat=True
)
errors = []

# Validate all prior reference numbers for each award
for award_ref, prior_refs_strings in all_prior_refs.items():
prior_refs = prior_refs_strings.split(",")
_validate_prior_refs(
prior_refs,
award_ref,
auditee_uei,
previous_report_ids,
errors,
)

return errors


def _get_prior_refs(findings_uniform_guidance):
"""
Returns a dict that maps award references to a list of prior references
strings
"""
all_prior_refs = {}

for finding in findings_uniform_guidance:
if finding["findings"]["repeat_prior_reference"] == "Y":
award_ref = finding["program"]["award_reference"]
cur_prior_refs = finding["findings"]["prior_references"]
all_prior_refs[award_ref] = cur_prior_refs

return all_prior_refs


def _validate_prior_refs(
prior_refs, award_ref, auditee_uei, previous_report_ids, errors
):
"""
Performs validation on the given list of prior reference numbers
"""
for prior_ref in prior_refs:
prior_ref_year = prior_ref[:4]

if prior_ref == "N/A":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to remove (or keep) this check. Since we are enforcing validation for year > 2022 and we have these validations (v1 and v2) at intake time it is unlikely to have a case with finding["findings"]["repeat_prior_reference"] == "Y" and prior_ref == "N/A"

Copy link
Contributor Author

@phildominguez-gsa phildominguez-gsa Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

errors.append(
{
"error": err_bad_repeat_prior_reference(award_ref),
}
)

continue
elif prior_ref_year.isnumeric() and int(prior_ref_year) < 2022:
# Skip validation for pre-UEI prior references
continue
elif not previous_report_ids:
errors.append(
{
"error": err_prior_no_report(auditee_uei, prior_ref),
}
)

continue
elif not Finding.objects.filter(
report_id__in=previous_report_ids,
reference_number=prior_ref,
).exists():
# Error if we can't find the prior finding in previous reports
errors.append(
{
"error": err_prior_ref_not_found(prior_ref),
}
)
12 changes: 12 additions & 0 deletions backend/audit/cross_validation/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ def err_duplicate_finding_reference(award_ref, ref_number):
return f"Award {award_ref} repeats reference {ref_number}. The reference {ref_number} should only appear once for award {award_ref}."


def err_prior_no_report(auditee_uei, prior_ref_number):
return f"Findings uniform guidance contains prior reference {prior_ref_number}, but no previous reports were found for UEI {auditee_uei}."


def err_bad_repeat_prior_reference(award_ref):
return f"Award {award_ref} field 'Repeat Findings from Prior Year' is set to 'Y', but the 'Prior Year Audit Finding Reference Number' is set to 'N/A'."


def err_prior_ref_not_found(prior_ref_number):
return f"Prior reference number {prior_ref_number} not found in previous reports."


def err_findings_count_inconsistent(total_expected, total_counted, award_ref):
return (
f"You reported {total_expected} findings for award {award_ref} in the {SECTION_NAMES.FEDERAL_AWARDS} workbook, "
Expand Down
Loading