diff --git a/src/registrar/utility/csv_export.py b/src/registrar/utility/csv_export.py index 91eaad09e..2706a0d87 100644 --- a/src/registrar/utility/csv_export.py +++ b/src/registrar/utility/csv_export.py @@ -573,13 +573,10 @@ def get_sliced_requests(filter_condition): """Get filtered requests counts sliced by org type and election office.""" return get_org_type_counts(DomainRequest, filter_condition) - -def _org_type_count_query_builder(generic_org_type): - return Count(Case(When(generic_org_type=generic_org_type, then=1))) - def get_org_type_counts(model_class, filter_condition): """Returns a list of counts for each org type""" + # Count all org types, such as federal dynamic_count_dict = {} for choice in DomainRequest.OrganizationChoices: choice_name = f"{choice}_count" @@ -589,30 +586,55 @@ def get_org_type_counts(model_class, filter_condition): static_count_dict = { # Count all distinct records "total_count": Count('id'), + # Count all election boards "election_board_count": Count(Case(When(is_election_board=True, then=1))), } - # Merge static aggregates with dynamic organization type counts + # Merge static counts with dynamic organization type counts merged_count_dict = {**static_count_dict, **dynamic_count_dict} # Perform a single query with conditional aggregation model_queryset = model_class.objects.filter(**filter_condition).distinct() aggregates = model_queryset.aggregate(**merged_count_dict) - # TODO - automate this + # This can be automated but for the sake of readability, this is fixed for now. + # To automate this would also mean the added benefit of + # auto-updating (automatically adds new org types) charts, + # but that requires an upstream refactor. return [ - aggregates['total_count'], # total count - aggregates['federal_count'], # federal count - aggregates['interstate_count'], # interstate count - aggregates['state_or_territory_count'], # state or territory count - aggregates['tribal_count'], # tribal count - aggregates['county_count'], # county count - aggregates['city_count'], # city count - aggregates['special_district_count'], # special district count - aggregates['school_district_count'], # school district count - aggregates['election_board_count'], # election board count + # Total number of records + aggregates['total_count'], + # Number of records with org type FEDERAL + aggregates['federal_count'], + # Number of records with org type INTERSTATE + aggregates['interstate_count'], + # Number of records with org type STATE_OR_TERRITORY + aggregates['state_or_territory_count'], + # Number of records for TRIBAL + aggregates['tribal_count'], + # Number of records for COUNTY + aggregates['county_count'], + # Number of records for CITY + aggregates['city_count'], + # Number of records for SPECIAL_DISTRICT + aggregates['special_district_count'], + # Number of records for SCHOOL_DISTRICT + aggregates['school_district_count'], + # Number of records for ELECTION_BOARD + aggregates['election_board_count'], ] +def _org_type_count_query_builder(generic_org_type): + """ + Returns an expression that counts the number of a given generic_org_type. + On the backend (the DB), this returns an array of "1" which is then counted by the expression. + Used within an .aggregate call, but this essentially performs the same as queryset.count() + + We use this as opposed to queryset.count() because when this operation is repeated multiple times, + it is more efficient to do these once in the DB rather than multiple times (as each count consitutes a call) + """ + return Count(Case(When(generic_org_type=generic_org_type, then=1))) + def export_data_managed_domains_to_csv(csv_file, start_date, end_date): """Get counts for domains that have domain managers for two different dates, get list of managed domains at end_date."""