Skip to content

Commit

Permalink
uses the old api to pull in the cerner demographics over the patholog…
Browse files Browse the repository at this point in the history
…y demographics refs #496
  • Loading branch information
fredkingham committed Oct 4, 2018
1 parent c47a6fe commit 534111a
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 28 deletions.
2 changes: 1 addition & 1 deletion apps/tb/migrations/0029_auto_20180815_1338.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class Migration(migrations.Migration):

dependencies = [
('opal', '0035_auto_20180806_1150'),
('opal', '0034_auto_20171214_1845'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('tb', '0028_pregnancy'),
]
Expand Down
112 changes: 99 additions & 13 deletions intrahospital_api/apis/prod_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
# if we fail in a query, the amount of seconds we wait before retrying
RETRY_DELAY = 30

MAIN_DEMOGRAPHICS_VIEW = "VIEW_CRS_Patient_Masterfile"

DEMOGRAPHICS_QUERY = "SELECT top(1) * FROM {view} WHERE Patient_Number = \
PATHOLOGY_DEMOGRAPHICS_QUERY = "SELECT top(1) * FROM {view} WHERE Patient_Number = \
@hospital_number ORDER BY last_updated DESC;"

MAIN_DEMOGRAPHICS_QUERY = "SELECT top(1) * FROM {view} WHERE Patient_Number = \
@hospital_number ORDER BY last_updated DESC;"

ALL_DATA_QUERY_FOR_HOSPITAL_NUMBER = "SELECT * FROM {view} WHERE Patient_Number = \
Expand Down Expand Up @@ -90,7 +94,61 @@ def wrap(*args, **kw):
return wrap


class Row(object):
class MainDemographicsRow(object):
DEMOGRAPHICS_FIELDS = [
"hospital_number",
"nhs_number",
"first_name",
"surname",
"date_of_birth",
"sex",
"ethnicity",
"title"
]

def __init__(self, db_row):
self.db_row = db_row

def get_hospital_number(self):
return self.db_row.get("PATIENT_NUMBER")

def get_nhs_number(self):
return self.db_row.get("NHS_NUMBER")

def get_first_name(self):
return self.db_row.get("FORENAME1")

def get_surname(self):
return self.db_row.get("SURNAME")

def get_date_of_birth(self):
dob = self.db_row.get("DOB")
if dob:
return to_date_str(dob.date())

def get_sex(self):
sex_abbreviation = self.db_row.get("SEX")

if sex_abbreviation:
if sex_abbreviation == "M":
return "Male"
else:
return "Female"

def get_ethnicity(self):
return ETHNICITY_MAPPING.get(self.db_row.get("ETHNIC_GROUP"))

def get_title(self):
return self.db_row.get("TITLE")

def get_demographics_dict(self):
result = {}
for field in self.DEMOGRAPHICS_FIELDS:
result[field] = getattr(self, "get_{}".format(field))()
return result


class PathologyRow(object):
""" a simple wrapper to get us the fields we actually want out of a row
"""
DEMOGRAPHICS_FIELDS = [
Expand Down Expand Up @@ -305,8 +363,8 @@ def execute_query(self, query, params=None):
return result

@property
def demographics_query(self):
return DEMOGRAPHICS_QUERY.format(view=self.view)
def pathology_demographics_query(self):
return PATHOLOGY_DEMOGRAPHICS_QUERY.format(view=self.view)

@property
def all_data_for_hospital_number_query(self):
Expand All @@ -324,20 +382,48 @@ def all_data_query_for_lab_number(self):
def all_data_query_for_lab_test_type(self):
return ALL_DATA_QUERY_WITH_LAB_TEST_TYPE.format(view=self.view)

@timing
@db_retry

@property
def main_demographics_query(self):
return MAIN_DEMOGRAPHICS_QUERY.format(view=MAIN_DEMOGRAPHICS_VIEW)

def demographics(self, hospital_number):
hospital_number = hospital_number.strip()

demographics_result = self.main_demographics(hospital_number)

if not demographics_result:
demographics_result = self.pathology_demographics(hospital_number)

if demographics_result:
demographics_result["external_system"] = EXTERNAL_SYSTEM
return demographics_result


@timing
@db_retry
def main_demographics(self, hospital_number):
rows = list(self.execute_query(
self.pathology_demographics_query,
params=dict(hospital_number=hospital_number)
))
if not len(rows):
return

return MainDemographicsRow(rows[0]).get_demographics_dict()


@timing
@db_retry
def pathology_demographics(self, hospital_number):
rows = list(self.execute_query(
self.demographics_query,
self.pathology_demographics_query,
params=dict(hospital_number=hospital_number)
))
if not len(rows):
return

demographics_dict = Row(rows[0]).get_demographics_dict()
demographics_dict["external_system"] = EXTERNAL_SYSTEM
return demographics_dict
return PathologyRow(rows[0]).get_demographics_dict()

def raw_data(self, hospital_number, lab_number=None, test_type=None):
""" not all data, I lied. Only the last year's
Expand Down Expand Up @@ -375,7 +461,7 @@ def data_delta_query(self, since):
self.all_data_since_query,
params=dict(since=since)
)
return (Row(r) for r in all_rows)
return (PathologyRow(r) for r in all_rows)

def data_deltas(self, some_datetime):
""" yields an iterator of dictionary
Expand Down Expand Up @@ -407,7 +493,7 @@ def data_deltas(self, some_datetime):

def cooked_data(self, hospital_number):
raw_data = self.raw_data(hospital_number)
return (Row(row).get_all_fields() for row in raw_data)
return (PathologyRow(row).get_all_fields() for row in raw_data)

def cast_rows_to_lab_test(self, rows):
""" We cast multiple rows to lab tests.
Expand Down Expand Up @@ -453,5 +539,5 @@ def results_for_hospital_number(self, hospital_number):
"""

raw_rows = self.raw_data(hospital_number)
rows = (Row(raw_row) for raw_row in raw_rows)
rows = (PathologyRow(raw_row) for raw_row in raw_rows)
return self.cast_rows_to_lab_test(rows)
119 changes: 105 additions & 14 deletions intrahospital_api/test/test_prod_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
from datetime import datetime, date
from opal.core.test import OpalTestCase
from intrahospital_api.apis import prod_api
from intrahospital_api import constants
from lab import models as lmodels


FAKE_ROW_DATA = {
FAKE_PATHOLOGY_DATA = {
u'Abnormal_Flag': u'',
u'Accession_number': u'73151060487',
u'CRS_ADDRESS_LINE1': u'James Centre',
Expand Down Expand Up @@ -149,11 +150,11 @@ def tests_reraises(self, time):
)


class RowTestCase(OpalTestCase):
class PathologyRowTestCase(OpalTestCase):
def get_row(self, **kwargs):
raw_data = copy.copy(FAKE_ROW_DATA)
raw_data = copy.copy(FAKE_PATHOLOGY_DATA)
raw_data.update(kwargs)
return prod_api.Row(raw_data)
return prod_api.PathologyRow(raw_data)

def test_get_or_fall_back_hit_first(self):
row = self.get_row(Department="something")
Expand Down Expand Up @@ -377,6 +378,18 @@ def test_get_all_fields(self):
self.assertEqual(result, expected)


FAKE_MAIN_DEMOGRAPHICS_ROW = {
u'PATIENT_NUMBER': u'20552710',
u'NHS_NUMBER': u'111',
u'FORENAME1': u'TEST',
u'SURNAME': u'ZZZTEST',
u'DOB': datetime(1980, 10, 10, 0, 0),
u'SEX': u'F',
u'ETHNIC_GROUP': u'D',
u'TITLE': u'Ms',
}


class ProdApiTestcase(OpalTestCase):
REQUIRED_FIELDS = dict(
ip_address="0.0.0.0",
Expand Down Expand Up @@ -447,9 +460,9 @@ def test_execute_query_without_params(self, pytds):
def test_raw_data(self, dt):
dt.today.return_value = date(2017, 10, 1)
api = self.get_api()
expected = [copy.copy(FAKE_ROW_DATA)]
expected = [copy.copy(FAKE_PATHOLOGY_DATA)]
with mock.patch.object(api, 'execute_query') as execute_query:
execute_query.return_value = [copy.copy(FAKE_ROW_DATA)]
execute_query.return_value = [copy.copy(FAKE_PATHOLOGY_DATA)]
result = api.raw_data("12312222")
self.assertEqual(result, expected)

Expand All @@ -469,15 +482,15 @@ def test_raw_data(self, dt):
def test_cooked_data(self):
api = self.get_api()
with mock.patch.object(api, "raw_data") as raw_data:
raw_data.return_value = [copy.copy(FAKE_ROW_DATA)]
raw_data.return_value = [copy.copy(FAKE_PATHOLOGY_DATA)]
rows = api.cooked_data("123")
self.assertEqual(len(list(rows)), 1)

def test_demographics_success(self):
def test_pathology_demographics_success(self):
api = self.get_api()
with mock.patch.object(api, "execute_query") as execute_query:
execute_query.return_value = [FAKE_ROW_DATA]
result = api.demographics("123")
execute_query.return_value = [FAKE_PATHOLOGY_DATA]
result = api.pathology_demographics("123")

self.assertEqual(
result["first_name"], "TEST"
Expand All @@ -492,18 +505,96 @@ def test_demographics_success(self):
execute_query.call_args[1]["params"], dict(hospital_number="123")
)

def test_empty_demographics(self):
def test_pathology_demographics_hospital_number_fail(self):
api = self.get_api()
with mock.patch.object(api, "execute_query") as execute_query:
execute_query.return_value = []
result = api.demographics("123")
result = api.pathology_demographics("A1' 23")

self.assertIsNone(result)

def test_demographics_hospital_number_fail(self):
def test_main_demographics_success(self):
api = self.get_api()
with mock.patch.object(api, "execute_query") as execute_query:
execute_query.return_value = [FAKE_MAIN_DEMOGRAPHICS_ROW]
result = api.main_demographics("123")

self.assertEqual(
result["first_name"], "TEST"
)

self.assertEqual(
result["surname"], "ZZZTEST"
)
self.assertEqual(
result["hospital_number"], "20552710"
)
self.assertEqual(
result["date_of_birth"], "10/10/1980"
)
self.assertEqual(
result["sex"], "Female"
)
self.assertEqual(
result["title"], "Ms"
)
self.assertEqual(
result["ethnicity"], "Mixed - White and Black Caribbean"
)

expected_query = "SELECT top(1) * FROM some_view WHERE Patient_Number \
= @hospital_number ORDER BY last_updated DESC;"
self.assertEqual(
execute_query.call_args[0][0], expected_query
)
self.assertEqual(
execute_query.call_args[1]["params"], dict(hospital_number="123")
)

def test_main_demographics_fail(self):
api = self.get_api()
with mock.patch.object(api, "execute_query") as execute_query:
execute_query.return_value = []
result = api.demographics("A1' 23")
result = api.main_demographics("A1' 23")

self.assertIsNone(result)

def test_demographics_found_in_main(self):
api = self.get_api()
with mock.patch.object(api, "main_demographics") as main_demographics:
with mock.patch.object(api, "pathology_demographics") as pathology_demographics:
main_demographics.return_value = dict(first_name="Wilma")
result = api.demographics("111")

self.assertEqual(
result,
dict(first_name="Wilma", external_system=constants.EXTERNAL_SYSTEM)
)

main_demographics.assert_called_once_with("111")
self.assertFalse(pathology_demographics.called)

def test_demographics_found_in_pathology(self):
api = self.get_api()
with mock.patch.object(api, "main_demographics") as main_demographics:
with mock.patch.object(api, "pathology_demographics") as pathology_demographics:
main_demographics.return_value = None
pathology_demographics.return_value = dict(first_name="Wilma")
result = api.demographics("111")

self.assertEqual(
result,
dict(first_name="Wilma", external_system=constants.EXTERNAL_SYSTEM)
)

main_demographics.assert_called_once_with("111")
pathology_demographics.assert_called_once_with("111")

def test_demographics_not_found_in_either(self):
api = self.get_api()

with mock.patch.object(api, "execute_query") as execute_query:
execute_query.return_value = []
result = api.demographics("123")

self.assertIsNone(result)

0 comments on commit 534111a

Please sign in to comment.