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

2024-12-05 | MAIN --> PROD | DEV (53c8abd) --> STAGING #4512

Merged
merged 1 commit into from
Dec 5, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion backend/audit/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,14 @@ def assign_cog_over(self):
self.submission_status,
)

audit_date = self.general_information["auditee_fiscal_period_end"]
audit_year = int(audit_date.split("-")[0])
cognizant_agency, oversight_agency = compute_cog_over(
self.federal_awards, self.submission_status, self.ein, self.auditee_uei
self.federal_awards,
self.submission_status,
self.ein,
self.auditee_uei,
audit_year,
)
if oversight_agency:
self.oversight_agency = oversight_agency
Expand Down
54 changes: 41 additions & 13 deletions backend/support/cog_over.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from collections import defaultdict
import logging
import math

from django.db.models.functions import Cast
from django.db.models import BigIntegerField, Q
Expand All @@ -13,8 +14,15 @@
COG_LIMIT = 50_000_000
DA_THRESHOLD_FACTOR = 0.25

FIRST_BASELINE_YEAR = 2019
BASELINE_VALID_FOR_YEARS = 5

def compute_cog_over(federal_awards, submission_status, auditee_ein, auditee_uei):
DBKEY_TO_UEI_TRANSITION_YEAR = "2022"


def compute_cog_over(
federal_awards, submission_status, auditee_ein, auditee_uei, audit_year
):
"""
Compute cog or oversight agency for the sac.
Return tuple (cog_agency, oversight_agency)
Expand Down Expand Up @@ -45,13 +53,28 @@ def compute_cog_over(federal_awards, submission_status, auditee_ein, auditee_uei
oversight_agency = agency
# logger.warning("Assigning an oversight agenct", oversight_agency)
return (cognizant_agency, oversight_agency)
cognizant_agency = determine_hist_agency(auditee_ein, auditee_uei)
base_year = calc_base_year(audit_year)
cognizant_agency = determine_hist_agency(auditee_ein, auditee_uei, base_year)
if cognizant_agency:
return (cognizant_agency, oversight_agency)
cognizant_agency = agency
return (cognizant_agency, oversight_agency)


def calc_base_year(audit_year):
# Note: 2019 is the first supported baseline year in GSAFAC
# For audit years 2019 through 2023, baseline year is 2019
# For audit years 2024 through 2028, baseline year is 2024
# For audit years 2029 through 2033, baseline year is 2029
# For audit years 2034 through 2038, baseline year is 2034
# and so on
base_year = (
math.floor((int(audit_year) - FIRST_BASELINE_YEAR) / BASELINE_VALID_FOR_YEARS)
* BASELINE_VALID_FOR_YEARS
) + FIRST_BASELINE_YEAR
return str(base_year)


def calc_award_amounts(awards):
total_amount_agency = defaultdict(lambda: 0)
total_da_amount_agency = defaultdict(lambda: 0)
Expand All @@ -77,18 +100,22 @@ def determine_agency(total_amount_expended, max_total_agency, max_da_agency):
return agency


def determine_hist_agency(ein, uei):
dbkey = get_dbkey(ein, uei)
def determine_hist_agency(ein, uei, base_year):
dbkey = None
if int(base_year) == FIRST_BASELINE_YEAR:
dbkey = get_dbkey(ein, uei)

cog_agency = lookup_baseline(ein, uei, dbkey)
if cog_agency:
return cog_agency
(gen_count, total_amount_expended, report_id_2019) = get_2019_gen(ein, uei)

(gen_count, total_amount_expended, report_id_base_year) = get_base_gen(
ein, uei, base_year
)
if gen_count != 1:
return None
cfdas = get_2019_cfdas(report_id_2019)
cfdas = get_base_cfdas(report_id_base_year)
if not cfdas:
# logger.warning("Found no cfda data for dbkey {dbkey} in 2019")
return None
(max_total_agency, max_da_agency) = calc_cfda_amounts(cfdas)
cognizant_agency = determine_agency(
Expand All @@ -102,7 +129,9 @@ def determine_hist_agency(ein, uei):
def get_dbkey(ein, uei):
try:
report_id = General.objects.values_list("report_id", flat=True).get(
Q(auditee_ein=ein), Q(auditee_uei=uei), Q(audit_year="2022")
Q(auditee_ein=ein),
Q(auditee_uei=uei),
Q(audit_year=DBKEY_TO_UEI_TRANSITION_YEAR),
)
except (General.DoesNotExist, General.MultipleObjectsReturned):
report_id = None
Expand All @@ -111,7 +140,7 @@ def get_dbkey(ein, uei):

try:
dbkey = MigrationInspectionRecord.objects.values_list("dbkey", flat=True).get(
Q(report_id=report_id), Q(audit_year="2022")
Q(report_id=report_id), Q(audit_year=DBKEY_TO_UEI_TRANSITION_YEAR)
)
except (
MigrationInspectionRecord.DoesNotExist,
Expand All @@ -136,18 +165,18 @@ def lookup_baseline(ein, uei, dbkey):
return cognizant_agency


def get_2019_gen(ein, uei):
def get_base_gen(ein, uei, base_year):
gens = General.objects.annotate(
amt=Cast("total_amount_expended", output_field=BigIntegerField())
).filter(Q(auditee_ein=ein), Q(auditee_uei=uei), Q(audit_year="2019"))
).filter(Q(auditee_ein=ein), Q(auditee_uei=uei), Q(audit_year=base_year))

if len(gens) != 1:
return (len(gens), 0, None)
gen = gens[0]
return (1, gen.amt, gen.report_id)


def get_2019_cfdas(report_id):
def get_base_cfdas(report_id):
cfdas = FederalAward.objects.annotate(
amt=Cast("amount_expended", output_field=BigIntegerField())
).filter(Q(report_id=report_id))
Expand Down Expand Up @@ -188,7 +217,6 @@ def prune_dict_to_max_values(data: dict):
for key, value in data.items():
if value == max_value:
pruned_dict[key] = value

return pruned_dict


Expand Down
Loading
Loading