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,