def test_overwrite_existing_pairing(self): participant_id = 99 created = self.dao.insert( Participant(participantId=participant_id, biobankId=2, hpoId=self._test_db.hpo_id, providerLink=make_primary_provider_link_for_id( self._test_db.hpo_id))) self.participant_summary_dao.insert(self.participant_summary(created)) self.assertEquals(created.hpoId, self._test_db.hpo_id) # sanity check other_hpo = HPODao().insert( HPO(hpoId=PITT_HPO_ID + 1, name='DIFFERENT_HPO')) other_site = SiteDao().insert( Site(hpoId=other_hpo.hpoId, siteName='Arbitrary Site', googleGroup='*****@*****.**')) with self.dao.session() as session: self.dao.add_missing_hpo_from_site(session, participant_id, other_site.siteId) # Original Participant + summary is affected. refetched = self.dao.get(participant_id) self.assertEquals(refetched.hpoId, other_hpo.hpoId) self.assertEquals(refetched.providerLink, make_primary_provider_link_for_id(other_hpo.hpoId)) self.assertEquals( self.participant_summary_dao.get(participant_id).hpoId, other_hpo.hpoId)
def add_missing_hpo_from_site(self, session, participant_id, site_id): if site_id is None: raise BadRequest('No site ID given for auto-pairing participant.') site = SiteDao().get_with_session(session, site_id) if site is None: raise BadRequest('Invalid siteId reference %r.' % site_id) participant = self.get_for_update(session, participant_id) if participant is None: raise BadRequest('No participant %r for HPO ID udpate.' % participant_id) if participant.siteId == site.siteId: return participant.hpoId = site.hpoId participant.organizationId = site.organizationId participant.siteId = site.siteId participant.providerLink = make_primary_provider_link_for_id( site.hpoId) if participant.participantSummary is None: raise RuntimeError('No ParticipantSummary available for P%d.' % participant_id) participant.participantSummary.hpoId = site.hpoId participant.lastModified = clock.CLOCK.now() # Update the version and add history row self._do_update(session, participant, participant)
def test_pairs_unset(self): participant_id = 22 self.dao.insert(Participant(participantId=participant_id, biobankId=2)) refetched = self.dao.get(participant_id) self.assertEquals(refetched.hpoId, UNSET_HPO_ID) # sanity check self.participant_summary_dao.insert( self.participant_summary(refetched)) with self.dao.session() as session: self.dao.add_missing_hpo_from_site(session, participant_id, self._test_db.site_id) paired = self.dao.get(participant_id) self.assertEquals(paired.hpoId, self._test_db.hpo_id) self.assertEquals( paired.providerLink, make_primary_provider_link_for_id(self._test_db.hpo_id)) self.assertEquals( self.participant_summary_dao.get(participant_id).hpoId, self._test_db.hpo_id) self.assertEquals(paired.organizationId, self._test_db.organization_id) self.assertEquals(paired.siteId, self._test_db.site_id)
def _do_update(self, session, obj, existing_obj): update_participants = False if obj.hpoId != existing_obj.hpoId: update_participants = True new_hpo_id = obj.hpoId super(OrganizationDao, self)._do_update(session, obj, existing_obj) if update_participants: provider_link = make_primary_provider_link_for_id(new_hpo_id) participant_sql = """ UPDATE participant SET hpo_id = :hpo_id, provider_link = :provider_link WHERE organization_id = :org_id; """ participant_summary_sql = """ UPDATE participant_summary SET hpo_id = :hpo_id, last_modified = :now WHERE organization_id = :org_id; """ participant_history_sql = """ UPDATE participant_history SET hpo_id = :hpo_id, provider_link = :provider_link WHERE organization_id = :org_id; """ params = { 'hpo_id': new_hpo_id, 'provider_link': provider_link, 'org_id': existing_obj.organizationId, 'now': clock.CLOCK.now() } session.execute(participant_sql, params) session.execute(participant_summary_sql, params) session.execute(participant_history_sql, params)
def _do_update(self, session, obj, existing_obj): """Updates the associated ParticipantSummary, and extracts HPO ID from the provider link or set pairing at another level (site/organization/awardee) with parent/child enforcement.""" obj.lastModified = clock.CLOCK.now() obj.signUpTime = existing_obj.signUpTime obj.biobankId = existing_obj.biobankId obj.withdrawalTime = existing_obj.withdrawalTime obj.suspensionTime = existing_obj.suspensionTime need_new_summary = False if obj.withdrawalStatus != existing_obj.withdrawalStatus: obj.withdrawalTime = (obj.lastModified if obj.withdrawalStatus == WithdrawalStatus.NO_USE else None) obj.withdrawalAuthored = obj.withdrawalAuthored \ if obj.withdrawalStatus == WithdrawalStatus.NO_USE else None need_new_summary = True if obj.suspensionStatus != existing_obj.suspensionStatus: obj.suspensionTime = (obj.lastModified if obj.suspensionStatus == SuspensionStatus.NO_CONTACT else None) need_new_summary = True update_pairing = True if obj.siteId is None and obj.organizationId is None and obj.hpoId is None and \ obj.providerLink == 'null': # Prevent unpairing if /PUT is sent with no pairing levels. update_pairing = False if update_pairing is True: has_id = False if obj.organizationId or obj.siteId or (obj.hpoId >= 0): has_id = True provider_link_unchanged = True if obj.providerLink is not None: if existing_obj.providerLink: provider_link_unchanged = json.loads(obj.providerLink) == \ json.loads(existing_obj.providerLink) else: provider_link_unchanged = False null_provider_link = obj.providerLink == 'null' # site,org,or awardee is sent in request: Get relationships and try to set provider link. if has_id and (provider_link_unchanged or null_provider_link): site, organization, awardee = self.get_pairing_level(obj) obj.organizationId = organization obj.siteId = site obj.hpoId = awardee if awardee is not None and (obj.hpoId != existing_obj.hpoId): # get provider link for hpo_id (awardee) obj.providerLink = make_primary_provider_link_for_id(awardee) need_new_summary = True else: # providerLink has changed # If the provider link changes, update the HPO ID on the participant and its summary. if obj.hpoId is None: obj.hpoId = existing_obj.hpoId new_hpo_id = self._get_hpo_id(obj) if new_hpo_id != existing_obj.hpoId: obj.hpoId = new_hpo_id obj.siteId = None obj.organizationId = None need_new_summary = True # No pairing updates sent, keep existing values. if update_pairing == False: obj.siteId = existing_obj.siteId obj.organizationId = existing_obj.organizationId obj.hpoId = existing_obj.hpoId obj.providerLink = existing_obj.providerLink if need_new_summary and existing_obj.participantSummary: # Copy the existing participant summary, and mutate the fields that # come from participant. summary = existing_obj.participantSummary summary.hpoId = obj.hpoId summary.organizationId = obj.organizationId summary.siteId = obj.siteId summary.withdrawalStatus = obj.withdrawalStatus summary.withdrawalReason = obj.withdrawalReason summary.withdrawalReasonJustification = obj.withdrawalReasonJustification summary.withdrawalTime = obj.withdrawalTime summary.withdrawalAuthored = obj.withdrawalAuthored summary.suspensionStatus = obj.suspensionStatus summary.suspensionTime = obj.suspensionTime summary.lastModified = clock.CLOCK.now() make_transient(summary) make_transient(obj) obj.participantSummary = summary self._update_history(session, obj, existing_obj) super(ParticipantDao, self)._do_update(session, obj, existing_obj)