diff --git a/backend/dissemination/forms.py b/backend/dissemination/forms.py
index 5db043b3ea..9b51cb52c8 100644
--- a/backend/dissemination/forms.py
+++ b/backend/dissemination/forms.py
@@ -15,6 +15,7 @@ class SearchForm(forms.Form):
cog_or_oversight = forms.CharField(required=False)
agency_name = forms.CharField(required=False)
audit_year = forms.MultipleChoiceField(choices=AY_choices, required=False)
+ auditee_state = forms.CharField(required=False)
# Display params
limit = forms.CharField(required=False)
diff --git a/backend/dissemination/search.py b/backend/dissemination/search.py
index 66fc7f215d..d9ffec1fe7 100644
--- a/backend/dissemination/search.py
+++ b/backend/dissemination/search.py
@@ -12,6 +12,7 @@ def search_general(
cog_or_oversight=None,
agency_name=None,
audit_years=None,
+ auditee_state=None,
include_private=False,
):
query = Q()
@@ -23,6 +24,7 @@ def search_general(
query.add(_get_end_date_match_query(end_date), Q.AND)
query.add(_get_cog_or_oversight_match_query(agency_name, cog_or_oversight), Q.AND)
query.add(_get_audit_years_match_query(audit_years), Q.AND)
+ query.add(_get_auditee_state_match_query(auditee_state), Q.AND)
if not include_private:
query.add(Q(is_public=True), Q.AND)
@@ -167,3 +169,10 @@ def _get_audit_years_match_query(audit_years):
return Q()
return Q(audit_year__in=audit_years)
+
+
+def _get_auditee_state_match_query(auditee_state):
+ if not auditee_state:
+ return Q()
+
+ return Q(auditee_state__in=[auditee_state])
diff --git a/backend/dissemination/templates/search.html b/backend/dissemination/templates/search.html
index bba71d81e3..33aa9b568e 100644
--- a/backend/dissemination/templates/search.html
+++ b/backend/dissemination/templates/search.html
@@ -116,6 +116,19 @@
Filters
name="agency_name"
value="{{ form.cleaned_data.agency_name }}" />
+
+
+
+
{% comment %} Submission {% endcomment %}
diff --git a/backend/dissemination/test_search.py b/backend/dissemination/test_search.py
index ddc3788faf..4be697f078 100644
--- a/backend/dissemination/test_search.py
+++ b/backend/dissemination/test_search.py
@@ -223,14 +223,43 @@ def test_audit_year(self):
results = search_general(
audit_years=[2016],
)
+ assert_all_results_public(self, results)
self.assertEqual(len(results), 0)
results = search_general(
audit_years=[2020],
)
+ assert_all_results_public(self, results)
self.assertEqual(len(results), 1)
results = search_general(
audit_years=[2020, 2021, 2022],
)
+ assert_all_results_public(self, results)
self.assertEqual(len(results), 3)
+
+ def test_auditee_state(self):
+ """Given a state, search_general should return only records with a matching auditee_state"""
+ al = baker.make(General, is_public=True, auditee_state="AL")
+ baker.make(General, is_public=True, auditee_state="AK")
+ baker.make(
+ General,
+ is_public=True,
+ auditee_state="AZ",
+ audit_year="2020",
+ oversight_agency="01",
+ auditee_uei="not-looking-for-this-uei",
+ )
+
+ # there should be on result for AL
+ results = search_general(auditee_state="AL")
+
+ assert_all_results_public(self, results)
+ self.assertEqual(len(results), 1)
+ self.assertEqual(results[0], al)
+
+ # there should be no results for WI
+ results = search_general(auditee_state="WI")
+
+ assert_all_results_public(self, results)
+ self.assertEqual(len(results), 0)
diff --git a/backend/dissemination/views.py b/backend/dissemination/views.py
index 6cc0aff2d5..8d2bab9bf9 100644
--- a/backend/dissemination/views.py
+++ b/backend/dissemination/views.py
@@ -9,6 +9,8 @@
from audit.file_downloads import get_download_url, get_filename
from audit.models import SingleAuditChecklist
+from config.settings import STATE_ABBREVS
+
from dissemination.forms import SearchForm
from dissemination.search import search_general
from dissemination.mixins import ReportAccessRequiredMixin
@@ -41,7 +43,14 @@ class Search(View):
def get(self, request, *args, **kwargs):
form = SearchForm()
- return render(request, "search.html", {"form": form})
+ return render(
+ request,
+ "search.html",
+ {
+ "form": form,
+ "state_abbrevs": STATE_ABBREVS,
+ },
+ )
def post(self, request, *args, **kwargs):
form = SearchForm(request.POST)
@@ -59,6 +68,7 @@ def post(self, request, *args, **kwargs):
audit_years = [
int(year) for year in form.cleaned_data["audit_year"]
] # Cast strings from HTML to int
+ auditee_state = form.cleaned_data["auditee_state"]
# TODO: Add a limit choice field to the form
limit = form.cleaned_data["limit"] or 30
@@ -77,6 +87,7 @@ def post(self, request, *args, **kwargs):
cog_or_oversight=cog_or_oversight,
agency_name=agency_name,
audit_years=audit_years,
+ auditee_state=auditee_state,
include_private=include_private,
)
results_count = results.count()
@@ -100,6 +111,7 @@ def post(self, request, *args, **kwargs):
context = context | {
"form": form,
+ "state_abbrevs": STATE_ABBREVS,
"limit": limit,
"results": results,
"results_count": results_count,