Skip to content

Commit

Permalink
Merge pull request #277 from biocore/st_dh_query_email_stats
Browse files Browse the repository at this point in the history
Account Summaries Backend
  • Loading branch information
wasade committed Nov 16, 2020
2 parents 26276c1 + c6e1553 commit 3dacfb0
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 0 deletions.
74 changes: 74 additions & 0 deletions microsetta_private_api/admin/admin_impl.py
@@ -1,4 +1,6 @@
import uuid
from collections import defaultdict

from flask import jsonify, Response

from microsetta_private_api.config_manager import SERVER_CONFIG
Expand All @@ -7,6 +9,9 @@
from microsetta_private_api.exceptions import RepoException
from microsetta_private_api.repo.account_repo import AccountRepo
from microsetta_private_api.repo.event_log_repo import EventLogRepo
from microsetta_private_api.repo.kit_repo import KitRepo
from microsetta_private_api.repo.sample_repo import SampleRepo
from microsetta_private_api.repo.source_repo import SourceRepo
from microsetta_private_api.repo.transaction import Transaction
from microsetta_private_api.repo.admin_repo import AdminRepo
from microsetta_private_api.repo.metadata_repo import (retrieve_metadata,
Expand Down Expand Up @@ -297,3 +302,72 @@ def get_daklapack_articles(token_info):
admin_repo = AdminRepo(t)
dak_article_dicts = admin_repo.get_daklapack_articles()
return jsonify(dak_article_dicts), 200


def query_email_stats(body, token_info):
validate_admin_access(token_info)

email_list = body.get("emails", [])
project = body.get("project")

results = []
with Transaction() as t:
account_repo = AccountRepo(t)
kit_repo = KitRepo(t)
source_repo = SourceRepo(t)
sample_repo = SampleRepo(t)

for email in email_list:
result = {'email': email, 'project': project}
results.append(result)
# can use internal lookup by email, because we have admin access
account = account_repo._find_account_by_email(email) # noqa
if account is None:
result['summary'] = "No Account"
continue
else:
result['account_id'] = account.id
result['creation_time'] = account.creation_time
result['kit_name'] = account.created_with_kit_id

if account.created_with_kit_id is not None:
unused = kit_repo.get_kit_unused_samples(
account.created_with_kit_id
)
if unused is None:
result['unclaimed-samples-in-kit'] = 0
else:
result['unclaimed-samples-in-kit'] = len(unused.samples)

sample_statuses = defaultdict(int)
sources = source_repo.get_sources_in_account(account.id)

samples_in_project = 0
for source in sources:
samples = sample_repo.get_samples_by_source(account.id,
source.id)
for sample in samples:
if project is not None and \
project != "" and \
project not in sample.sample_projects:
continue
samples_in_project += 1
sample_status = sample_repo.get_sample_status(
sample.barcode,
sample._latest_scan_timestamp # noqa
)
if sample_status is None:
sample_status = "never-scanned"
sample_statuses[sample_status] += 1
result.update(sample_statuses)

if result.get('unclaimed-samples-in-kit', 0) > 0:
result['summary'] = 'Possible Unreturned Samples'
elif samples_in_project == 0:
result['summary'] = "No Samples In Specified Project"
elif result.get('sample-is-valid') == samples_in_project:
result['summary'] = 'All Samples Valid'
else:
result['summary'] = 'May Require User Interaction'

return jsonify(results), 200
28 changes: 28 additions & 0 deletions microsetta_private_api/admin/tests/test_admin_api.py
Expand Up @@ -716,6 +716,34 @@ def test_get_daklapack_articles(self):
self.assertEqual(len(article_dicts_list), len(response_obj))
self.assertEqual(FIRST_DAKLAPACK_ARTICLE, response_obj[0])

def test_email_stats(self):
with Transaction() as t:
accts = AccountRepo(t)
acct1 = accts.get_account("65dcd6c8-69fa-4de8-a33a-3de4957a0c79")
acct2 = accts.get_account("556f5dc4-8cf2-49ae-876c-32fbdfb005dd")

# execute articles get
for project in [None, "American Gut Project", "NotAProj"]:
response = self.client.post(
"/api/admin/account_email_summary",
headers=MOCK_HEADERS,
content_type='application/json',
data=json.dumps({
"emails": [acct1.email, acct2.email],
"project": project
})
)
self.assertEqual(200, response.status_code)
result = json.loads(response.data)
self.assertEqual(result[0]["account_id"],
"65dcd6c8-69fa-4de8-a33a-3de4957a0c79")
self.assertEqual(result[1]["account_id"],
"556f5dc4-8cf2-49ae-876c-32fbdfb005dd")
if project is None or project == "American Gut Project":
self.assertEqual(result[0]["sample-is-valid"], 1)
else:
self.assertEqual(result[0].get("sample-is-valid", 0), 0)

def test_metadata_qiita_compatible_invalid(self):
data = json.dumps({'sample_barcodes': ['bad']})
response = self.client.post('/api/admin/metadata/qiita-compatible',
Expand Down
27 changes: 27 additions & 0 deletions microsetta_private_api/api/microsetta_private_api.yaml
Expand Up @@ -1358,6 +1358,33 @@ paths:
schema:
type: array

'/admin/account_email_summary':
post:
operationId: microsetta_private_api.admin.admin_impl.query_email_stats
tags:
- Admin
requestBody:
content:
application/json:
schema:
type: object
properties:
# issue type defines what resolution_url the user should go to
emails:
type: array
items:
$ref: '#/components/schemas/email'
project:
type: string
nullable: true
responses:
'200':
description: Return list of dictionaries of sample status for requested accounts
content:
application/json:
schema:
type: array

components:
parameters:
# path parameters
Expand Down
15 changes: 15 additions & 0 deletions microsetta_private_api/repo/sample_repo.py
Expand Up @@ -228,3 +228,18 @@ def dissociate_sample(self, account_id, source_id, sample_id,
# And detach the sample from the source
self._update_sample_association(sample_id, None,
override_locked=override_locked)

def get_sample_status(self, sample_barcode, scan_timestamp):
with self._transaction.cursor() as cur:
cur.execute(
"SELECT "
"sample_status "
"FROM barcodes.barcode_scans "
"WHERE barcode=%s AND scan_timestamp = %s "
"LIMIT 1",
(sample_barcode, scan_timestamp)
)
row = cur.fetchone()
if row is None:
return None
return row[0]

0 comments on commit 3dacfb0

Please sign in to comment.