def post(self, request):
        models = [
            {"name": "subawards", "key": "subawards", "type": "boolean", "default": False},
            {
                "name": "scope",
                "key": "scope",
                "type": "enum",
                "optional": False,
                "enum_values": ["place_of_performance", "recipient_location"],
            },
            {
                "name": "geo_layer",
                "key": "geo_layer",
                "type": "enum",
                "optional": False,
                "enum_values": ["state", "county", "district"],
            },
            {
                "name": "geo_layer_filters",
                "key": "geo_layer_filters",
                "type": "array",
                "array_type": "text",
                "text_type": "search",
            },
        ]
        models.extend(copy.deepcopy(AWARD_FILTER))
        models.extend(copy.deepcopy(PAGINATION))
        json_request = TinyShield(models).block(request.data)

        self.subawards = json_request["subawards"]
        self.scope = json_request["scope"]
        self.filters = json_request.get("filters", None)
        self.geo_layer = json_request["geo_layer"]
        self.geo_layer_filters = json_request.get("geo_layer_filters", None)

        fields_list = []  # fields to include in the aggregate query

        loc_dict = {"state": "state_code", "county": "county_code", "district": "congressional_code"}

        model_dict = {
            "place_of_performance": "pop",
            "recipient_location": "recipient_location",
            # 'subawards_place_of_performance': 'pop',
            # 'subawards_recipient_location': 'recipient_location'
        }

        # Build the query based on the scope fields and geo_layers
        # Fields not in the reference objects above then request is invalid

        scope_field_name = model_dict.get(self.scope)
        loc_field_name = loc_dict.get(self.geo_layer)
        loc_lookup = "{}_{}".format(scope_field_name, loc_field_name)

        if self.subawards:
            # We do not use matviews for Subaward filtering, just the Subaward download filters
            self.queryset = subaward_filter(self.filters)
            self.model_name = SubawardView
        else:
            self.queryset, self.model_name = spending_by_geography(self.filters)

        if self.geo_layer == "state":
            # State will have one field (state_code) containing letter A-Z
            column_isnull = "generated_pragmatic_obligation__isnull"
            if self.subawards:
                column_isnull = "amount__isnull"
            kwargs = {"{}_country_code".format(scope_field_name): "USA", column_isnull: False}

            # Only state scope will add its own state code
            # State codes are consistent in database i.e. AL, AK
            fields_list.append(loc_lookup)

            state_response = {
                "scope": self.scope,
                "geo_layer": self.geo_layer,
                "results": self.state_results(kwargs, fields_list, loc_lookup),
                "messages": [get_time_period_message()],
            }

            return Response(state_response)

        else:
            # County and district scope will need to select multiple fields
            # State code is needed for county/district aggregation
            state_lookup = "{}_{}".format(scope_field_name, loc_dict["state"])
            fields_list.append(state_lookup)

            # Adding regex to county/district codes to remove entries with letters since can't be surfaced by map
            kwargs = {"{}__isnull".format("amount" if self.subawards else "generated_pragmatic_obligation"): False}

            if self.geo_layer == "county":
                # County name added to aggregation since consistent in db
                county_name_lookup = "{}_county_name".format(scope_field_name)
                fields_list.append(county_name_lookup)
                self.county_district_queryset(kwargs, fields_list, loc_lookup, state_lookup, scope_field_name)

                county_response = {
                    "scope": self.scope,
                    "geo_layer": self.geo_layer,
                    "results": self.county_results(state_lookup, county_name_lookup),
                    "messages": [get_time_period_message()],
                }

                return Response(county_response)
            else:
                self.county_district_queryset(kwargs, fields_list, loc_lookup, state_lookup, scope_field_name)

                district_response = {
                    "scope": self.scope,
                    "geo_layer": self.geo_layer,
                    "results": self.district_results(state_lookup),
                    "messages": [get_time_period_message()],
                }

                return Response(district_response)
    def post(self, request: Request) -> Response:
        models = [
            {
                "name": "subawards",
                "key": "subawards",
                "type": "boolean",
                "default": False
            },
            {
                "name": "scope",
                "key": "scope",
                "type": "enum",
                "optional": False,
                "enum_values": ["place_of_performance", "recipient_location"],
            },
            {
                "name": "geo_layer",
                "key": "geo_layer",
                "type": "enum",
                "optional": False,
                "enum_values": ["state", "county", "district"],
            },
            {
                "name": "geo_layer_filters",
                "key": "geo_layer_filters",
                "type": "array",
                "array_type": "text",
                "text_type": "search",
            },
        ]
        models.extend(copy.deepcopy(AWARD_FILTER))
        models.extend(copy.deepcopy(PAGINATION))
        original_filters = request.data.get("filters")
        json_request = TinyShield(models).block(request.data)

        agg_key_dict = {
            "county": "county_agg_key",
            "district": "congressional_agg_key",
            "state": "state_agg_key",
        }
        location_dict = {
            "county": "county_code",
            "district": "congressional_code",
            "state": "state_code"
        }
        model_dict = {
            "place_of_performance": "pop",
            "recipient_location": "recipient_location",
            # 'subawards_place_of_performance': 'pop',
            # 'subawards_recipient_location': 'recipient_location'
        }

        self.scope_field_name = model_dict[json_request["scope"]]
        self.agg_key = f"{self.scope_field_name}_{agg_key_dict[json_request['geo_layer']]}"
        self.filters = json_request.get("filters")
        self.geo_layer = GeoLayer(json_request["geo_layer"])
        self.geo_layer_filters = json_request.get("geo_layer_filters")
        self.loc_field_name = location_dict[self.geo_layer.value]
        self.loc_lookup = f"{self.scope_field_name}_{self.loc_field_name}"
        self.subawards = json_request["subawards"]

        if self.subawards:
            # We do not use matviews for Subaward filtering, just the Subaward download filters
            self.model_name = SubawardView
            self.queryset = subaward_filter(self.filters)
            self.obligation_column = "amount"
            result = self.query_django()
        elif is_experimental_elasticsearch_api(request):
            if self.scope_field_name == "pop":
                scope_filter_name = "place_of_performance_scope"
            else:
                scope_filter_name = "recipient_scope"

            # Only search for values within USA, but don't overwrite a user's search
            if scope_filter_name not in self.filters:
                self.filters[scope_filter_name] = "domestic"

            self.obligation_column = "generated_pragmatic_obligation"
            filter_query = QueryWithFilters.generate_transactions_elasticsearch_query(
                self.filters)
            result = self.query_elasticsearch(filter_query)
        else:
            self.queryset, self.model_name = spending_by_geography(
                self.filters)
            self.obligation_column = "generated_pragmatic_obligation"
            result = self.query_django()

        return Response({
            "scope":
            json_request["scope"],
            "geo_layer":
            self.geo_layer.value,
            "results":
            result,
            "messages":
            get_generic_filters_message(
                original_filters.keys(),
                [elem["name"] for elem in AWARD_FILTER]),
        })
