-
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.
Merge pull request #4647 from GSA-TTS/main
- Loading branch information
Showing
21 changed files
with
224 additions
and
162 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
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 was deleted.
Oops, something went wrong.
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
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,18 @@ | ||
import contextvars | ||
from contextlib import contextmanager | ||
|
||
|
||
current_sac = contextvars.ContextVar("current_sac", default=None) | ||
|
||
|
||
@contextmanager | ||
def set_sac_to_context(sac): | ||
reference = current_sac.set(sac) | ||
try: | ||
yield | ||
finally: | ||
current_sac.reset(reference) | ||
|
||
|
||
def get_sac_from_context(): | ||
return current_sac.get(None) |
62 changes: 62 additions & 0 deletions
62
backend/audit/intakelib/checks/check_finding_reference_year.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,62 @@ | ||
import logging | ||
from django.core.exceptions import ValidationError | ||
from audit.intakelib.intermediate_representation import ( | ||
get_range_by_name, | ||
) | ||
from audit.intakelib.common import ( | ||
get_message, | ||
build_cell_error_tuple, | ||
) | ||
|
||
from audit.context import get_sac_from_context | ||
from audit.intakelib.common.util import get_range_start_row | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
# DESCRIPTION | ||
# Finding references should be in 20##-### format where the first four | ||
# digits match the audit_year. | ||
|
||
|
||
def finding_reference_year(ir, is_gsa_migration=False): | ||
references = get_range_by_name(ir, "reference_number") | ||
range_start = int(get_range_start_row(references)) | ||
errors = [] | ||
sac = get_sac_from_context() | ||
if is_gsa_migration or sac and sac.general_information is None: | ||
# In real use cases, no report can be created if general_information is missing, as it is a required field. | ||
# The condition sac.general_information is None can occur only in test cases | ||
# where general_information has been ignored purposefully (like in test_workbooks_should_pass.py). | ||
return | ||
elif sac is None: | ||
raise ValidationError( | ||
( | ||
"", | ||
"", | ||
"Workbook Validation Failed", | ||
{ | ||
"text": "The workbook cannot be validated at the moment. Please contact the helpdesk for assistance.", | ||
"link": "Intake checks: no link defined", | ||
}, | ||
) | ||
) | ||
audit_date = sac.general_information["auditee_fiscal_period_end"] | ||
audit_year = int(audit_date.split("-")[0]) | ||
for index, reference in enumerate(references["values"]): | ||
year = int(reference.split("-")[0]) | ||
if audit_year != year: | ||
errors.append( | ||
build_cell_error_tuple( | ||
ir, | ||
references, | ||
index, | ||
get_message("check_invalid_finding_reference_year").format( | ||
reference, index + range_start, audit_year | ||
), | ||
) | ||
) | ||
|
||
if len(errors) > 0: | ||
logger.info("Raising a validation error.") | ||
raise ValidationError(errors) |
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 |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from unittest.mock import Mock | ||
from django.test import SimpleTestCase | ||
from django.core.exceptions import ValidationError | ||
from audit.intakelib.checks.check_finding_reference_year import finding_reference_year | ||
from audit.context import set_sac_to_context | ||
|
||
|
||
class TestFindingReferenceYear(SimpleTestCase): | ||
def setUp(self): | ||
self.ir = [ | ||
{ | ||
"name": "Form", | ||
"ranges": [ | ||
{ | ||
"name": "reference_number", | ||
"start_cell": {"column": "A", "row": "2"}, | ||
"end_cell": {"column": "A", "row": "20001"}, | ||
"values": ["2022-001", "2022-002", "2022-003"], | ||
}, | ||
], | ||
} | ||
] | ||
self.mock_sac = Mock() | ||
|
||
def test_success(self): | ||
""" | ||
Test case where all finding reference years match the audit year. | ||
""" | ||
self.mock_sac.general_information = { | ||
"auditee_fiscal_period_end": "2022-12-31", | ||
"auditee_uei": "UEI", | ||
} | ||
with set_sac_to_context(self.mock_sac): | ||
|
||
errors = finding_reference_year(self.ir) | ||
|
||
self.assertEqual(errors, None) | ||
|
||
def test_mismatched_years(self): | ||
""" | ||
Test case where finding reference years do not match the audit year. | ||
""" | ||
self.mock_sac.general_information = { | ||
"auditee_fiscal_period_end": "2023-12-31", | ||
"auditee_uei": "UEI", | ||
} | ||
with set_sac_to_context(self.mock_sac): | ||
with self.assertRaises(ValidationError) as context: | ||
finding_reference_year(self.ir) | ||
|
||
errors = context.exception.args[0] | ||
self.assertEqual(len(errors), 3) # Three mismatches | ||
self.assertIn("2022-001", errors[0][3]["text"]) | ||
self.assertIn("2022-002", errors[1][3]["text"]) | ||
self.assertIn("2022-003", errors[2][3]["text"]) | ||
|
||
def test_gsa_migration(self): | ||
""" | ||
Test case where is_gsa_migration is True and no validation is performed. | ||
""" | ||
errors = finding_reference_year(self.ir, is_gsa_migration=True) | ||
|
||
self.assertEqual(errors, None) | ||
|
||
def test_auditee_uei_missing(self): | ||
""" | ||
Test case where auditee_uei is None and the function returns without validation. | ||
""" | ||
self.mock_sac.general_information = { | ||
"auditee_fiscal_period_end": "2022-12-31", | ||
"auditee_uei": None, | ||
} | ||
with set_sac_to_context(self.mock_sac): | ||
errors = finding_reference_year(self.ir) | ||
self.assertEqual(errors, None) | ||
|
||
def test_sac_is_none(self): | ||
""" | ||
Test case where sac is None and a ValidationError is raised. | ||
""" | ||
with set_sac_to_context(None): | ||
with self.assertRaises(ValidationError) as context: | ||
finding_reference_year(self.ir) | ||
|
||
error = context.exception.args[0] | ||
self.assertEqual(error[2], "Workbook Validation Failed") | ||
self.assertEqual( | ||
error[3]["text"], | ||
"The workbook cannot be validated at the moment. Please contact the helpdesk for assistance.", | ||
) |
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
Oops, something went wrong.