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

Add Cross Validation for total_amount_expended < DOLLAR_THRESHOLD #4128

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 2 additions & 0 deletions backend/audit/cross_validation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
from .check_has_federal_awards import check_has_federal_awards
from .check_ref_number_in_cap import check_ref_number_in_cap
from .check_ref_number_in_findings_text import check_ref_number_in_findings_text
from .check_total_amount_expended import check_total_amount_expended
from .sac_validation_shape import sac_validation_shape # noqa: F401
from .submission_progress_check import submission_progress_check
from .tribal_data_sharing_consent import tribal_data_sharing_consent
Expand All @@ -86,6 +87,7 @@
check_has_federal_awards,
check_ref_number_in_cap,
check_ref_number_in_findings_text,
check_total_amount_expended,
submission_progress_check,
tribal_data_sharing_consent,
validate_general_information,
Expand Down
21 changes: 21 additions & 0 deletions backend/audit/cross_validation/check_total_amount_expended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from .errors import err_total_amount_expended
from config.settings import DOLLAR_THRESHOLD


def check_total_amount_expended(sac_dict, *_args, **_kwargs):
"""
Check that the total amount expended is less than the dollar threshold
"""
all_sections = sac_dict["sf_sac_sections"]

federal_awards = all_sections.get("federal_awards", {})

if not (federal_awards):
return []

total_amount_expended = federal_awards.get("total_amount_expended")

if total_amount_expended < DOLLAR_THRESHOLD:
return [{"error": err_total_amount_expended(total_amount_expended)}]
else:
return []
16 changes: 16 additions & 0 deletions backend/audit/cross_validation/errors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from audit.fixtures.excel import (
SECTION_NAMES,
)
from config.settings import DOLLAR_THRESHOLD
from .utils import format_refs


Expand Down Expand Up @@ -53,6 +54,21 @@ def err_biennial_low_risk():
)


def err_total_amount_expended(amount_expended):
# The UG states the exact dollar amount, but is potentially subject to change.
# So, we decouple the value from the quote and use the DOLLAR_THRESHOLD.
pretty_dollar_threshold = format(DOLLAR_THRESHOLD, ",")
pretty_amount_expended = format(amount_expended, ",")
return (
"According to Uniform Guidance section 200.501(d), a non-Federal entity "
"that expends less than the threshold during the non-Federal entity's "
"fiscal year in Federal awards is exempt from Federal audit requirements "
"for that year. "
f"The current threshold is ${pretty_dollar_threshold}. "
f"The amount expended is ${pretty_amount_expended}. "
)


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}."

Expand Down
56 changes: 56 additions & 0 deletions backend/audit/cross_validation/test_check_total_amount_expended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from django.test import TestCase
from model_bakery import baker
from audit.models import SingleAuditChecklist
from config.settings import DOLLAR_THRESHOLD

from .errors import err_total_amount_expended
from .check_total_amount_expended import check_total_amount_expended
from .sac_validation_shape import sac_validation_shape


class CheckTotalAmountExpendedTests(TestCase):
"""
Tests for check_total_amount_expended
"""

def _make_federal_awards(self, total_amount_expended) -> dict:
return {"FederalAwards": {"total_amount_expended": total_amount_expended}}

def test_total_amount_expended_equal_threshold(self):
"""
total_amount_expended at the threshold should pass.
"""
sac = baker.make(SingleAuditChecklist)
sac.federal_awards = self._make_federal_awards(DOLLAR_THRESHOLD)

validation_result = check_total_amount_expended(sac_validation_shape(sac))

self.assertEqual(validation_result, [])

def test_total_amount_expended_above_threshold(self):
"""
total_amount_expended above the threshold should pass.
"""
sac = baker.make(SingleAuditChecklist)
total_amount_expended = DOLLAR_THRESHOLD + 1
sac.federal_awards = self._make_federal_awards(total_amount_expended)

validation_result = check_total_amount_expended(sac_validation_shape(sac))

self.assertEqual(validation_result, [])

def test_total_amount_expended_below_threshold(self):
"""
total_amount_expended below the threshold should fail.
"""
sac = baker.make(SingleAuditChecklist)
total_amount_expended = DOLLAR_THRESHOLD - 1
sac.federal_awards = self._make_federal_awards(total_amount_expended)

validation_result = check_total_amount_expended(sac_validation_shape(sac))

self.assertEqual(len(validation_result), 1)
self.assertEqual(
validation_result[0],
{"error": err_total_amount_expended(total_amount_expended)},
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"FederalAwards": {
"auditee_uei": "TEST0001TEST",
"total_amount_expended": 12345,
"total_amount_expended": 1234567,
"federal_awards": [
{
"program": {
Expand Down
Loading