Пример #3
0
    def post(self, request):
        json_request = request.data

        self.subawards = json_request.get("subawards", False)
        self.scope = json_request.get("scope")
        self.filters = json_request.get("filters", {})
        self.geo_layer = json_request.get("geo_layer")
        self.geo_layer_filters = json_request.get("geo_layer_filters")

        fields_list = []  # fields to include in the aggregate query

        loc_dict = {
            'state': 'state_code',
            'county': 'county_code',
            'district': 'congressional_code'
        }

        model_dict = {
            'place_of_performance': 'pop',
            'recipient_location': 'recipient_location',
            'subawards_place_of_performance': 'place_of_performance',
            'subawards_recipient_location': 'recipient__location'
        }

        # Build the query based on the scope fields and geo_layers
        # Fields not in the reference objects above then request is invalid

        scope_field_name = model_dict.get('{}{}'.format('subawards_' if self.subawards else '', self.scope))
        loc_field_name = loc_dict.get(self.geo_layer)
        loc_lookup = '{}_{}{}'.format(scope_field_name, '_' if self.subawards else '', loc_field_name)

        if scope_field_name is None:
            raise InvalidParameterException("Invalid request parameters: scope")
        if loc_field_name is None:
            raise InvalidParameterException("Invalid request parameters: geo_layer")
        if type(self.subawards) is not bool:
            raise InvalidParameterException('subawards does not have a valid value')

        if self.subawards:
            # We do not use matviews for Subaward filtering, just the Subaward download filters
            self.queryset = subaward_filter(self.filters)
            self.model_name = Subaward
        else:
            self.queryset, self.model_name = spending_by_geography(self.filters)

        if self.geo_layer == 'state':
            # State will have one field (state_code) containing letter A-Z
            kwargs = {
                '{}_{}country_code'.format(scope_field_name, '_location_' if self.subawards else ''): 'USA',
                '{}'.format('amount__isnull' if self.subawards else 'federal_action_obligation__isnull'): False
            }

            # Only state scope will add its own state code
            # State codes are consistent in database i.e. AL, AK
            fields_list.append(loc_lookup)

            state_response = {
                'scope': self.scope,
                'geo_layer': self.geo_layer,
                'results': self.state_results(kwargs, fields_list, loc_lookup)
            }

            return Response(state_response)

        else:
            # County and district scope will need to select multiple fields
            # State code is needed for county/district aggregation
            state_lookup = '{}_{}{}'.format(scope_field_name, '_' if self.subawards else '', loc_dict['state'])
            fields_list.append(state_lookup)

            # Adding regex to county/district codes to remove entries with letters since can't be surfaced by map
            kwargs = {
                '{}__isnull'.format('amount' if self.subawards else 'federal_action_obligation'): False
            }

            if self.geo_layer == 'county':
                # County name added to aggregation since consistent in db
                county_name_lookup = '{}_{}county_name'.format(scope_field_name, '_' if self.subawards else '')
                fields_list.append(county_name_lookup)
                self.county_district_queryset(
                    kwargs,
                    fields_list,
                    loc_lookup,
                    state_lookup,
                    scope_field_name
                )

                county_response = {
                    'scope': self.scope,
                    'geo_layer': self.geo_layer,
                    'results': self.county_results(state_lookup, county_name_lookup)
                }

                return Response(county_response)
            else:
                self.county_district_queryset(
                    kwargs,
                    fields_list,
                    loc_lookup,
                    state_lookup,
                    scope_field_name
                )

                district_response = {
                    'scope': self.scope,
                    'geo_layer': self.geo_layer,
                    'results': self.district_results(state_lookup)
                }

                return Response(district_response)
