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

Sk/cog rebase #4489

Merged
merged 12 commits into from
Dec 4, 2024
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,
gsa-suk marked this conversation as resolved.
Show resolved Hide resolved
)
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
):
gsa-suk marked this conversation as resolved.
Show resolved Hide resolved
"""
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