class MetricsEhrServiceTest(SqlTestBase): def setUp(self, with_data=True, use_mysql=True): super(MetricsEhrServiceTest, self).setUp(with_data=with_data, use_mysql=use_mysql) self.service = MetricsEhrService() self.hpo_dao = HPODao() self.org_dao = OrganizationDao() self.hpo_foo = self._make_hpo(hpoId=10, name='FOO', displayName='Foo') self.hpo_bar = self._make_hpo(hpoId=11, name='BAR', displayName='Bar') self.org_foo_a = self._make_org( organizationId=10, externalId='FOO_A', displayName='Foo A', hpoId=self.hpo_foo.hpoId ) self.org_bar_a = self._make_org( organizationId=11, externalId='BAR_A', displayName='Bar A', hpoId=self.hpo_bar.hpoId ) self.org_bar_b = self._make_org( organizationId=12, externalId='BAR_B', displayName='Bar B', hpoId=self.hpo_bar.hpoId ) def _make_hpo(self, **kwargs): hpo = HPO(**kwargs) self.hpo_dao.insert(hpo) return hpo def _make_org(self, **kwargs): org = Organization(**kwargs) self.org_dao.insert(org) return org def test_get_organization_ids_from_hpo_ids(self): self.assertEqual( self.service._get_organization_ids_from_hpo_ids([self.hpo_foo.hpoId]), [self.org_foo_a.organizationId] ) self.assertEqual( self.service._get_organization_ids_from_hpo_ids([self.hpo_bar.hpoId]), [ self.org_bar_a.organizationId, self.org_bar_b.organizationId, ] ) self.assertEqual( self.service._get_organization_ids_from_hpo_ids([self.hpo_foo.hpoId, self.hpo_bar.hpoId]), [ self.org_foo_a.organizationId, self.org_bar_a.organizationId, self.org_bar_b.organizationId, ] )
def _setup_hpos(self): hpo_dao = HPODao() hpo_dao.insert(HPO(hpoId=UNSET_HPO_ID, name='UNSET')) hpo_dao.insert( HPO(hpoId=PITT_HPO_ID, name='PITT', organizationType=OrganizationType.HPO)) self.hpo_id = PITT_HPO_ID site_dao = SiteDao() created_site = site_dao.insert( Site(siteName='Monroeville Urgent Care Center', googleGroup='hpo-site-monroeville', consortiumName='Pittsburgh', mayolinkClientNumber=7035769, hpoId=PITT_HPO_ID)) self.site_id = created_site.siteId site_dao.insert( Site(siteName='Phoenix Urgent Care Center', googleGroup='hpo-site-bannerphoenix', consortiumName='Pittsburgh', mayolinkClientNumber=7035770, hpoId=PITT_HPO_ID))
def _setup_hpos(self, org_dao=None): hpo_dao = HPODao() hpo_dao.insert( HPO(hpoId=UNSET_HPO_ID, name='UNSET', displayName='Unset', organizationType=OrganizationType.UNSET)) hpo_dao.insert( HPO(hpoId=PITT_HPO_ID, name='PITT', displayName='Pittsburgh', organizationType=OrganizationType.HPO)) hpo_dao.insert( HPO(hpoId=AZ_HPO_ID, name='AZ_TUCSON', displayName='Arizona', organizationType=OrganizationType.HPO)) self.hpo_id = PITT_HPO_ID org_dao = OrganizationDao() org_dao.insert( Organization(organizationId=AZ_ORG_ID, externalId='AZ_TUCSON_BANNER_HEALTH', displayName='Banner Health', hpoId=AZ_HPO_ID)) created_org = org_dao.insert( Organization(organizationId=PITT_ORG_ID, externalId='PITT_BANNER_HEALTH', displayName='PITT display Banner Health', hpoId=PITT_HPO_ID)) self.organization_id = created_org.organizationId site_dao = SiteDao() created_site = site_dao.insert( Site(siteName='Monroeville Urgent Care Center', googleGroup='hpo-site-monroeville', mayolinkClientNumber=7035769, organizationId=PITT_ORG_ID, hpoId=PITT_HPO_ID)) self.site_id = created_site.siteId site_dao.insert( Site(siteName='Phoenix Urgent Care Center', googleGroup='hpo-site-bannerphoenix', mayolinkClientNumber=7035770, organizationId=PITT_ORG_ID, hpoId=PITT_HPO_ID)) site_dao.insert( Site(siteName='Phoenix clinic', googleGroup='hpo-site-clinic-phoenix', mayolinkClientNumber=7035770, organizationId=AZ_ORG_ID, hpoId=AZ_HPO_ID))
def setUp(self): super(AwardeeApiTest, self).setUp(with_data=False) hpo_dao = HPODao() hpo_dao.insert( HPO(hpoId=UNSET_HPO_ID, name='UNSET', displayName='Unset', organizationType=OrganizationType.UNSET)) hpo_dao.insert( HPO(hpoId=PITT_HPO_ID, name='PITT', displayName='Pittsburgh', organizationType=OrganizationType.HPO)) hpo_dao.insert( HPO(hpoId=AZ_HPO_ID, name='AZ_TUCSON', displayName='Arizona', organizationType=OrganizationType.HPO))
def setUp(self): super(HierarchyContentApiTest, self).setUp(with_data=False) hpo_dao = HPODao() hpo_dao.insert( HPO(hpoId=UNSET_HPO_ID, name='UNSET', displayName='Unset', organizationType=OrganizationType.UNSET, resourceId='h123456')) hpo_dao.insert( HPO(hpoId=PITT_HPO_ID, name='PITT', displayName='Pittsburgh', organizationType=OrganizationType.HPO, resourceId='h123457')) hpo_dao.insert( HPO(hpoId=AZ_HPO_ID, name='AZ_TUCSON', displayName='Arizona', organizationType=OrganizationType.HPO, resourceId='h123458')) self.site_dao = SiteDao() self.org_dao = OrganizationDao()
class ParticipantApiTest(FlaskTestBase): def setUp(self): super(ParticipantApiTest, self).setUp() provider_link = { "primary": False, "organization": { "reference": "columbia" } } self.participant = {'providerLink': [provider_link]} self.participant_2 = {'externalId': 12345} self.provider_link_2 = { "primary": True, "organization": { "reference": "Organization/PITT", } } # Needed by test_switch_to_test_account self.hpo_dao = HPODao() self.hpo_dao.insert( HPO(hpoId=TEST_HPO_ID, name=TEST_HPO_NAME, displayName='Test', organizationType=OrganizationType.UNSET)) def test_insert(self): response = self.send_post('Participant', self.participant) participant_id = response['participantId'] get_response = self.send_get('Participant/%s' % participant_id) self.assertEquals(response, get_response) biobank_id = response['biobankId'] self.assertTrue(biobank_id.startswith('Z')) self.assertEquals(str(WithdrawalStatus.NOT_WITHDRAWN), response['withdrawalStatus']) self.assertEquals(str(SuspensionStatus.NOT_SUSPENDED), response['suspensionStatus']) for auto_generated in ('participantId', 'externalId', 'site', 'organization', 'awardee', 'hpoId', 'biobankId', 'signUpTime', 'lastModified', 'withdrawalStatus', 'withdrawalReason', 'withdrawalReasonJustification', 'suspensionStatus'): del response[auto_generated] self.assertJsonResponseMatches(self.participant, response) def test_insert_with_same_external_id_fails(self): response = self.send_post('Participant', self.participant_2) participant_id = response['participantId'] get_response = self.send_get('Participant/%s' % participant_id) self.assertEqual(get_response['externalId'], self.participant_2['externalId']) self.assertEquals(response, get_response) response_2 = self.send_post('Participant', self.participant_2) self.assertEqual(response, response_2) def test_update_no_ifmatch_specified(self): response = self.send_post('Participant', self.participant) # Change the provider link for the participant participant_id = response['participantId'] response['providerLink'] = [self.provider_link_2] path = 'Participant/%s' % participant_id self.send_put(path, response, expected_status=httplib.BAD_REQUEST) def test_update_bad_ifmatch_specified(self): response = self.send_post('Participant', self.participant) # Change the provider link for the participant participant_id = response['participantId'] response['providerLink'] = [self.provider_link_2] path = 'Participant/%s' % participant_id self.send_put(path, response, headers={'If-Match': 'Blah'}, expected_status=httplib.BAD_REQUEST) def test_update_wrong_ifmatch_specified(self): response = self.send_post('Participant', self.participant) # Change the provider link for the participant participant_id = response['participantId'] response['providerLink'] = [self.provider_link_2] path = 'Participant/%s' % participant_id self.send_put(path, response, headers={'If-Match': 'W/"123"'}, expected_status=httplib.PRECONDITION_FAILED) def test_update_right_ifmatch_specified(self): response = self.send_post('Participant', self.participant) self.assertEquals('W/"1"', response['meta']['versionId']) # Change the provider link for the participant participant_id = response['participantId'] response['providerLink'] = [self.provider_link_2] response['withdrawalStatus'] = 'NO_USE' response['suspensionStatus'] = 'NO_CONTACT' response['site'] = 'UNSET' response['organization'] = 'UNSET' response['awardee'] = 'PITT' response['hpoId'] = 'PITT' path = 'Participant/%s' % participant_id update_response = self.send_put(path, response, headers={'If-Match': 'W/"1"'}) response['meta']['versionId'] = 'W/"2"' response['withdrawalTime'] = update_response['lastModified'] response['suspensionTime'] = update_response['lastModified'] self.assertJsonResponseMatches(response, update_response) def test_change_pairing_awardee_and_site(self): participant = self.send_post('Participant', self.participant) participant['providerLink'] = [self.provider_link_2] participant_id = participant['participantId'] participant['awardee'] = 'PITT' participant['site'] = 'hpo-site-monroeville' path = 'Participant/%s' % participant_id update_awardee = self.send_put(path, participant, headers={'If-Match': 'W/"1"'}) self.assertEquals(participant['awardee'], update_awardee['awardee']) def test_change_pairing_for_org_then_site(self): participant = self.send_post('Participant', self.participant) participant['providerLink'] = [self.provider_link_2] participant_id = participant['participantId'] path = 'Participant/%s' % participant_id update_1 = self.send_put(path, participant, headers={'If-Match': 'W/"1"'}) participant['site'] = 'hpo-site-bannerphoenix' update_2 = self.send_put(path, participant, headers={'If-Match': 'W/"2"'}) self.assertEqual(update_1['site'], 'UNSET') self.assertEqual(update_1['organization'], 'UNSET') self.assertEqual(update_2['site'], 'hpo-site-bannerphoenix') self.assertEqual(update_2['organization'], 'PITT_BANNER_HEALTH') participant['organization'] = 'AZ_TUCSON_BANNER_HEALTH' update_3 = self.send_put(path, participant, headers={'If-Match': 'W/"3"'}) self.assertEqual(update_2['hpoId'], update_3['hpoId']) self.assertEqual(update_2['organization'], update_3['organization']) self.assertEqual(update_3['site'], 'hpo-site-bannerphoenix') participant['site'] = 'hpo-site-clinic-phoenix' update_4 = self.send_put(path, participant, headers={'If-Match': 'W/"4"'}) self.assertEqual(update_4['site'], 'hpo-site-clinic-phoenix') self.assertEqual(update_4['organization'], 'AZ_TUCSON_BANNER_HEALTH') self.assertEqual(update_4['awardee'], 'AZ_TUCSON') def test_administrative_withdrawal(self): with FakeClock(TIME_1): response = self.send_post('Participant', self.participant) participant_id = response['participantId'] response['providerLink'] = [self.provider_link_2] response['withdrawalStatus'] = 'NO_USE' response['suspensionStatus'] = 'NO_CONTACT' response['withdrawalReason'] = 'TEST' response[ 'withdrawalReasonJustification'] = 'This was a test account.' path = 'Participant/%s' % participant_id update_response = self.send_put(path, response, headers={'If-Match': 'W/"1"'}) with FakeClock(TIME_2): response['meta']['versionId'] = 'W/"2"' response['withdrawalTime'] = update_response['lastModified'] response['suspensionTime'] = update_response['lastModified'] response['awardee'] = 'PITT' response['hpoId'] = 'PITT' self.assertJsonResponseMatches(response, update_response) def submit_questionnaire_response(self, participant_id, questionnaire_id, race_code, gender_code, first_name, middle_name, last_name, zip_code, state_code, street_address, city, sex_code, login_phone_number, sexual_orientation_code, phone_number, recontact_method_code, language_code, education_code, income_code, date_of_birth, cabor_signature_uri, time=TIME_1): code_answers = [] _add_code_answer(code_answers, "race", race_code) _add_code_answer(code_answers, "genderIdentity", gender_code) _add_code_answer(code_answers, "state", state_code) _add_code_answer(code_answers, "sex", sex_code) _add_code_answer(code_answers, "sexualOrientation", sexual_orientation_code) _add_code_answer(code_answers, "recontactMethod", recontact_method_code) _add_code_answer(code_answers, "language", language_code) _add_code_answer(code_answers, "education", education_code) _add_code_answer(code_answers, "income", income_code) qr = make_questionnaire_response_json( participant_id, questionnaire_id, code_answers=code_answers, string_answers=[("firstName", first_name), ("middleName", middle_name), ("lastName", last_name), ("streetAddress", street_address), ("city", city), ("phoneNumber", phone_number), ("loginPhoneNumber", login_phone_number), ("zipCode", zip_code)], date_answers=[("dateOfBirth", date_of_birth)], uri_answers=[("CABoRSignature", cabor_signature_uri)]) with FakeClock(time): self.send_post( 'Participant/%s/QuestionnaireResponse' % participant_id, qr) def test_switch_to_test_account(self): with FakeClock(TIME_1): participant_1 = self.send_post( 'Participant', {"providerLink": [self.provider_link_2]}) questionnaire_id = self.create_questionnaire('questionnaire3.json') participant_id_1 = participant_1['participantId'] self.send_consent(participant_id_1) self.submit_questionnaire_response( participant_id_1, questionnaire_id, RACE_WHITE_CODE, "male", "Bob", "Q", "Jones", "78751", "PIIState_VA", "1234 Main Street", "Austin", "male_sex", "215-222-2222", "straight", "512-555-5555", "email_code", "en", "highschool", "lotsofmoney", datetime.date(1978, 10, 9), "signature.pdf") ps_1 = self.send_get('Participant/%s/Summary' % participant_id_1) self.assertEquals('215-222-2222', ps_1['loginPhoneNumber']) self.assertEquals('PITT', ps_1['hpoId']) p_1 = self.send_get('Participant/%s' % participant_id_1) self.assertEquals('PITT', p_1['hpoId']) self.assertEquals(TIME_1.strftime('%Y' '-' '%m' '-' '%d' 'T' '%X'), p_1['lastModified']) self.assertEquals('W/"1"', p_1['meta']['versionId']) # change login phone number to 444-222-2222 self.submit_questionnaire_response( participant_id_1, questionnaire_id, RACE_WHITE_CODE, "male", "Bob", "Q", "Jones", "78751", "PIIState_VA", "1234 Main Street", "Austin", "male_sex", "444-222-2222", "straight", "512-555-5555", "email_code", "en", "highschool", "lotsofmoney", datetime.date(1978, 10, 9), "signature.pdf", TIME_2) ps_1_with_test_login_phone_number = self.send_get( 'Participant/%s/Summary' % participant_id_1) self.assertEquals( '444-222-2222', ps_1_with_test_login_phone_number['loginPhoneNumber']) self.assertEquals('TEST', ps_1_with_test_login_phone_number['hpoId']) p_1 = self.send_get('Participant/%s' % participant_id_1) self.assertEquals('TEST', p_1['hpoId']) self.assertEquals(TIME_2.strftime('%Y' '-' '%m' '-' '%d' 'T' '%X'), p_1['lastModified']) self.assertEquals('W/"2"', p_1['meta']['versionId'])
class ParticipantCountsOverTimeApiTest(FlaskTestBase): def setUp(self): super(ParticipantCountsOverTimeApiTest, self).setUp(use_mysql=True) self.dao = ParticipantDao() self.ps_dao = ParticipantSummaryDao() self.ps = ParticipantSummary() self.calendar_dao = CalendarDao() self.hpo_dao = HPODao() # Needed by ParticipantCountsOverTimeApi self.hpo_dao.insert(HPO(hpoId=TEST_HPO_ID, name=TEST_HPO_NAME, displayName='Test', organizationType=OrganizationType.UNSET)) self.time1 = datetime.datetime(2017, 12, 31) self.time2 = datetime.datetime(2018, 1, 1) self.time3 = datetime.datetime(2018, 1, 2) self.time4 = datetime.datetime(2018, 1, 3) # Insert 2 weeks of dates curr_date = datetime.date(2017, 12, 22) for _ in xrange(0, 14): calendar_day = Calendar(day=curr_date ) CalendarDao().insert(calendar_day) curr_date = curr_date + datetime.timedelta(days=1) def _insert(self, participant, first_name=None, last_name=None, hpo_name=None, unconsented=False, time_int=None, time_mem=None, time_fp=None): """ Create a participant in a transient test database. :param participant: Participant object :param first_name: First name :param last_name: Last name :param hpo_name: HPO name (one of PITT or AZ_TUCSON) :param time_int: Time that participant fulfilled INTERESTED criteria :param time_mem: Time that participant fulfilled MEMBER criteria :param time_fp: Time that participant fulfilled FULL_PARTICIPANT criteria :return: Participant object """ if unconsented is True: enrollment_status = None elif time_mem is None: enrollment_status = EnrollmentStatus.INTERESTED elif time_fp is None: enrollment_status = EnrollmentStatus.MEMBER else: enrollment_status = EnrollmentStatus.FULL_PARTICIPANT with FakeClock(time_int): self.dao.insert(participant) participant.providerLink = make_primary_provider_link_for_name(hpo_name) with FakeClock(time_mem): self.dao.update(participant) if enrollment_status is None: return None summary = self.participant_summary(participant) if first_name: summary.firstName = first_name if last_name: summary.lastName = last_name summary.dateOfBirth = datetime.date(1978, 10, 10) summary.enrollmentStatus = enrollment_status summary.hpoId = self.hpo_dao.get_by_name(hpo_name).hpoId if time_mem is not None: with FakeClock(time_mem): summary.consentForElectronicHealthRecordsTime = time_mem if time_fp is not None: with FakeClock(time_fp): summary.consentForElectronicHealthRecordsTime = time_fp summary.questionnaireOnTheBasicsTime = time_fp summary.questionnaireOnLifestyleTime = time_fp summary.questionnaireOnOverallHealthTime = time_fp summary.physicalMeasurementsFinalizedTime = time_fp summary.sampleOrderStatus1ED04Time = time_fp summary.sampleOrderStatus1SALTime = time_fp self.ps_dao.insert(summary) return summary def test_get_counts_with_default_parameters(self): # The most basic test in this class p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) # TODO: remove bucketSize from these parameters in all tests qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) # You can debug API responses easily by uncommenting the lines below # print('response') # print(response) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(interested_count_day_1, 0) self.assertEquals(interested_count_day_2, 1) def test_get_counts_with_single_awardee_filter(self): # Does the awardee filter work? p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p1 = Participant(participantId=2, biobankId=5) self._insert(p1, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p1 = Participant(participantId=3, biobankId=6) self._insert(p1, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1) # enrollmentStatus param left blank to test we can handle it qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=PITT &enrollmentStatus= """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(interested_count_day_1, 0) self.assertEquals(interested_count_day_2, 1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=AZ_TUCSON """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(interested_count_day_1, 0) self.assertEquals(interested_count_day_2, 2) def test_get_counts_with_single_awardee_filter(self): # Does the awardee filter work when passed a single awardee? p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p1 = Participant(participantId=2, biobankId=5) self._insert(p1, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p1 = Participant(participantId=3, biobankId=6) self._insert(p1, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=PITT """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(interested_count_day_1, 0) self.assertEquals(interested_count_day_2, 1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=AZ_TUCSON """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(interested_count_day_1, 0) self.assertEquals(interested_count_day_2, 2) def test_get_counts_with_multiple_awardee_filters(self): # Does the awardee filter work when passed more than one awardee? p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=PITT,AZ_TUCSON &enrollmentStatus= """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(interested_count_day_1, 0) self.assertEquals(interested_count_day_2, 3) def test_get_counts_with_enrollment_status_member_filter(self): p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time2) p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time2) p4 = Participant(participantId=4, biobankId=7) self._insert(p4, 'Debra', 'Dinosaur', 'PITT', time_int=self.time1, time_mem=self.time3) # awardee param intentionally left blank to test we can handle it qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee= &enrollmentStatus=MEMBER """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) member_count_day_1 = response[0]['metrics']['MEMBER'] member_count_day_2 = response[1]['metrics']['MEMBER'] member_count_day_3 = response[2]['metrics']['MEMBER'] member_count_day_4 = response[3]['metrics']['MEMBER'] interested_count_day_4 = response[1]['metrics']['INTERESTED'] self.assertEquals(member_count_day_1, 0) self.assertEquals(member_count_day_2, 0) self.assertEquals(member_count_day_3, 2) self.assertEquals(member_count_day_4, 3) self.assertEquals(interested_count_day_4, 0) qs = """ bucketSize=1 &stratification=TOTAL &startDate=2017-12-30 &endDate=2018-01-04 &enrollmentStatus=MEMBER """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) total_count_day_1 = response[0]['metrics']['TOTAL'] total_count_day_2 = response[1]['metrics']['TOTAL'] self.assertEquals(total_count_day_1, 0) self.assertEquals(total_count_day_2, 3) def test_get_counts_with_enrollment_status_full_participant_filter(self): # MEMBER @ time 1 p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1, time_mem=self.time1) # FULL PARTICIPANT @ time 2 p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time1, time_fp=self.time2) # FULL PARTICIPANT @ time 2 p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time1, time_fp=self.time2) # FULL PARTICIPANT @ time 3 p4 = Participant(participantId=4, biobankId=7) self._insert(p4, 'Debra', 'Dinosaur', 'PITT', time_int=self.time1, time_mem=self.time1, time_fp=self.time3) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &enrollmentStatus=FULL_PARTICIPANT """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) full_participant_count_day_1 = response[0]['metrics']['FULL_PARTICIPANT'] full_participant_count_day_2 = response[1]['metrics']['FULL_PARTICIPANT'] full_participant_count_day_3 = response[2]['metrics']['FULL_PARTICIPANT'] full_participant_count_day_4 = response[3]['metrics']['FULL_PARTICIPANT'] member_count_day_4 = response[4]['metrics']['MEMBER'] self.assertEquals(full_participant_count_day_1, 0) self.assertEquals(full_participant_count_day_2, 0) self.assertEquals(full_participant_count_day_3, 2) self.assertEquals(full_participant_count_day_4, 3) self.assertEquals(member_count_day_4, 0) # Excluded per enrollmentStatus parameter def test_get_counts_with_total_enrollment_status_full_participant_filter(self): # When filtering with TOTAL stratification, filtered participants are # returned by their sign up date, not the date they reached their highest # enrollment status. # MEMBER @ time 1 p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1, time_mem=self.time1) # FULL PARTICIPANT @ time 2 p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time1, time_fp=self.time2) # FULL PARTICIPANT @ time 2 p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time1, time_fp=self.time2) # FULL PARTICIPANT @ time 3 p4 = Participant(participantId=4, biobankId=7) self._insert(p4, 'Debra', 'Dinosaur', 'PITT', time_int=self.time1, time_mem=self.time1, time_fp=self.time3) qs = """ bucketSize=1 &stratification=TOTAL &startDate=2017-12-30 &endDate=2018-01-04 &enrollmentStatus=FULL_PARTICIPANT """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) total_count_day_1 = response[0]['metrics']['TOTAL'] total_count_day_2 = response[1]['metrics']['TOTAL'] total_count_day_3 = response[2]['metrics']['TOTAL'] total_count_day_4 = response[3]['metrics']['TOTAL'] self.assertEquals(total_count_day_1, 0) self.assertEquals(total_count_day_2, 3) self.assertEquals(total_count_day_3, 3) self.assertEquals(total_count_day_4, 3) def test_get_counts_with_single_various_filters(self): # Do the awardee and enrollment status filters work when passed single values? p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time1) p4 = Participant(participantId=4, biobankId=7) self._insert(p4, 'Debra', 'Dinosaur', 'PITT', time_int=self.time1, time_mem=self.time1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=PITT &enrollmentStatus=MEMBER """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] member_count_day_2 = response[1]['metrics']['MEMBER'] self.assertEquals(interested_count_day_1, 0) # We requested data for only MEMBERs, so no INTERESTEDs should be returned self.assertEquals(interested_count_day_2, 0) # We requested data for only MEMBERs in PITT, so no MEMBERs in AZ_TUCSON should be returned self.assertEquals(member_count_day_2, 1) def test_get_counts_with_multiple_various_filters(self): # Do the awardee and enrollment status filters work when passed multiple values? p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=AZ_TUCSON,PITT &enrollmentStatus=INTERESTED,MEMBER,FULL_PARTICIPANT """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_1 = response[0]['metrics']['INTERESTED'] interested_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(interested_count_day_1, 0) self.assertEquals(interested_count_day_2, 3) def test_get_counts_with_total_stratification_unfiltered(self): p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1) qs = """ bucketSize=1 &stratification=TOTAL &startDate=2017-12-30 &endDate=2018-01-04 """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) total_count_day_1 = response[0]['metrics']['TOTAL'] total_count_day_2 = response[1]['metrics']['TOTAL'] self.assertEquals(total_count_day_1, 0) self.assertEquals(total_count_day_2, 3) def test_get_counts_excluding_interested_participants(self): # When filtering only for MEMBER, no INTERESTED (neither consented nor unconsented) should be counted p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'UNSET', unconsented=True, time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1, time_mem=self.time1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &enrollmentStatus=MEMBER """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) interested_count_day_2 = response[1]['metrics']['INTERESTED'] member_count_day_2 = response[1]['metrics']['MEMBER'] self.assertEquals(interested_count_day_2, 0) self.assertEquals(member_count_day_2, 1) def test_get_counts_excluding_withdrawn_participants(self): # Withdrawn participants should not appear in counts p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'PITT', time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p3 = Participant(participantId=3, biobankId=6) ps3 = self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1) ps3.withdrawalStatus = WithdrawalStatus.NO_USE # Chad withdrew from the study self.ps_dao.update(ps3) qs = """ bucketSize=1 &stratification=TOTAL &startDate=2017-12-30 &endDate=2018-01-04 """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) total_count_day_1 = response[0]['metrics']['TOTAL'] total_count_day_2 = response[1]['metrics']['TOTAL'] self.assertEquals(total_count_day_1, 0) self.assertEquals(total_count_day_2, 2) def test_get_counts_for_unconsented_individuals(self): # Those who have signed up but not consented should be INTERESTED p1 = Participant(participantId=1, biobankId=4) self._insert(p1, 'Alice', 'Aardvark', 'UNSET', unconsented=True, time_int=self.time1) p2 = Participant(participantId=2, biobankId=5) self._insert(p2, 'Bob', 'Builder', 'AZ_TUCSON', time_int=self.time1) p3 = Participant(participantId=3, biobankId=6) self._insert(p3, 'Chad', 'Caterpillar', 'AZ_TUCSON', time_int=self.time1) qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs) total_count_day_1 = response[0]['metrics']['INTERESTED'] total_count_day_2 = response[1]['metrics']['INTERESTED'] self.assertEquals(total_count_day_1, 0) self.assertEquals(total_count_day_2, 3) def test_url_parameter_validation_for_date_range(self): # Ensure requests for very long date ranges are marked BAD REQUEST qs = """ bucketSize=1 &stratification=TOTAL &startDate=2017-12-30 &endDate=2217-12-30 """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs, expected_status=httplib.BAD_REQUEST) self.assertEquals(response, None) def test_url_parameter_validation_for_stratifications(self): # Ensure requests invalid stratifications are marked BAD REQUEST qs = """ bucketSize=1 &stratification=FOOBAR &startDate=2017-12-30 &endDate=2018-01-04 """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs, expected_status=httplib.BAD_REQUEST) self.assertEquals(response, None) def test_url_parameter_validation_for_awardee(self): # Ensure requests invalid awardee are marked BAD REQUEST qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &awardee=FOOBAR """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs, expected_status=httplib.BAD_REQUEST) self.assertEquals(response, None) def test_url_parameter_validation_for_enrollment_status(self): # Ensure requests invalid enrollment status are marked BAD REQUEST qs = """ bucketSize=1 &stratification=ENROLLMENT_STATUS &startDate=2017-12-30 &endDate=2018-01-04 &enrollmentStatus=FOOBAR """ qs = ''.join(qs.split()) # Remove all whitespace response = self.send_get('ParticipantCountsOverTime', query_string=qs, expected_status=httplib.BAD_REQUEST) self.assertEquals(response, None)
class MetricsEhrApiTestBase(FlaskTestBase): def setUp(self, **kwargs): super(MetricsEhrApiTestBase, self).setUp(use_mysql=True, **kwargs) self.dao = ParticipantDao() self.ps_dao = ParticipantSummaryDao() self.ehr_receipt_dao = EhrReceiptDao() self.ps = ParticipantSummary() self.calendar_dao = CalendarDao() self.site_dao = SiteDao() self.hpo_dao = HPODao() self.org_dao = OrganizationDao() self.hpo_test = self._make_hpo(hpoId=TEST_HPO_ID, name=TEST_HPO_NAME, displayName='Test', organizationType=OrganizationType.UNSET) self.hpo_foo = self._make_hpo(hpoId=10, name='FOO', displayName='Foo') self.hpo_bar = self._make_hpo(hpoId=11, name='BAR', displayName='Bar') self.org_foo_a = self._make_org(organizationId=10, externalId='FOO_A', displayName='Foo A', hpoId=self.hpo_foo.hpoId) self.org_bar_a = self._make_org(organizationId=11, externalId='BAR_A', displayName='Bar A', hpoId=self.hpo_bar.hpoId) def _make_hpo(self, **kwargs): hpo = HPO(**kwargs) self.hpo_dao.insert(hpo) return hpo def _make_org(self, **kwargs): org = Organization(**kwargs) self.org_dao.insert(org) return org def _make_participant(self, participant, first_name=None, last_name=None, hpo=None, organization=None, unconsented=False, time_int=None, time_study=None, time_mem=None, time_fp=None, time_fp_stored=None, gender_id=None, dob=None, state_id=None): """ Create a participant in a transient test database. Note: copied from ParticipantCountsOverTimeApiTest :param participant: Participant object :param first_name: First name :param last_name: Last name :param time_int: Time that participant fulfilled INTERESTED criteria :param time_mem: Time that participant fulfilled MEMBER criteria :param time_fp: Time that participant fulfilled FULL_PARTICIPANT criteria :return: Participant object """ participant.hpoId = hpo.hpoId participant.organizationId = organization.organizationId if unconsented is True: enrollment_status = None elif time_mem is None: enrollment_status = EnrollmentStatus.INTERESTED elif time_fp is None: enrollment_status = EnrollmentStatus.MEMBER else: enrollment_status = EnrollmentStatus.FULL_PARTICIPANT with FakeClock(time_int): self.dao.insert(participant) participant.providerLink = make_primary_provider_link_for_name( hpo.name) with FakeClock(time_mem): self.dao.update(participant) if enrollment_status is None: return None summary = self.participant_summary(participant) if first_name: summary.firstName = first_name if last_name: summary.lastName = last_name if gender_id: summary.genderIdentityId = gender_id if dob: summary.dateOfBirth = dob else: summary.dateOfBirth = datetime.date(1978, 10, 10) if state_id: summary.stateId = state_id summary.enrollmentStatus = enrollment_status summary.enrollmentStatusMemberTime = time_mem summary.enrollmentStatusCoreOrderedSampleTime = time_fp summary.enrollmentStatusCoreStoredSampleTime = time_fp_stored summary.hpoId = hpo.hpoId summary.organizationId = organization.organizationId if time_study is not None: with FakeClock(time_mem): summary.consentForStudyEnrollment = QuestionnaireStatus.SUBMITTED summary.consentForStudyEnrollmentTime = time_study if time_mem is not None: with FakeClock(time_mem): summary.consentForElectronicHealthRecords = QuestionnaireStatus.SUBMITTED summary.consentForElectronicHealthRecordsTime = time_mem if time_fp is not None: with FakeClock(time_fp): if not summary.consentForElectronicHealthRecords: summary.consentForElectronicHealthRecords = QuestionnaireStatus.SUBMITTED summary.consentForElectronicHealthRecordsTime = time_fp summary.questionnaireOnTheBasicsTime = time_fp summary.questionnaireOnLifestyleTime = time_fp summary.questionnaireOnOverallHealthTime = time_fp summary.physicalMeasurementsFinalizedTime = time_fp summary.physicalMeasurementsTime = time_fp summary.sampleOrderStatus1ED04Time = time_fp summary.sampleOrderStatus1SALTime = time_fp summary.sampleStatus1ED04Time = time_fp summary.sampleStatus1SALTime = time_fp summary.biospecimenOrderTime = time_fp summary.numCompletedBaselinePPIModules = REQUIRED_PPI_MODULE_COUNT self.ps_dao.insert(summary) return summary def _update_ehr(self, participant_summary, update_time): receipt = EhrReceipt(organizationId=participant_summary.organizationId, receiptTime=update_time) self.ehr_receipt_dao.insert(receipt) self.ps_dao.update_ehr_status(participant_summary, update_time) self.ps_dao.update(participant_summary)
class EhrReceiptDaoTest(SqlTestBase): def setUp(self, with_data=True, use_mysql=True): super(EhrReceiptDaoTest, self).setUp(with_data=with_data, use_mysql=use_mysql) self.setup_fake() self.calendar_dao = CalendarDao() self.org_dao = OrganizationDao() self.hpo_dao = HPODao() self.participant_dao = ParticipantDao() self.summary_dao = ParticipantSummaryDao() self.ehr_receipt_dao = EhrReceiptDao() self._setup_initial_data() @staticmethod def _iter_dates_in_range(start, end): current = start while current <= end: yield current current += datetime.timedelta(days=1) def _fill_calendar_range(self, start, end): for date in self._iter_dates_in_range(start, end): self.calendar_dao.insert(Calendar(day=date)) def _make_hpo(self, int_id, string_id): hpo = HPO(hpoId=int_id, name=string_id) self.hpo_dao.insert(hpo) return hpo def _make_org(self, **kwargs): org = Organization(**kwargs) self.org_dao.insert(org) return org def _make_participant(self, org, int_id): participant = self._participant_with_defaults(participantId=int_id, biobankId=int_id) participant.hpoId = org.hpoId participant.organizationId = org.organizationId self.participant_dao.insert(participant) summary = self.participant_summary(participant) summary.hpoId = participant.hpoId summary.organizationId = participant.organizationId self.summary_dao.insert(summary) return participant, summary def _update_ehr(self, participant_summary, update_time): self.summary_dao.update_ehr_status(participant_summary, update_time) self.summary_dao.update(participant_summary) def _save_ehr_receipt(self, org, receipt_time): receipt = EhrReceipt(organizationId=org.organizationId, receiptTime=receipt_time) self.ehr_receipt_dao.insert(receipt) def _setup_initial_data(self): self.hpo_foo = self._make_hpo(int_id=10, string_id='hpo_foo') self.hpo_bar = self._make_hpo(int_id=11, string_id='hpo_bar') self.org_foo_a = self._make_org(organizationId=10, externalId='FOO_A', displayName='Foo A', hpoId=self.hpo_foo.hpoId) self.org_bar_a = self._make_org(organizationId=11, externalId='BAR_A', displayName='Bar A', hpoId=self.hpo_bar.hpoId) participant_and_summary_pairs = [ self._make_participant(org=self.org_foo_a, int_id=11), self._make_participant(org=self.org_foo_a, int_id=12), self._make_participant(org=self.org_bar_a, int_id=13), self._make_participant(org=self.org_bar_a, int_id=14), ] self.participants = { participant.participantId: participant for participant, summary in participant_and_summary_pairs } self.summaries = { participant.participantId: summary for participant, summary in participant_and_summary_pairs } def test_get_active_organization_counts_in_interval_day(self): self._fill_calendar_range(datetime.date(2019, 1, 1), datetime.date(2019, 3, 1)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 2, 2)) self._save_ehr_receipt(org=self.org_bar_a, receipt_time=datetime.datetime(2019, 2, 2)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 2, 4)) results = self.ehr_receipt_dao.get_active_organization_counts_in_interval( start_date=datetime.datetime(2019, 2, 1), end_date=datetime.datetime(2019, 2, 7), interval=INTERVAL_DAY) self.assertEqual([(r['start_date'], r['active_organization_count']) for r in results], [ (datetime.date(2019, 2, 1), 0L), (datetime.date(2019, 2, 2), 2L), (datetime.date(2019, 2, 3), 0L), (datetime.date(2019, 2, 4), 1L), (datetime.date(2019, 2, 5), 0L), (datetime.date(2019, 2, 6), 0L), (datetime.date(2019, 2, 7), 0L), ]) def test_get_active_organization_counts_in_interval_week(self): self._fill_calendar_range(datetime.date(2019, 1, 1), datetime.date(2019, 3, 1)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 2, 4)) self._save_ehr_receipt(org=self.org_bar_a, receipt_time=datetime.datetime(2019, 2, 4)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 2, 18)) results = self.ehr_receipt_dao.get_active_organization_counts_in_interval( start_date=datetime.datetime(2019, 2, 1), end_date=datetime.datetime(2019, 3, 1), interval=INTERVAL_WEEK) self.assertEqual([(r['start_date'], r['active_organization_count']) for r in results], [ (datetime.date(2019, 1, 27), 0L), (datetime.date(2019, 2, 3), 2L), (datetime.date(2019, 2, 10), 0L), (datetime.date(2019, 2, 17), 1L), (datetime.date(2019, 2, 24), 0L), ]) def test_get_active_organization_counts_in_interval_month(self): self._fill_calendar_range(datetime.date(2018, 12, 1), datetime.date(2019, 7, 1)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 2, 1)) self._save_ehr_receipt(org=self.org_bar_a, receipt_time=datetime.datetime(2019, 2, 1)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 4, 1)) results = self.ehr_receipt_dao.get_active_organization_counts_in_interval( start_date=datetime.datetime(2019, 1, 1), end_date=datetime.datetime(2019, 5, 1), interval=INTERVAL_MONTH) self.assertEqual([(r['start_date'], r['active_organization_count']) for r in results], [ (datetime.date(2019, 1, 1), 0L), (datetime.date(2019, 2, 1), 2L), (datetime.date(2019, 3, 1), 0L), (datetime.date(2019, 4, 1), 1L), (datetime.date(2019, 5, 1), 0L), ]) def test_get_active_organization_counts_in_interval_quarter(self): self._fill_calendar_range(datetime.date(2018, 12, 1), datetime.date(2020, 1, 1)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 5, 1)) self._save_ehr_receipt(org=self.org_bar_a, receipt_time=datetime.datetime(2019, 5, 1)) self._save_ehr_receipt(org=self.org_foo_a, receipt_time=datetime.datetime(2019, 11, 1)) results = self.ehr_receipt_dao.get_active_organization_counts_in_interval( start_date=datetime.datetime(2019, 1, 1), end_date=datetime.datetime(2020, 1, 1), interval=INTERVAL_QUARTER) self.assertEqual([(r['start_date'], r['active_organization_count']) for r in results], [ (datetime.date(2019, 1, 1), 0L), (datetime.date(2019, 4, 1), 2L), (datetime.date(2019, 7, 1), 0L), (datetime.date(2019, 10, 1), 1L), (datetime.date(2020, 1, 1), 0L), ])
class UpdateEhrStatusUpdatesTestCase(SqlTestBase): def setUp(self, **kwargs): super(UpdateEhrStatusUpdatesTestCase, self).setUp(use_mysql=True, **kwargs) self.hpo_dao = HPODao() self.org_dao = OrganizationDao() self.participant_dao = ParticipantDao() self.summary_dao = ParticipantSummaryDao() self.ehr_receipt_dao = EhrReceiptDao() self.hpo_foo = self._make_hpo(int_id=10, string_id='hpo_foo') self.hpo_bar = self._make_hpo(int_id=11, string_id='hpo_bar') self.org_foo_a = self._make_org(hpo=self.hpo_foo, int_id=10, external_id='FOO_A') self.org_foo_b = self._make_org(hpo=self.hpo_foo, int_id=11, external_id='FOO_B') self.org_bar_a = self._make_org(hpo=self.hpo_bar, int_id=12, external_id='BAR_A') self.participants = [ self._make_participant(hpo=self.hpo_foo, org=self.org_foo_a, int_id=11), self._make_participant(hpo=self.hpo_foo, org=self.org_foo_b, int_id=12), self._make_participant(hpo=self.hpo_bar, org=self.org_bar_a, int_id=13), self._make_participant(hpo=self.hpo_bar, org=self.org_bar_a, int_id=14), ] def _make_hpo(self, int_id, string_id): hpo = HPO(hpoId=int_id, name=string_id) self.hpo_dao.insert(hpo) return hpo def _make_org(self, hpo, int_id, external_id): org = Organization(organizationId=int_id, externalId=external_id, displayName='SOME ORG', hpoId=hpo.hpoId) self.org_dao.insert(org) return org def _make_participant(self, hpo, org, int_id): participant = self._participant_with_defaults(participantId=int_id, biobankId=int_id) participant.hpoId = hpo.hpoId participant.organizationId = org.organizationId self.participant_dao.insert(participant) summary = self.participant_summary(participant) self.summary_dao.insert(summary) return participant, summary # Mock BigQuery result types EhrUpdatePidRow = collections.namedtuple('EhrUpdatePidRow', [ 'person_id', ]) TableCountsRow = collections.namedtuple('TableCountsRow', [ 'org_id', 'person_upload_time', ]) @mock.patch('offline.update_ehr_status.update_organizations_from_job') @mock.patch( 'offline.update_ehr_status.update_participant_summaries_from_job') @mock.patch('offline.update_ehr_status.make_update_organizations_job') @mock.patch( 'offline.update_ehr_status.make_update_participant_summaries_job') def test_skips_when_no_job(self, mock_summary_job, mock_organization_job, mock_update_summaries, mock_update_organizations): mock_summary_job.return_value = None mock_organization_job.return_value = None with FakeClock(datetime.datetime(2019, 1, 1)): offline.update_ehr_status.update_ehr_status() self.assertFalse(mock_update_summaries.called) self.assertFalse(mock_update_organizations.called) @mock.patch('offline.update_ehr_status.make_update_organizations_job') @mock.patch( 'offline.update_ehr_status.make_update_participant_summaries_job') def test_updates_participant_summaries(self, mock_summary_job, mock_organization_job): mock_summary_job.return_value.__iter__.return_value = [[ self.EhrUpdatePidRow(11), ]] mock_organization_job.return_value.__iter__.return_value = [] with FakeClock(datetime.datetime(2019, 1, 1)): offline.update_ehr_status.update_ehr_status() mock_summary_job.return_value.__iter__.return_value = [[ self.EhrUpdatePidRow(11), self.EhrUpdatePidRow(12), ]] mock_organization_job.return_value.__iter__.return_value = [] with FakeClock(datetime.datetime(2019, 1, 2)): offline.update_ehr_status.update_ehr_status() summary = self.summary_dao.get(11) self.assertEqual(summary.ehrStatus, EhrStatus.PRESENT) self.assertEqual(summary.ehrReceiptTime, datetime.datetime(2019, 1, 1)) self.assertEqual(summary.ehrUpdateTime, datetime.datetime(2019, 1, 2)) summary = self.summary_dao.get(12) self.assertEqual(summary.ehrStatus, EhrStatus.PRESENT) self.assertEqual(summary.ehrReceiptTime, datetime.datetime(2019, 1, 2)) self.assertEqual(summary.ehrUpdateTime, datetime.datetime(2019, 1, 2)) @mock.patch('offline.update_ehr_status.make_update_organizations_job') @mock.patch( 'offline.update_ehr_status.make_update_participant_summaries_job') def test_creates_receipts(self, mock_summary_job, mock_organization_job): mock_summary_job.return_value.__iter__.return_value = [] mock_organization_job.return_value.__iter__.return_value = [ [ self.TableCountsRow(org_id='FOO_A', person_upload_time=datetime.datetime( 2019, 1, 1).replace(tzinfo=pytz.UTC)), ], ] with FakeClock(datetime.datetime(2019, 1, 1)): offline.update_ehr_status.update_ehr_status() foo_a_receipts = self.ehr_receipt_dao.get_by_organization_id( self.org_foo_a.organizationId) self.assertEqual(len(foo_a_receipts), 1) self.assertEqual(foo_a_receipts[0].receiptTime, datetime.datetime(2019, 1, 1)) foo_b_receipts = self.ehr_receipt_dao.get_by_organization_id( self.org_foo_b.organizationId) self.assertEqual(len(foo_b_receipts), 0) mock_summary_job.return_value.__iter__.return_value = [] mock_organization_job.return_value.__iter__.return_value = [ [ self.TableCountsRow(org_id='FOO_A', person_upload_time=datetime.datetime( 2019, 1, 1).replace(tzinfo=pytz.UTC)), self.TableCountsRow(org_id='FOO_A', person_upload_time=datetime.datetime( 2019, 1, 2).replace(tzinfo=pytz.UTC)), self.TableCountsRow(org_id='FOO_B', person_upload_time=datetime.datetime( 2019, 1, 2).replace(tzinfo=pytz.UTC)), ], ] with FakeClock(datetime.datetime(2019, 1, 2)): offline.update_ehr_status.update_ehr_status() foo_a_receipts = self.ehr_receipt_dao.get_by_organization_id( self.org_foo_a.organizationId) self.assertEqual(len(foo_a_receipts), 2) self.assertEqual(foo_a_receipts[0].receiptTime, datetime.datetime(2019, 1, 1)) self.assertEqual(foo_a_receipts[1].receiptTime, datetime.datetime(2019, 1, 2)) foo_b_receipts = self.ehr_receipt_dao.get_by_organization_id( self.org_foo_b.organizationId) self.assertEqual(len(foo_b_receipts), 1) self.assertEqual(foo_b_receipts[0].receiptTime, datetime.datetime(2019, 1, 2)) @mock.patch('offline.update_ehr_status.make_update_organizations_job') @mock.patch( 'offline.update_ehr_status.make_update_participant_summaries_job') def test_ignores_bad_data(self, mock_summary_job, mock_organization_job): invalid_participant_id = -1 mock_summary_job.return_value.__iter__.return_value = [[ self.EhrUpdatePidRow(invalid_participant_id), ]] mock_organization_job.return_value.__iter__.return_value = [ [ self.TableCountsRow( org_id='FOO_A', person_upload_time="an invalid date string"), self.TableCountsRow(org_id='AN_ORG_THAT_DOESNT_EXIST', person_upload_time=datetime.datetime( 2019, 1, 1).replace(tzinfo=pytz.UTC)), self.TableCountsRow(org_id='AN_ORG_THAT_DOESNT_EXIST', person_upload_time=None), ], ] with FakeClock(datetime.datetime(2019, 1, 1)): offline.update_ehr_status.update_ehr_status() foo_a_receipts = self.ehr_receipt_dao.get_all() self.assertEqual(len(foo_a_receipts), 0)