Skip to content

Commit

Permalink
Merge 0f04944 into c47a6fe
Browse files Browse the repository at this point in the history
  • Loading branch information
fredkingham committed Oct 4, 2018
2 parents c47a6fe + 0f04944 commit 7c2bffb
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 29 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
114 changes: 100 additions & 14 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.main_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 All @@ -396,7 +482,7 @@ def data_deltas(self, some_datetime):
if Demographics.objects.filter(
hospital_number=hospital_number
).exists():
demographics = list(rows)[0].get_demographics_dict()
demographics = rows[0].get_demographics_dict()
lab_tests = self.cast_rows_to_lab_test(rows)
yield (
dict(
Expand All @@ -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_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 VIEW_CRS_Patient_Masterfile 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.main_demographics("A1' 23")

self.assertIsNone(result)

def test_demographics_hospital_number_fail(self):
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("A1' 23")
result = api.demographics("123")

self.assertIsNone(result)

0 comments on commit 7c2bffb

Please sign in to comment.