Пример #4
0
    def post(self, request):
        models = [{
            'name': 'subawards',
            'key': 'subawards',
            'type': 'boolean',
            'default': False
        }, {
            'name': 'scope',
            'key': 'scope',
            'type': 'enum',
            'optional': False,
            'enum_values': ['place_of_performance', 'recipient_location']
        }, {
            'name': 'geo_layer',
            'key': 'geo_layer',
            'type': 'enum',
            'optional': False,
            'enum_values': ['state', 'county', 'district']
        }, {
            'name': 'geo_layer_filters',
            'key': 'geo_layer_filters',
            'type': 'array',
            'array_type': 'text',
            'text_type': 'search'
        }]
        models.extend(copy.deepcopy(AWARD_FILTER))
        models.extend(copy.deepcopy(PAGINATION))
        json_request = TinyShield(models).block(request.data)

        self.subawards = json_request["subawards"]
        self.scope = json_request["scope"]
        self.filters = json_request.get("filters", None)
        self.geo_layer = json_request["geo_layer"]
        self.geo_layer_filters = json_request.get("geo_layer_filters", None)

        fields_list = []  # fields to include in the aggregate query

        loc_dict = {
            'state': 'state_code',
            'county': 'county_code',
            'district': 'congressional_code'
        }

        model_dict = {
            'place_of_performance': 'pop',
            'recipient_location': 'recipient_location',
            # 'subawards_place_of_performance': 'pop',
            # 'subawards_recipient_location': 'recipient_location'
        }

        # Build the query based on the scope fields and geo_layers
        # Fields not in the reference objects above then request is invalid

        scope_field_name = model_dict.get(self.scope)
        loc_field_name = loc_dict.get(self.geo_layer)
        loc_lookup = '{}_{}'.format(scope_field_name, loc_field_name)

        if self.subawards:
            # We do not use matviews for Subaward filtering, just the Subaward download filters
            self.queryset = subaward_filter(self.filters)
            self.model_name = SubawardView
        else:
            self.queryset, self.model_name = spending_by_geography(
                self.filters)

        if self.geo_layer == 'state':
            # State will have one field (state_code) containing letter A-Z
            column_isnull = 'generated_pragmatic_obligation__isnull'
            if self.subawards:
                column_isnull = 'amount__isnull'
            kwargs = {
                '{}_country_code'.format(scope_field_name): 'USA',
                column_isnull: False
            }

            # Only state scope will add its own state code
            # State codes are consistent in database i.e. AL, AK
            fields_list.append(loc_lookup)

            state_response = {
                'scope': self.scope,
                'geo_layer': self.geo_layer,
                'results': self.state_results(kwargs, fields_list, loc_lookup)
            }

            return Response(state_response)

        else:
            # County and district scope will need to select multiple fields
            # State code is needed for county/district aggregation
            state_lookup = '{}_{}'.format(scope_field_name, loc_dict['state'])
            fields_list.append(state_lookup)

            # Adding regex to county/district codes to remove entries with letters since can't be surfaced by map
            kwargs = {
                '{}__isnull'.format('amount' if self.subawards else 'generated_pragmatic_obligation'):
                False
            }

            if self.geo_layer == 'county':
                # County name added to aggregation since consistent in db
                county_name_lookup = '{}_county_name'.format(scope_field_name)
                fields_list.append(county_name_lookup)
                self.county_district_queryset(kwargs, fields_list, loc_lookup,
                                              state_lookup, scope_field_name)

                county_response = {
                    'scope':
                    self.scope,
                    'geo_layer':
                    self.geo_layer,
                    'results':
                    self.county_results(state_lookup, county_name_lookup)
                }

                return Response(county_response)
            else:
                self.county_district_queryset(kwargs, fields_list, loc_lookup,
                                              state_lookup, scope_field_name)

                district_response = {
                    'scope': self.scope,
                    'geo_layer': self.geo_layer,
                    'results': self.district_results(state_lookup)
                }

                return Response(district_response)
    def post(self, request):
        models = [
            {'name': 'subawards', 'key': 'subawards', 'type': 'boolean', 'default': False},
            {'name': 'scope', 'key': 'scope', 'type': 'enum', 'optional': False,
             'enum_values': ['place_of_performance', 'recipient_location']},
            {'name': 'geo_layer', 'key': 'geo_layer', 'type': 'enum', 'optional': False,
             'enum_values': ['state', 'county', 'district']},
            {'name': 'geo_layer_filters', 'key': 'geo_layer_filters', 'type': 'array', 'array_type': 'text',
             'text_type': 'search'}
        ]
        models.extend(copy.deepcopy(AWARD_FILTER))
        models.extend(copy.deepcopy(PAGINATION))
        json_request = TinyShield(models).block(request.data)

        self.subawards = json_request["subawards"]
        self.scope = json_request["scope"]
        self.filters = json_request.get("filters", None)
        self.geo_layer = json_request["geo_layer"]
        self.geo_layer_filters = json_request.get("geo_layer_filters", None)

        fields_list = []  # fields to include in the aggregate query

        loc_dict = {
            'state': 'state_code',
            'county': 'county_code',
            'district': 'congressional_code'
        }

        model_dict = {
            'place_of_performance': 'pop',
            'recipient_location': 'recipient_location',
            # 'subawards_place_of_performance': 'pop',
            # 'subawards_recipient_location': 'recipient_location'
        }

        # Build the query based on the scope fields and geo_layers
        # Fields not in the reference objects above then request is invalid

        scope_field_name = model_dict.get(self.scope)
        loc_field_name = loc_dict.get(self.geo_layer)
        loc_lookup = '{}_{}'.format(scope_field_name, loc_field_name)

        if self.subawards:
            # We do not use matviews for Subaward filtering, just the Subaward download filters
            self.queryset = subaward_filter(self.filters)
            self.model_name = SubawardView
        else:
            self.queryset, self.model_name = spending_by_geography(self.filters)

        if self.geo_layer == 'state':
            # State will have one field (state_code) containing letter A-Z
            column_isnull = 'generated_pragmatic_obligation__isnull'
            if self.subawards:
                column_isnull = 'amount__isnull'
            kwargs = {
                '{}_country_code'.format(scope_field_name): 'USA',
                column_isnull: False
            }

            # Only state scope will add its own state code
            # State codes are consistent in database i.e. AL, AK
            fields_list.append(loc_lookup)

            state_response = {
                'scope': self.scope,
                'geo_layer': self.geo_layer,
                'results': self.state_results(kwargs, fields_list, loc_lookup)
            }

            return Response(state_response)

        else:
            # County and district scope will need to select multiple fields
            # State code is needed for county/district aggregation
            state_lookup = '{}_{}'.format(scope_field_name, loc_dict['state'])
            fields_list.append(state_lookup)

            # Adding regex to county/district codes to remove entries with letters since can't be surfaced by map
            kwargs = {
                '{}__isnull'.format('amount' if self.subawards else 'generated_pragmatic_obligation'): False
            }

            if self.geo_layer == 'county':
                # County name added to aggregation since consistent in db
                county_name_lookup = '{}_county_name'.format(scope_field_name)
                fields_list.append(county_name_lookup)
                self.county_district_queryset(
                    kwargs,
                    fields_list,
                    loc_lookup,
                    state_lookup,
                    scope_field_name
                )

                county_response = {
                    'scope': self.scope,
                    'geo_layer': self.geo_layer,
                    'results': self.county_results(state_lookup, county_name_lookup)
                }

                return Response(county_response)
            else:
                self.county_district_queryset(
                    kwargs,
                    fields_list,
                    loc_lookup,
                    state_lookup,
                    scope_field_name
                )

                district_response = {
                    'scope': self.scope,
                    'geo_layer': self.geo_layer,
                    'results': self.district_results(state_lookup)
                }

                return Response(district_response)