From ecabc8e77f7e56e129132485cb2c4f7b6c1cafd3 Mon Sep 17 00:00:00 2001
From: pcain-usgs <pcain@usgs.gov>
Date: Mon, 10 May 2021 14:35:54 -0600
Subject: [PATCH 1/2] get metadata history from query parameters

---
 geomagio/api/db/MetadataDatabaseFactory.py | 59 ++++++++++++++++++----
 geomagio/api/secure/metadata.py            | 49 +++++++++++-------
 2 files changed, 79 insertions(+), 29 deletions(-)

diff --git a/geomagio/api/db/MetadataDatabaseFactory.py b/geomagio/api/db/MetadataDatabaseFactory.py
index e97afd77..b9fa85cc 100644
--- a/geomagio/api/db/MetadataDatabaseFactory.py
+++ b/geomagio/api/db/MetadataDatabaseFactory.py
@@ -3,7 +3,7 @@ from typing import List, Optional
 
 from databases import Database
 from obspy import UTCDateTime
-from sqlalchemy import or_
+from sqlalchemy import or_, Table
 
 from ...metadata import Metadata, MetadataCategory
 from .metadata_history_table import metadata_history
@@ -36,9 +36,10 @@ class MetadataDatabaseFactory(object):
         created_after: datetime = None,
         created_before: datetime = None,
         data_valid: bool = None,
+        metadata: Table = metadata,
         metadata_valid: bool = None,
         status: List[str] = None,
-    ):
+    ) -> List[Metadata]:
         query = metadata.select()
         if id:
             query = query.where(metadata.c.id == id)
@@ -85,7 +86,51 @@ class MetadataDatabaseFactory(object):
             raise ValueError(f"{len(meta)} records found")
         return meta[0]
 
