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, 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_data(self): organization_dao = OrganizationDao() site_dao = SiteDao() org_1 = organization_dao.insert( Organization(externalId='ORG_1', displayName='Organization 1', hpoId=PITT_HPO_ID, resourceId='o123456')) organization_dao.insert( Organization(externalId='AARDVARK_ORG', displayName='Aardvarks Rock', hpoId=PITT_HPO_ID, resourceId='o123457')) site_dao.insert( Site(siteName='Site 1', googleGroup='hpo-site-1', mayolinkClientNumber=123456, organizationId=org_1.organizationId, siteStatus=SiteStatus.ACTIVE, enrollingStatus=EnrollingStatus.ACTIVE, launchDate=datetime.datetime(2016, 1, 1), notes='notes', latitude=12.1, longitude=13.1, directions='directions', physicalLocationName='locationName', address1='address1', address2='address2', city='Austin', state='TX', zipCode='78751', phoneNumber='555-555-5555', adminEmails='[email protected], [email protected]', link='http://www.example.com')) site_dao.insert( Site(siteName='Zebras Rock', googleGroup='aaaaaaa', organizationId=org_1.organizationId, enrollingStatus=EnrollingStatus.INACTIVE, siteStatus=SiteStatus.INACTIVE))
def _setup_unset_enrollment_site(self): site_dao = SiteDao() organization_dao = OrganizationDao() org_2 = organization_dao.insert( Organization(externalId='ORG_2', displayName='Organization 2', hpoId=PITT_HPO_ID)) site_dao.insert( Site(siteName='not enrolling site', googleGroup='not_enrolling_dot_com', organizationId=org_2.organizationId, enrollingStatus=EnrollingStatus.UNSET, siteStatus=SiteStatus.INACTIVE))
class SyncConsentFilesTest(CloudStorageSqlTestBase, NdbTestBase): """Tests behavior of sync_consent_files """ def setUp(self, **kwargs): super(SyncConsentFilesTest, self).setUp(use_mysql=True, **kwargs) NdbTestBase.doSetUp(self) TestBase.setup_fake(self) self.org_dao = OrganizationDao() self.site_dao = SiteDao() self.participant_dao = ParticipantDao() self.summary_dao = ParticipantSummaryDao() def tearDown(self): super(SyncConsentFilesTest, self).tearDown() def _create_org(self, id_): org = Organization(organizationId=id_, externalId=id_, displayName=id_, hpoId=UNSET_HPO_ID) self.org_dao.insert(org) return org def _create_site(self, id_, google_group): site = Site(siteId=id_, siteName=id_, googleGroup=google_group) self.site_dao.insert(site) return site def _create_participant(self, id_, org_id, site_id, consents=False, ghost=None, email=None, null_email=False): participant = Participant(participantId=id_, biobankId=id_, organizationId=org_id, siteId=site_id, isGhostId=ghost) self.participant_dao.insert(participant) summary = self.participant_summary(participant) if consents: summary.consentForElectronicHealthRecords = 1 summary.consentForStudyEnrollment = 1 if email: summary.email = email if null_email: summary.email = None self.summary_dao.insert(summary) return participant def test_iter_participants_data(self): """should list consenting participants """ org1 = self._create_org(1) org2 = self._create_org(2) site1 = self._create_site(1001, 'group1') site2 = self._create_site(1002, 'group2') self._create_participant(1, org1.organizationId, site1.siteId, consents=True, null_email=True) self._create_participant(2, org2.organizationId, site2.siteId) self._create_participant(3, org1.organizationId, None, consents=True, ghost=False) self._create_participant(4, org1.organizationId, None, consents=True, ghost=True) self._create_participant(5, org1.organizationId, None, consents=True, email='*****@*****.**') participant_data_list = list( sync_consent_files._iter_participants_data()) participant_ids = [d.participant_id for d in participant_data_list] self.assertEqual(len(participant_ids), 2, "finds correct number of results") self.assertEqual(participant_ids, [1, 3], "finds valid participants") self.assertEqual(participant_data_list[0].google_group, 'group1', "Includes google group") self.assertEqual(participant_data_list[1].google_group, None, "allows None for google group") @mock.patch('cloudstorage.listbucket') @mock.patch('cloudstorage.copy2') def test_cloudstorage_copy_objects_api_calls(self, mock_copy2, mock_listbucket): """Makes the proper google cloudstorage API calls """ mock_listbucket.return_value = [ cloudstorage.common.GCSFileStat('/fake_bucket1/prefix1/foo', 0, 'x', 0), cloudstorage.common.GCSFileStat('/fake_bucket1/prefix1/bar', 0, 'x', 0), ] # with trailing slashes sync_consent_files.cloudstorage_copy_objects('/fake_bucket1/prefix1/', '/fake_bucket2/prefix2/') mock_copy2.assert_has_calls([ mock.call('/fake_bucket1/prefix1/foo', '/fake_bucket2/prefix2/foo'), mock.call('/fake_bucket1/prefix1/bar', '/fake_bucket2/prefix2/bar'), ]) # without trailing slashes sync_consent_files.cloudstorage_copy_objects('/fake_bucket1/prefix1', '/fake_bucket2/prefix2') mock_copy2.assert_has_calls([ mock.call('/fake_bucket1/prefix1/foo', '/fake_bucket2/prefix2/foo'), mock.call('/fake_bucket1/prefix1/bar', '/fake_bucket2/prefix2/bar'), ]) @staticmethod def _write_cloud_object(cloud_filename, contents_str): with cloudstorage.cloudstorage_api.open(cloud_filename, mode='w') as cloud_file: cloud_file.write(contents_str.encode('utf-8')) def test_cloudstorage_copy_objects_actual(self): self._write_cloud_object('/fake_bucket1/prefix/x1/foo.txt', 'foo') self._write_cloud_object('/fake_bucket1/prefix/x1/bar.txt', 'bar') self._write_cloud_object('/fake_bucket1/prefix/x1/y1/foo.txt', 'foo') with cloudstorage.cloudstorage_api.open( '/fake_bucket1/prefix/x1/foo.txt', mode='r') as f: self.assertEqual(f.read(), 'foo', 'Wrote to cloud storage') sync_consent_files.cloudstorage_copy_objects( '/fake_bucket1/prefix/x1/', '/fake_bucket2/prefix/z/x1/') self.assertEqual([ file_stat.filename for file_stat in cloudstorage.cloudstorage_api.listbucket( '/fake_bucket2/prefix/z/x1/') ], [ '/fake_bucket2/prefix/z/x1/bar.txt', '/fake_bucket2/prefix/z/x1/foo.txt', '/fake_bucket2/prefix/z/x1/y1/foo.txt', ], "copied all objects") with cloudstorage.cloudstorage_api.open( '/fake_bucket2/prefix/z/x1/foo.txt', mode='r') as f: self.assertEqual(f.read(), 'foo', 'copied contents') @mock.patch('cloudstorage.copy2') def test_cloudstorage_copy_objects_only_new_and_changed(self, copy2): self._write_cloud_object('/fake_bucket1/prefix/x1/foo.txt', 'foo') self._write_cloud_object('/fake_bucket1/prefix/x1/bar.txt', 'bar') self._write_cloud_object('/fake_bucket2/prefix/z/x1/foo.txt', 'foo') self._write_cloud_object('/fake_bucket2/prefix/z/x1/bar.txt', 'baz') sync_consent_files.cloudstorage_copy_objects( '/fake_bucket1/prefix/x1/', '/fake_bucket2/prefix/z/x1/') copy2.assert_called_once_with('/fake_bucket1/prefix/x1/bar.txt', '/fake_bucket2/prefix/z/x1/bar.txt')
class OrganizationDaoTest(SqlTestBase): def setUp(self): super(OrganizationDaoTest, self).setUp() self.organization_dao = OrganizationDao() self.participant_dao = ParticipantDao() self.ps_dao = ParticipantSummaryDao() self.ps_history = ParticipantHistoryDao() def test_insert(self): organization = Organization(externalId='myorg', displayName='myorg_display', hpoId=PITT_HPO_ID, isObsolete=1) created_organization = self.organization_dao.insert(organization) new_organization = self.organization_dao.get(created_organization.organizationId) organization.organizationId = created_organization.organizationId organization.isObsolete = new_organization.isObsolete self.assertEquals(organization.asdict(), new_organization.asdict()) def test_participant_pairing_updates_onchange(self): provider_link = '[{"organization": {"reference": "Organization/AZ_TUCSON"}, "primary": true}]' TIME = datetime.datetime(2018, 1, 1) TIME2 = datetime.datetime(2018, 1, 2) insert_org = self.organization_dao.insert( Organization(externalId='tardis', displayName='bluebox', hpoId=PITT_HPO_ID)) with FakeClock(TIME): self.participant_dao.insert(Participant(participantId=1, biobankId=2)) participant = self.participant_dao.get(1) participant.organizationId = insert_org.organizationId self.participant_dao.update(participant) self.assertEquals(participant.hpoId, insert_org.hpoId) participant = self.participant_dao.get(1) p_summary = self.ps_dao.insert(self.participant_summary(participant)) with FakeClock(TIME2): insert_org.hpoId = AZ_HPO_ID self.organization_dao.update(insert_org) new_org = self.organization_dao.get_by_external_id('tardis') ps = self.ps_dao.get(p_summary.participantId) ph = self.ps_history.get([participant.participantId, 2]) participant = self.participant_dao.get(1) self.assertEquals(ps.lastModified, TIME2) self.assertEquals(ps.hpoId, new_org.hpoId) self.assertEquals(ph.hpoId, insert_org.hpoId) self.assertEquals(ph.organizationId, insert_org.organizationId) self.assertEquals(new_org.hpoId, participant.hpoId) self.assertEquals(new_org.organizationId, participant.organizationId) self.assertIsNone(participant.siteId) self.assertEquals(participant.providerLink, provider_link) def test_participant_different_hpo_does_not_change(self): insert_org = self.organization_dao.insert( Organization(externalId='stark_industries', displayName='ironman', hpoId=PITT_HPO_ID)) self.participant_dao.insert(Participant(participantId=1, biobankId=2)) participant = self.participant_dao.get(1) participant.hpoId = UNSET_HPO_ID self.participant_dao.update(participant) insert_org.hpoId = AZ_HPO_ID self.organization_dao.update(insert_org) new_org = self.organization_dao.get_by_external_id('stark_industries') participant = self.participant_dao.get(1) self.assertNotEqual(new_org.hpoId, participant.hpoId) self.assertEqual(new_org.hpoId, AZ_HPO_ID) self.assertEqual(participant.hpoId, UNSET_HPO_ID)
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)