Skip to content
Open
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
5 changes: 5 additions & 0 deletions backend/audit/models/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ class RESUBMISSION_STATUS:
UNKNOWN = "unknown_resubmission_status"


class RESUBMISSION_TAGS:
MOST_RECENT = "MOST RECENT"
DEPRECATED = "RESUBMITTED"


RESUBMISSION_STATUS_CHOICES = (
(RESUBMISSION_STATUS.MOST_RECENT, "Most Recent"),
(RESUBMISSION_STATUS.DEPRECATED, "Deprecated via Resubmission"),
Expand Down
80 changes: 18 additions & 62 deletions backend/dissemination/searchlib/search_resub_tags.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
from typing import Iterable, Mapping, Optional, Tuple
from collections.abc import MutableMapping

from dissemination.models import General
from audit.models.constants import RESUBMISSION_STATUS, RESUBMISSION_TAGS


def _safe_int(v) -> int:
Expand All @@ -11,64 +8,23 @@ def _safe_int(v) -> int:
return 0


def build_resub_tag_map(rows: Iterable[General]) -> Mapping[str, Optional[str]]:
def add_resub_tag_data(rows):
"""
report_id -> tag

Since everything is marked MOST_RECENT in the DB, we treat "is part of a resub chain"
as: resubmission_version > 1.

Per (auditee_uei, audit_year):
- the row with the highest version => "Most Recent"
- all other rows with version > 1 => "Resubmitted"
- version <= 1 (or missing) => no tag
Adds resubmission data to given rows
Only tag if it's deprecated OR if it's the most recent amongst resubmissions
"""

# (uei, year) -> best score (version, accepted_date, report_id) for stable tie-breaking
best_score_by_group: dict[Tuple[str, str], tuple] = {}
winner_report_id_by_group: dict[Tuple[str, str], str] = {}

# 1) find the winner per group among rows where version > 1
for row in rows:
v = _safe_int(getattr(row, "resubmission_version", None))
if v <= 1:
continue

key = (row.auditee_uei, row.audit_year)

acc = getattr(row, "fac_accepted_date", None)
# if date is None, keep it low so real dates win ties
score = (v, acc or 0, row.report_id)

if key not in best_score_by_group or score > best_score_by_group[key]:
best_score_by_group[key] = score
winner_report_id_by_group[key] = row.report_id

# 2) assign tags
tag_map: dict[str, Optional[str]] = {}

for row in rows:
v = _safe_int(getattr(row, "resubmission_version", None))
if v < 1:
tag_map[row.report_id] = None
continue

key = (row.auditee_uei, row.audit_year)
if winner_report_id_by_group.get(key) == row.report_id:
tag_map[row.report_id] = "Most Recent"
else:
tag_map[row.report_id] = "Resubmitted"

return tag_map


def attach_resubmission_tags(
rows: Iterable[General], tag_map: Mapping[str, Optional[str]]
) -> None:

for row in rows:
tag = tag_map.get(row.report_id)
if isinstance(row, MutableMapping):
row["resubmission_tag"] = tag
else:
setattr(row, "resubmission_tag", tag)
v = _safe_int(getattr(row, "resubmission_version", 0))
resub_status = getattr(row, "resubmission_status", RESUBMISSION_STATUS.UNKNOWN)
tag = None
color = None

if resub_status == RESUBMISSION_STATUS.DEPRECATED:
tag = f"V{v} ({RESUBMISSION_TAGS.DEPRECATED})"
color = "bg-red"
elif v > 1 and resub_status == RESUBMISSION_STATUS.MOST_RECENT:
tag = f"V{v} ({RESUBMISSION_TAGS.MOST_RECENT})"
color = "bg-green"

setattr(row, "resubmission_tag", tag)
setattr(row, "tag_color", color)
6 changes: 2 additions & 4 deletions backend/dissemination/templates/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,8 @@ <h1 class="font-sans-2xl">Audit Submissions Basic Search </h1>
<tr>
<th>
{{ result.auditee_name }}
{% if result.resubmission_tag == "Most Recent" %}
<span class="usa-tag bg-green margin-left-1">MOST RECENT</span>
{% elif result.resubmission_tag == "Resubmitted" %}
<span class="usa-tag bg-red margin-left-1">RESUBMITTED</span>
{% if result.resubmission_tag %}
<span class="usa-tag {{ result.tag_color }} margin-left-1">{{ result.resubmission_tag }}</span>
{% endif %}
</th>
{% comment %} Display UEI. If it's "GSA_MIGRATION", use the EIN instead. If no EIN, just show "GSA_MIGRATION". {% endcomment %}
Expand Down
208 changes: 106 additions & 102 deletions backend/dissemination/test_search_resub_tags.py
Original file line number Diff line number Diff line change
@@ -1,116 +1,120 @@
from datetime import date

from django.test import TestCase
from model_bakery import baker

from dissemination.models import General
from dissemination.searchlib.search_resub_tags import (
build_resub_tag_map,
attach_resubmission_tags,
add_resub_tag_data,
)
from model_bakery import baker
from audit.models.constants import RESUBMISSION_STATUS, RESUBMISSION_TAGS


class ResubmissionTagTests(TestCase):
def test_tag_most_recent_single_row_version_gt_1(self):
row = baker.make(
General,
report_id="1001",
auditee_uei="UEI1",
audit_year="2022",
resubmission_version=2,
)
tag_map = build_resub_tag_map([row])
self.assertEqual(tag_map["1001"], "Most Recent")

def test_highest_version_wins_rest_resubmitted(self):
row_v2 = baker.make(
General,
report_id="1002",
auditee_uei="UEI2",
audit_year="2022",
resubmission_version=2,
)
row_v3 = baker.make(
General,
report_id="1003",
auditee_uei="UEI2",
audit_year="2022",
resubmission_version=3,
)
def test_v0_no_tag(self):
"""v0 audits don't get a tag"""
rows = [
baker.make(
General,
report_id="1001",
auditee_uei="UEI1",
audit_year="2022",
resubmission_status=RESUBMISSION_STATUS.MOST_RECENT,
resubmission_version=0,
)
]
add_resub_tag_data(rows)

tag_map = build_resub_tag_map([row_v2, row_v3])
self.assertEqual(tag_map["1003"], "Most Recent")
self.assertEqual(tag_map["1002"], "Resubmitted")

def test_version_lt_1_should_not_tag(self):
row_v1 = baker.make(
General,
report_id="1004",
auditee_uei="UEI3",
audit_year="2022",
resubmission_version=1,
)
row_v0 = baker.make(
General,
report_id="1005",
auditee_uei="UEI3",
audit_year="2023",
resubmission_version=0, # use 0 instead of None (field is NOT NULL)
)
self.assertEqual(rows[0].resubmission_tag, None)

tag_map = build_resub_tag_map([row_v1, row_v0])
self.assertIsNotNone(tag_map["1004"])
self.assertIsNone(tag_map["1005"])

def test_tie_breaker_fac_accepted_date_then_report_id(self):
# same version -> later fac_accepted_date should win
row_earlier = baker.make(
General,
report_id="2001",
auditee_uei="UEI4",
audit_year="2022",
resubmission_version=2,
fac_accepted_date=date(2025, 1, 1),
)
row_later = baker.make(
General,
report_id="2002",
auditee_uei="UEI4",
audit_year="2022",
resubmission_version=2,
fac_accepted_date=date(2025, 2, 1),
)
def test_v1_no_tag(self):
"""v1 most_recent audits don't get a tag"""

tag_map = build_resub_tag_map([row_earlier, row_later])
self.assertEqual(tag_map["2002"], "Most Recent")
self.assertEqual(tag_map["2001"], "Resubmitted")

def test_attach_resubmission_tags(self):
row1 = baker.make(
General,
report_id="3001",
auditee_uei="UEI5",
audit_year="2022",
resubmission_version=2,
)
row2 = baker.make(
General,
report_id="3002",
auditee_uei="UEI5",
audit_year="2022",
resubmission_version=1,
rows = [
baker.make(
General,
report_id="1001",
auditee_uei="UEI1",
audit_year="2022",
resubmission_status=RESUBMISSION_STATUS.MOST_RECENT,
resubmission_version=1,
)
]
add_resub_tag_data(rows)

self.assertEqual(rows[0].resubmission_tag, None)

def test_v2_most_recent(self):
"""v2 most_recent audits do get a tag"""

rows = [
baker.make(
General,
report_id="1001",
auditee_uei="UEI1",
audit_year="2022",
resubmission_status=RESUBMISSION_STATUS.MOST_RECENT,
resubmission_version=2,
)
]
add_resub_tag_data(rows)

self.assertEqual(
rows[0].resubmission_tag, f"V2 ({RESUBMISSION_TAGS.MOST_RECENT})"
)
row3 = baker.make(
General,
report_id="3003",
auditee_uei="UEI5",
audit_year="2022",
resubmission_version=0, # no tag (unknown version number)

def test_v1_resub(self):
"""v1 deprecated audits do get a tag"""

rows = [
baker.make(
General,
report_id="1001",
auditee_uei="UEI1",
audit_year="2022",
resubmission_status=RESUBMISSION_STATUS.DEPRECATED,
resubmission_version=1,
)
]
add_resub_tag_data(rows)

self.assertEqual(
rows[0].resubmission_tag, f"V1 ({RESUBMISSION_TAGS.DEPRECATED})"
)
rows = [row1, row2, row3]

tag_map = build_resub_tag_map(rows)
attach_resubmission_tags(rows, tag_map)
def test_mixed(self):
"""Simple case of audits that get different tags"""

rows = [
baker.make(
General,
report_id="1000",
auditee_uei="UEI1",
audit_year="2022",
resubmission_status=RESUBMISSION_STATUS.MOST_RECENT,
resubmission_version=1,
),
baker.make(
General,
report_id="1001",
auditee_uei="UEI1",
audit_year="2022",
resubmission_status=RESUBMISSION_STATUS.DEPRECATED,
resubmission_version=1,
),
baker.make(
General,
report_id="1002",
auditee_uei="UEI1",
audit_year="2022",
resubmission_status=RESUBMISSION_STATUS.MOST_RECENT,
resubmission_version=2,
),
]
add_resub_tag_data(rows)

self.assertEqual(row1.resubmission_tag, "Most Recent")
self.assertEqual(row2.resubmission_tag, "Resubmitted")
self.assertIsNone(row3.resubmission_tag)
self.assertEqual(rows[0].resubmission_tag, None)
self.assertEqual(
rows[1].resubmission_tag, f"V1 ({RESUBMISSION_TAGS.DEPRECATED})"
)
self.assertEqual(
rows[2].resubmission_tag, f"V2 ({RESUBMISSION_TAGS.MOST_RECENT})"
)
Loading
Loading