-    async def get_metadata_history(self, metadata_id: int) -> List[Metadata]:
+    async def get_metadata_history(
+        self,
+        *,  # make all params keyword
+        id: int = None,
+        network: str = None,
+        station: str = None,
+        channel: str = None,
+        location: str = None,
+        category: MetadataCategory = None,
+        starttime: datetime = None,
+        endtime: datetime = None,
+        created_after: datetime = None,
+        created_before: datetime = None,
+        data_valid: bool = None,
+        metadata_valid: bool = None,
+        status: List[str] = None,
+    ) -> List[Metadata]:
+        return await self.get_metadata(
+            id=id,
+            network=network,
+            station=station,
+            channel=channel,
+            location=location,
+            category=category,
+            starttime=starttime,
+            endtime=endtime,
+            created_after=created_after,
+            created_before=created_before,
+            data_valid=data_valid,
+            metadata=metadata_history,
+            metadata_valid=metadata_valid,
+            status=status,
+        )
+
+    async def get_metadata_history_by_id(self, id: int) -> Optional[Metadata]:
+        query = metadata_history.select()
+        query = query.where(metadata_history.c.id == id)
+        meta = await self.database.fetch_one(query)
+        if meta is None:
+            return meta
+        return Metadata(**meta)
+
+    async def get_metadata_history_by_metadata_id(
+        self, metadata_id: int
+    ) -> List[Metadata]:
         async with self.database.transaction() as transaction:
             query = metadata_history.select()
             query = query.where(metadata_history.c.metadata_id == metadata_id).order_by(
@@ -99,14 +144,6 @@ class MetadataDatabaseFactory(object):
             metadata.reverse()
             return metadata
 
-    async def get_metadata_history_by_id(self, id: int) -> Optional[Metadata]:
-        query = metadata_history.select()
-        query = query.where(metadata_history.c.id == id)
-        meta = await self.database.fetch_one(query)
-        if meta is None:
-            return meta
-        return Metadata(**meta)
-
     async def update_metadata(self, meta: Metadata, updated_by: str) -> Metadata:
         async with self.database.transaction() as transaction:
             # write current record to metadata history table
diff --git a/geomagio/api/secure/metadata.py b/geomagio/api/secure/metadata.py
index a2015abc..4821c83b 100644
--- a/geomagio/api/secure/metadata.py
+++ b/geomagio/api/secure/metadata.py
@@ -29,20 +29,7 @@ from .login import require_user, User
 router = APIRouter()
 
 
-@router.post("/metadata", response_model=Metadata)
-async def create_metadata(
-    request: Request,
-    metadata: Metadata,
-    user: User = Depends(require_user()),
-):
-    metadata = await MetadataDatabaseFactory(database=database).create_metadata(
-        meta=metadata
-    )
-    return Response(metadata.json(), status_code=201, media_type="application/json")
-
-
-@router.get("/metadata", response_model=List[Metadata])
-async def get_metadata(
+def get_metadata_query(
     category: MetadataCategory = None,
     starttime: UTCDateTime = None,
     endtime: UTCDateTime = None,
@@ -55,8 +42,8 @@ async def get_metadata(
     data_valid: bool = None,
     metadata_valid: bool = True,
     status: List[str] = Query(None),
-):
-    query = MetadataQuery(
+) -> MetadataQuery:
+    return MetadataQuery(
         category=category,
         starttime=starttime,
         endtime=endtime,
@@ -70,22 +57,48 @@ async def get_metadata(
         metadata_valid=metadata_valid,
         status=status,
     )
+
+
+@router.post("/metadata", response_model=Metadata)
+async def create_metadata(
+    request: Request,
+    metadata: Metadata,
+    user: User = Depends(require_user()),
+):
+    metadata = await MetadataDatabaseFactory(database=database).create_metadata(
+        meta=metadata
+    )
+    return Response(metadata.json(), status_code=201, media_type="application/json")
+
+
+@router.get("/metadata", response_model=List[Metadata])
+async def get_metadata(query: MetadataQuery = Depends(get_metadata_query)):
     metas = await MetadataDatabaseFactory(database=database).get_metadata(
         **query.datetime_dict(exclude={"id", "metadata_id"})
     )
     return metas
 
 
+@router.get("/metadata/history", response_model=List[Metadata])
+async def get_metadata_history(query: MetadataQuery = Depends(get_metadata_query)):
+    metas = await MetadataDatabaseFactory(database=database).get_metadata_history(
+        **query.datetime_dict(exclude={"id", "metadata_id"})
+    )
+    return metas
+
+
 @router.get("/metadata/{id}", response_model=Metadata)
 async def get_metadata_by_id(id: int):
     return await MetadataDatabaseFactory(database=database).get_metadata_by_id(id=id)
 
 
 @router.get("/metadata/{metadata_id}/history", response_model=List[Metadata])
-async def get_metadata_history(
+async def get_metadata_history_by_metadata_id(
     metadata_id: int,
 ):
-    return await MetadataDatabaseFactory(database=database).get_metadata_history(
+    return await MetadataDatabaseFactory(
+        database=database
+    ).get_metadata_history_by_metadata_id(
         metadata_id=metadata_id,
     )
 
-- 
GitLab


From f027a1eeba3e18ef78499a31c5f010d8c9b7e7e3 Mon Sep 17 00:00:00 2001
From: pcain-usgs <pcain@usgs.gov>
Date: Mon, 17 May 2021 16:28:57 -0600
Subject: [PATCH 2/2] create history boolean flag, get metadata from query

---
 geomagio/api/db/MetadataDatabaseFactory.py | 107 ++++++++-------------
 geomagio/api/secure/metadata.py            |   8 +-
 2 files changed, 42 insertions(+), 73 deletions(-)

diff --git a/geomagio/api/db/MetadataDatabaseFactory.py b/geomagio/api/db/MetadataDatabaseFactory.py
index b9fa85cc..c7676bc7 100644
--- a/geomagio/api/db/MetadataDatabaseFactory.py
+++ b/geomagio/api/db/MetadataDatabaseFactory.py
@@ -3,9 +3,9 @@ from typing import List, Optional
 
 from databases import Database
 from obspy import UTCDateTime
-from sqlalchemy import or_, Table
+from sqlalchemy import or_
 
-from ...metadata import Metadata, MetadataCategory
+from ...metadata import Metadata, MetadataQuery
 from .metadata_history_table import metadata_history
 from .metadata_table import metadata
 
@@ -24,102 +24,73 @@ class MetadataDatabaseFactory(object):
 
     async def get_metadata(
         self,
-        *,  # make all params keyword
-        id: int = None,
-        network: str = None,
-        station: str = None,
-        channel: str = None,
-        location: str = None,
-        category: MetadataCategory = None,
-        starttime: datetime = None,
-        endtime: datetime = None,
-        created_after: datetime = None,
-        created_before: datetime = None,
-        data_valid: bool = None,
-        metadata: Table = metadata,
-        metadata_valid: bool = None,
-        status: List[str] = None,
+        params: MetadataQuery,
+        history: bool = False,
     ) -> List[Metadata]:
-        query = metadata.select()
+        table = metadata
+        if history:
+            table = metadata_history
+        query = table.select()
+        (
+            id,
+            category,
+            network,
+            station,
+            channel,
+            location,
+            starttime,
+            endtime,
+            created_after,
+            created_before,
+            data_valid,
+            metadata_valid,
+            status,
+        ) = params.dict().values()
         if id:
-            query = query.where(metadata.c.id == id)
+            query = query.where(table.c.id == id)
         if category:
-            query = query.where(metadata.c.category == category)
+            query = query.where(table.c.category == category)
         if network:
-            query = query.where(metadata.c.network == network)
+            query = query.where(table.c.network == network)
         if station:
-            query = query.where(metadata.c.station == station)
+            query = query.where(table.c.station == station)
         if channel:
-            query = query.where(metadata.c.channel.like(channel))
+            query = query.where(table.c.channel.like(channel))
         if location:
-            query = query.where(metadata.c.location.like(location))
+            query = query.where(table.c.location.like(location))
         if starttime:
             query = query.where(
                 or_(
-                    metadata.c.endtime == None,
-                    metadata.c.endtime > starttime,
+                    table.c.endtime == None,
+                    table.c.endtime > starttime,
                 )
             )
         if endtime:
             query = query.where(
                 or_(
-                    metadata.c.starttime == None,
-                    metadata.c.starttime < endtime,
+                    table.c.starttime == None,
+                    table.c.starttime < endtime,
                 )
             )
         if created_after:
-            query = query.where(metadata.c.created_time > created_after)
+            query = query.where(table.c.created_time > created_after)
         if created_before:
-            query = query.where(metadata.c.created_time < created_before)
+            query = query.where(table.c.created_time < created_before)
         if data_valid is not None:
-            query = query.where(metadata.c.data_valid == data_valid)
+            query = query.where(table.c.data_valid == data_valid)
         if metadata_valid is not None:
-            query = query.where(metadata.c.metadata_valid == metadata_valid)
+            query = query.where(table.c.metadata_valid == metadata_valid)
         if status is not None:
-            query = query.where(metadata.c.status.in_(status))
+            query = query.where(table.c.status.in_(status))
         rows = await self.database.fetch_all(query)
         return [Metadata(**row) for row in rows]
 
     async def get_metadata_by_id(self, id: int):
-        meta = await self.get_metadata(id=id)
+        meta = await self.get_metadata(MetadataQuery(id=id))
         if len(meta) != 1:
             raise ValueError(f"{len(meta)} records found")
         return meta[0]
 
-    async def get_metadata_history(
-        self,
-        *,  # make all params keyword
-        id: int = None,
-        network: str = None,
-        station: str = None,
-        channel: str = None,
-        location: str = None,
-        category: MetadataCategory = None,
-        starttime: datetime = None,
-        endtime: datetime = None,
-        created_after: datetime = None,
-        created_before: datetime = None,
-        data_valid: bool = None,
-        metadata_valid: bool = None,
-        status: List[str] = None,
-    ) -> List[Metadata]:
-        return await self.get_metadata(
-            id=id,
-            network=network,
-            station=station,
-            channel=channel,
-            location=location,
-            category=category,
-            starttime=starttime,
-            endtime=endtime,
-            created_after=created_after,
-            created_before=created_before,
-            data_valid=data_valid,
-            metadata=metadata_history,
-            metadata_valid=metadata_valid,
-            status=status,
-        )
-
     async def get_metadata_history_by_id(self, id: int) -> Optional[Metadata]:
         query = metadata_history.select()
         query = query.where(metadata_history.c.id == id)
diff --git a/geomagio/api/secure/metadata.py b/geomagio/api/secure/metadata.py
index 4821c83b..755948d1 100644
--- a/geomagio/api/secure/metadata.py
+++ b/geomagio/api/secure/metadata.py
@@ -73,16 +73,14 @@ async def create_metadata(
 
 @router.get("/metadata", response_model=List[Metadata])
 async def get_metadata(query: MetadataQuery = Depends(get_metadata_query)):
-    metas = await MetadataDatabaseFactory(database=database).get_metadata(
-        **query.datetime_dict(exclude={"id", "metadata_id"})
-    )
+    metas = await MetadataDatabaseFactory(database=database).get_metadata(params=query)
     return metas
 
 
 @router.get("/metadata/history", response_model=List[Metadata])
 async def get_metadata_history(query: MetadataQuery = Depends(get_metadata_query)):
-    metas = await MetadataDatabaseFactory(database=database).get_metadata_history(
-        **query.datetime_dict(exclude={"id", "metadata_id"})
+    metas = await MetadataDatabaseFactory(database=database).get_metadata(
+        params=query, history=True
     )
     return metas
 
-- 
GitLab