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

Replacing missing ZIPCODE, CPAZIPCODE in historical audits #3808

Merged
merged 19 commits into from
May 13, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def check_for_gsa_migration_keyword(ir):
"contains_chart_or_table",
"is_minimis_rate_used",
"compliance_requirement",
"secondary_auditor_address_zipcode",
"secondary_auditor_name",
"secondary_auditor_address_state",
]
Expand Down
4 changes: 2 additions & 2 deletions backend/audit/test_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def test_invalid_zip(self):

with self.assertRaisesRegex(
exceptions.ValidationError,
"does not match",
"is not valid under any of the given schemas",
msg=f"ValidationError not raised with zip = {bad_zip}",
):
validate(instance, schema)
Expand Down Expand Up @@ -290,7 +290,7 @@ def test_invalid_zip_plus_4(self):

with self.assertRaisesRegex(
exceptions.ValidationError,
"does not match",
"is not valid under any of the given schemas",
msg=f"ValidationError not raised with zip = {bad_zip}",
):
validate(instance, schema)
Expand Down
2 changes: 2 additions & 0 deletions backend/audit/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ def validate_use_of_gsa_migration_keyword(general_information, is_data_migration
general_information.get("auditee_uei", ""),
general_information.get("ein", ""),
general_information.get("auditor_ein", ""),
general_information.get("auditee_zip", ""),
general_information.get("auditor_zip", ""),
]:
raise ValidationError(
_(f"{settings.GSA_MIGRATION} not permitted outside of migrations"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,32 @@ def xform_replace_empty_or_invalid_auditee_ein_with_gsa_migration(general_inform
return general_information


def xform_replace_empty_zips(general_information):
"""Replaces empty auditor and auditee zipcodes with GSA Migration keyword"""
# Transformation recorded.
if not general_information.get("auditor_zip"):
general_information["auditor_zip"] = settings.GSA_MIGRATION
track_transformations(
"CPAZIPCODE",
"",
"auditor_zip",
general_information["auditor_zip"],
"xform_replace_empty_zips",
)

if not general_information.get("auditee_zip"):
general_information["auditee_zip"] = settings.GSA_MIGRATION
track_transformations(
"ZIPCODE",
"",
"auditee_zip",
general_information["auditee_zip"],
"xform_replace_empty_zips",
)

return general_information


def general_information(audit_header):
"""Generates general information JSON."""
xform_update_multiple_eins_flag(audit_header)
Expand All @@ -458,6 +484,7 @@ def general_information(audit_header):
xform_replace_empty_auditee_email,
xform_replace_empty_or_invalid_auditor_ein_with_gsa_migration,
xform_replace_empty_or_invalid_auditee_ein_with_gsa_migration,
xform_replace_empty_zips,
]

for transform in transformations:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
xform_replace_empty_or_invalid_auditee_uei_with_gsa_migration,
xform_replace_empty_or_invalid_auditor_ein_with_gsa_migration,
xform_replace_empty_or_invalid_auditee_ein_with_gsa_migration,
xform_replace_empty_zips,
)
from .exception_utils import (
DataMigrationError,
Expand Down Expand Up @@ -431,3 +432,25 @@ def test_auditee_ein_empty_replaced(self):
result = xform_replace_empty_or_invalid_auditee_ein_with_gsa_migration(info)
mock_track.assert_called_once()
self.assertEqual(result["ein"], settings.GSA_MIGRATION)


class TestXformReplaceEmptyAuditorZip(SimpleTestCase):
def test_empty_auditor_zip(self):
"""Test that an empty auditor_zip and auditee_zip are replaced with 'GSA_MIGRATION'"""
input_data = {
"auditee_zip": "",
"auditor_zip": "",
}
expected_output = {
"auditee_zip": settings.GSA_MIGRATION,
"auditor_zip": settings.GSA_MIGRATION,
}
self.assertEqual(xform_replace_empty_zips(input_data), expected_output)

def test_non_empty_auditor_zip(self):
"""Test that a non-empty auditor_zip and auditee_zip remain unchanged"""
input_data = {
"auditee_zip": "10108",
"auditor_zip": "12345",
}
self.assertEqual(xform_replace_empty_zips(input_data), input_data)
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

from .workbooklib.secondary_auditors import (
xform_address_state,
xform_address_zipcode,
xform_cpafirmname,
)


class TestXformSecondaryAuditors(SimpleTestCase):
class TestXformSecondaryAuditorsState(SimpleTestCase):
class SecondaryAuditor:
def __init__(self, state):
self.CPASTATE = state
Expand All @@ -33,6 +34,32 @@ def test_missing_address_state(self):
self.assertEqual(secondary_auditors[0].CPASTATE, settings.GSA_MIGRATION)


class TestXformSecondaryAuditorsZipcode(SimpleTestCase):
class SecondaryAuditor:
def __init__(self, zipcode):
self.CPAZIPCODE = zipcode

def test_normal_address_zipcode(self):
# Setup specific test data
secondary_auditors = [
self.SecondaryAuditor("10108"),
]

xform_address_zipcode(secondary_auditors)

self.assertEqual(secondary_auditors[0].CPAZIPCODE, "10108")

def test_missing_address_zipcode(self):
# Setup specific test data
secondary_auditors = [
self.SecondaryAuditor(""),
]

xform_address_zipcode(secondary_auditors)

self.assertEqual(secondary_auditors[0].CPAZIPCODE, settings.GSA_MIGRATION)


class TestXformCpaFirmName(SimpleTestCase):
class MockSecondaryAuditorHeader:
def __init__(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
from ..exception_utils import DataMigrationError
from .xform_string_to_string import string_to_string
from django.conf import settings


def xform_remove_hyphen_and_pad_zip(zip):
"""
Transform a ZIP code string by removing hyphen if present and adding a leading zero when necessary.
- If the ZIP is settings.GSA_MIGRATION, return it
- If the ZIP code has hyphen, remove that character.
- If the ZIP code has 4 or 8 digits, pads with a leading zero.
- Returns the ZIP code if it has 5 digits or 9 digitis (after padding if needed).
- Raises an error for other cases.
"""
# Transformation to be documented.

if zip == settings.GSA_MIGRATION:
return zip

strzip = string_to_string(zip)
if "-" in strzip:
parts = strzip.split("-")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,33 @@ def xform_address_state(secondary_auditors):
InspectionRecord.append_secondary_auditor_changes(change_records)


def xform_address_zipcode(secondary_auditors):
"""Default missing address_zipcode to GSA_MIGRATION"""
change_records = []
is_empty_address_zipcode_found = False

for secondary_auditor in secondary_auditors:
address_zipcode = string_to_string(secondary_auditor.CPAZIPCODE)
if not address_zipcode:
is_empty_address_zipcode_found = True
address_zipcode = settings.GSA_MIGRATION

track_transformations(
"CPAZIPCODE",
secondary_auditor.CPAZIPCODE,
"address_zipcode",
address_zipcode,
["xform_address_zipcode"],
change_records,
)

secondary_auditor.CPAZIPCODE = address_zipcode

# See Transformation Method Change Recording comment at the top of this file
if change_records and is_empty_address_zipcode_found:
InspectionRecord.append_secondary_auditor_changes(change_records)


def _get_secondary_auditors(dbkey, year):
results = Caps.objects.filter(DBKEY=dbkey, AUDITYEAR=year)

Expand Down Expand Up @@ -142,6 +169,7 @@ def generate_secondary_auditors(audit_header, outfile):
audit_header.DBKEY, audit_header.AUDITYEAR
)
xform_address_state(secondary_auditors)
xform_address_zipcode(secondary_auditors)
xform_cpafirmname(secondary_auditors)
map_simple_columns(wb, mappings, secondary_auditors)
wb.save(outfile)
Expand Down
24 changes: 20 additions & 4 deletions backend/schemas/output/sections/GeneralInformation.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,16 @@
]
},
"auditee_zip": {
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
"oneOf": [
{
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
},
{
"const": "GSA_MIGRATION",
"type": "string"
}
]
},
"auditor_address_line_1": {
"maxLength": 100,
Expand Down Expand Up @@ -298,8 +306,16 @@
]
},
"auditor_zip": {
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
"oneOf": [
{
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
},
{
"const": "GSA_MIGRATION",
"type": "string"
}
]
},
"ein": {
"oneOf": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,16 @@
]
},
"auditee_zip": {
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
"oneOf": [
{
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
},
{
"const": "GSA_MIGRATION",
"type": "string"
}
]
},
"auditor_address_line_1": {
"maxLength": 100,
Expand Down Expand Up @@ -408,8 +416,16 @@
]
},
"auditor_zip": {
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
"oneOf": [
{
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
},
{
"const": "GSA_MIGRATION",
"type": "string"
}
]
},
"ein": {
"oneOf": [
Expand Down
12 changes: 10 additions & 2 deletions backend/schemas/output/sections/SecondaryAuditors.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,16 @@
"type": "string"
},
"secondary_auditor_address_zipcode": {
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
"oneOf": [
{
"pattern": "^[0-9]{5}(?:[0-9]{4})?$",
"type": "string"
},
{
"const": "GSA_MIGRATION",
"type": "string"
}
]
},
"secondary_auditor_contact_email": {
"format": "email",
Expand Down
18 changes: 16 additions & 2 deletions backend/schemas/source/sections/GeneralInformation.schema.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ Typechecks fields, but allows for empty data as well. Contains conditional check
maxLength: 100,
},
auditee_state: Base.Enum.UnitedStatesStateAbbr,
auditee_zip: Base.Compound.Zip,
auditee_zip: {
oneOf: [
Base.Compound.Zip,
Types.string {
const: Base.Const.GSA_MIGRATION,
},
],
},

auditee_contact_name: Types.string {
maxLength: 100,
Expand Down Expand Up @@ -91,7 +98,14 @@ Typechecks fields, but allows for empty data as well. Contains conditional check
maxLength: 100,
},
auditor_state: Base.Enum.UnitedStatesStateAbbr,
auditor_zip: Base.Compound.Zip,
auditor_zip: {
oneOf: [
Base.Compound.Zip,
Types.string {
const: Base.Const.GSA_MIGRATION,
},
],
},

auditor_contact_name: Types.string {
maxLength: 100,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ local SecondaryAuditorsEntry = {
},
],
},
secondary_auditor_address_zipcode: Base.Compound.Zip,
secondary_auditor_address_zipcode: {
oneOf: [
Base.Compound.Zip,
Types.string {
const: Base.Const.GSA_MIGRATION,
},
],
},
secondary_auditor_contact_name: Types.string,
secondary_auditor_contact_title: Types.string,
secondary_auditor_contact_phone: Base.Compound.UnitedStatesPhone,
Expand Down