From 0e40783a83709b807e235781f1cffcaa894de189 Mon Sep 17 00:00:00 2001 From: Matt Webster Date: Wed, 10 Feb 2021 21:59:24 -0800 Subject: [PATCH] Enable filtering on /requests endpoint - Should default to last week's data if no limit provided - Can filter on date, council, and type Fixes #942 --- .../lacity_data_api/models/service_request.py | 59 +++++++++++-------- .../code/lacity_data_api/routers/reports.py | 1 + .../routers/service_requests.py | 31 +++++++--- .../tests/integration/test_api_requests.py | 37 +++++++++++- 4 files changed, 94 insertions(+), 34 deletions(-) diff --git a/server/api/code/lacity_data_api/models/service_request.py b/server/api/code/lacity_data_api/models/service_request.py index b95d60a0d..1f87509f8 100644 --- a/server/api/code/lacity_data_api/models/service_request.py +++ b/server/api/code/lacity_data_api/models/service_request.py @@ -1,13 +1,11 @@ import datetime from typing import List -from aiocache import cached, Cache, serializers -from sqlalchemy import sql, and_ +from aiocache import cached +from sqlalchemy import sql, and_, desc, text from . import db from .request_type import RequestType -from ..config import CACHE_ENDPOINT -from ..services import utilities class ServiceRequest(db.Model): @@ -55,6 +53,21 @@ async def get_request_reports( ) return result + @classmethod + @cached(alias="default") + async def get_recent_requests(cls, start_date: datetime.date): + + result = await ( + db.select( + ServiceRequest + ).where( + ServiceRequest.created_date >= start_date + ).order_by( + desc(ServiceRequest.created_date) + ).gino.all() + ) + return result + async def get_full_request(srnumber: str): # query the request table to get full record @@ -105,34 +118,28 @@ async def get_open_request_counts(): return result -@cached(cache=Cache.REDIS, - endpoint=CACHE_ENDPOINT, - namespace="filtered", - serializer=serializers.PickleSerializer(), - key_builder=utilities.cache_key - ) async def get_filtered_requests( start_date: datetime.date, - end_date: datetime.date, - type_ids: List[int], - council_ids: List[int] + end_date: datetime.date = None, + type_ids: List[int] = None, + council_ids: List[int] = None ): + + where_text = f"created_date >= '{start_date}'" + if (end_date): + where_text += f" AND created_date <= '{end_date}'" + if (type_ids): + where_text += f" AND type_id IN ({', '.join([str(i) for i in type_ids])})" + if (council_ids): + where_text += f" AND council_id IN ({', '.join([str(i) for i in council_ids])})" + result = await ( db.select( - [ - ServiceRequest.request_id, - ServiceRequest.srnumber, - ServiceRequest.type_id, - ServiceRequest.latitude, - ServiceRequest.longitude - ] + ServiceRequest ).where( - and_( - ServiceRequest.created_date >= start_date, - ServiceRequest.created_date <= end_date, - ServiceRequest.type_id.in_(type_ids), - ServiceRequest.council_id.in_(council_ids) - ) + text(where_text) + ).order_by( + desc(ServiceRequest.created_date) ).gino.all() ) return result diff --git a/server/api/code/lacity_data_api/routers/reports.py b/server/api/code/lacity_data_api/routers/reports.py index ada066ccf..01f07c3e7 100644 --- a/server/api/code/lacity_data_api/routers/reports.py +++ b/server/api/code/lacity_data_api/routers/reports.py @@ -30,6 +30,7 @@ filter_regex = "^(\w+)([>=<]+)([\w-]+)$" # noqa +# TODO: add created_dow option @router.get("") async def run_report( field: Optional[List[str]] = Query( diff --git a/server/api/code/lacity_data_api/routers/service_requests.py b/server/api/code/lacity_data_api/routers/service_requests.py index e53a4127a..e1a784895 100644 --- a/server/api/code/lacity_data_api/routers/service_requests.py +++ b/server/api/code/lacity_data_api/routers/service_requests.py @@ -1,3 +1,6 @@ +import datetime +from typing import Optional + from sqlalchemy import sql from fastapi import APIRouter @@ -7,18 +10,32 @@ from ..models.service_request import ( ServiceRequest, get_open_request_counts, get_open_requests, get_filtered_requests ) -from ..models import db router = APIRouter() +# TODO: #942 default to last week's data if no limit provided @router.get("", response_model=ServiceRequestList) -async def get_all_service_requests(skip: int = 0, limit: int = 100): - async with db.transaction(): - cursor = await ServiceRequest.query.gino.iterate() - if skip > 0: - await cursor.forward(skip) # skip 80 rows - result = await cursor.many(limit) # and retrieve next 10 rows +async def get_all_service_requests( + start_date: datetime.date = datetime.date.today() - datetime.timedelta(days=7), + end_date: datetime.date = None, + type_id: Optional[int] = None, + council_id: Optional[int] = None, +): + type_ids = [] + council_ids = [] + + if type_id: + type_ids = [type_id] + if council_id: + council_ids = [council_id] + + result = await get_filtered_requests( + start_date=start_date, + end_date=end_date, + type_ids=type_ids, + council_ids=council_ids + ) return result diff --git a/server/api/tests/integration/test_api_requests.py b/server/api/tests/integration/test_api_requests.py index 67b872de2..56681325e 100644 --- a/server/api/tests/integration/test_api_requests.py +++ b/server/api/tests/integration/test_api_requests.py @@ -3,7 +3,42 @@ def test_service_requests(client): url = "/requests" response = client.get(url) assert response.status_code == 200 - assert len(response.json()) == 100 + assert len(response.json()) == 0 + + +def test_service_requests_start(client): + url = "/requests?start_date=2020-01-01" + response = client.get(url) + assert response.status_code == 200 + assert len(response.json()) == 9877 + + +def test_service_requests_end(client): + url = "/requests?start_date=2020-01-01&end_date=2020-01-02" + response = client.get(url) + assert response.status_code == 200 + assert len(response.json()) == 7574 + + +def test_service_requests_type(client): + url = "/requests?start_date=2020-01-01&end_date=2020-01-02&type_id=2" + response = client.get(url) + assert response.status_code == 200 + assert len(response.json()) == 297 + + +def test_service_requests_council(client): + url = "/requests?start_date=2020-01-01&end_date=2020-01-02&council_id=4" + response = client.get(url) + assert response.status_code == 200 + assert len(response.json()) == 38 + + +def test_service_requests_all(client): + url = "/requests?start_date=2020-01-01&end_date=2020-01-02&type_id=2&council_id=4" + response = client.get(url) + assert response.status_code == 200 + assert len(response.json()) == 3 def test_service_request(client):