diff --git a/backend/dissemination/search.py b/backend/dissemination/search.py index d9ffec1fe7..6a6d209bf5 100644 --- a/backend/dissemination/search.py +++ b/backend/dissemination/search.py @@ -1,6 +1,6 @@ from django.db.models import Q -from dissemination.models import General, FederalAward +from dissemination.models import General, FederalAward, Finding def search_general( @@ -17,7 +17,11 @@ def search_general( ): query = Q() - query.add(_get_aln_match_query(alns), Q.AND) + # 'alns' gets processed before the match query function, as they get used again after the main search. + if alns: + split_alns, agency_numbers = _split_alns(alns) + query.add(_get_aln_match_query(split_alns, agency_numbers), Q.AND) + query.add(_get_names_match_query(names), Q.AND) query.add(_get_uei_or_eins_match_query(uei_or_eins), Q.AND) query.add(_get_start_date_match_query(start_date), Q.AND) @@ -31,27 +35,20 @@ def search_general( results = General.objects.filter(query).order_by("-fac_accepted_date") + if alns: + results = _attach_finding_my_aln_and_finding_all_aln_fields( + results, split_alns, agency_numbers + ) + return results -def _get_aln_match_query(alns): +def _split_alns(alns): """ - Create the match query for ALNs. - Takes: A list of (potential) ALNs. - Returns: A query object matching on relevant report_ids found in the FederalAward table. - - # ALNs are a little weird, because they are stored per-award in the FederalAward table. To search on ALNs, we: - # 1. Split the given ALNs into a set with their prefix and extention. - # 2. Search the FederalAward table for awards with matching federal_agency_prefix and federal_award_extension. - # If there's just a prefix, search on all prefixes. - # If there's a prefix and extention, search on both. - # 3. Add the report_ids from the identified awards to the search params. + Split an ALN query string into two sets. + 1. split_alns: {(federal_agency_prefix, federal_award_extension), ...} + 2. agency_numbers: {('federal_agency_prefix'), ...} """ - - if not alns: - return Q() - - # Split each ALN into (prefix, extention) split_alns = set() agency_numbers = set() for aln in alns: @@ -66,28 +63,16 @@ def _get_aln_match_query(alns): # Otherwise, the individual elements go in unpaired. split_alns.update([tuple(split_aln)]) - # Search for relevant awards - report_ids = _get_aln_report_ids(split_alns) + return split_alns, agency_numbers - for agency_number in agency_numbers: - matching_awards = FederalAward.objects.filter( - federal_agency_prefix=agency_number - ).values() - if matching_awards: - for matching_award in matching_awards: - report_ids.update([matching_award.get("report_id")]) - # Add the report_id's from the award search to the full search params - alns_match = Q() - for report_id in report_ids: - alns_match.add(Q(report_id=report_id), Q.OR) - return alns_match - -def _get_aln_report_ids(split_alns): +def _get_aln_report_ids(split_alns, agency_numbers): """ - Given a set of split ALNs, find the relevant awards and return their report_ids. + Given a set of ALNs and a set agency numbers, find the relevant awards and return a set of report_ids. + Utilizing sets helps to avoid duplicate reports. """ report_ids = set() + # Matching on a specific ALN, such as '12.345' for aln_list in split_alns: matching_awards = FederalAward.objects.filter( federal_agency_prefix=aln_list[0], federal_award_extension=aln_list[1] @@ -97,9 +82,66 @@ def _get_aln_report_ids(split_alns): # Again, adding in a string requires [] so the individual # characters of the report ID don't go in... we want the whole string. report_ids.update([matching_award.get("report_id")]) + # Matching on a whole agency, such as '12' + for agency_number in agency_numbers: + matching_awards = FederalAward.objects.filter( + federal_agency_prefix=agency_number + ).values() + if matching_awards: + for matching_award in matching_awards: + report_ids.update([matching_award.get("report_id")]) + return report_ids +def _attach_finding_my_aln_and_finding_all_aln_fields( + results, split_alns, agency_numbers +): + """ + Given the results QuerySet (full of 'General' objects) and an ALN query string, + return the modified QuerySet, where each 'General' object has two new fields. + + The process: + 1. Get findings that fall under the given reports. + 2. For each finding, get the relevant award. This is to access its ALN. + 3. For each finding/award pair, they are either: + a. Under one of my ALNs, so we update finding_my_aln to True. + b. Under any other ALN, so we update finding_all_aln to True. + """ + for result in results: + result.finding_my_aln = False + result.finding_all_aln = False + matching_findings = Finding.objects.filter(report_id=result.report_id) + + for finding in matching_findings: + matching_award = FederalAward.objects.get( + report_id=result.report_id, award_reference=finding.award_reference + ) + prefix = matching_award.federal_agency_prefix + extension = matching_award.federal_award_extension + + if ((prefix, extension) in split_alns) or (prefix in agency_numbers): + result.finding_my_aln = True + else: + result.finding_all_aln = True + + return results + + +def _get_aln_match_query(split_alns, agency_numbers): + """ + Given split ALNs and agency numbers, return the match query for ALNs. + """ + # Search for relevant awards + report_ids = _get_aln_report_ids(split_alns, agency_numbers) + + # Add the report_id's from the award search to the full search params + alns_match = Q() + for report_id in report_ids: + alns_match.add(Q(report_id=report_id), Q.OR) + return alns_match + + def _get_names_match_query(names): """ Given a list of (potential) names, return the query object that searches auditee and firm names. diff --git a/backend/dissemination/templates/search.html b/backend/dissemination/templates/search.html index 33aa9b568e..f72c824e42 100644 --- a/backend/dissemination/templates/search.html +++ b/backend/dissemination/templates/search.html @@ -15,7 +15,9 @@
Name | -UEI or EIN | -Acc Date | -AY | -Cog or Over | -View | -
---|
{{ result.auditee_name }} | -{{ result.auditee_uei }} | - {% comment %} Sorts ascending/descending by the numeric date string (i.e. 20231231) {% endcomment %} -{{ result.fac_accepted_date }} - | -{{ result.audit_year }} | -- {% if result.oversight_agency %} - Oversight - {% else %} - Cognizant - {% endif %} - | -- - - - | -- - - - | +Name | +UEI or EIN | +Acc Date | +AY | +Cog or Over | +View | +Finding my ALN | +Finding all ALN | + {% endif %}
---|
+ Learn more about how our search filters work on our Search Resources page. +
+-Search works best with your device in landscape orientation.
-Search works best with your device in landscape orientation.
+