def test_deactivate_tous(self): timestamp = datetime.utcnow() pptou_audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID, timestamp=timestamp) pptou = ToU(audit=pptou_audit, agreement_url=tou_url, type='privacy policy') wtou_audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) wtou = ToU(audit=wtou_audit, agreement_url=tou_url, type='website terms of use') with SessionScope(db): db.session.add(pptou) db.session.add(wtou) db.session.commit() self.test_user, pptou, wtou = map( db.session.merge, (self.test_user, pptou, wtou)) # confirm active self.assertTrue(all((pptou.active, wtou.active))) # test deactivating single type self.test_user.deactivate_tous(self.test_user, ['privacy policy']) self.assertFalse(pptou.active) self.assertTrue(wtou.active) # test deactivating all types self.test_user.deactivate_tous(self.test_user) self.assertFalse(all((pptou.active, wtou.active)))
def add_procedure(self, code='367336001', display='Chemotherapy', system=SNOMED, setdate=None): "Add procedure data into the db for the test user" with SessionScope(db): audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) procedure = Procedure(audit=audit) coding = Coding( system=system, code=code, display=display).add_if_not_found(True) code = CodeableConcept(codings=[coding]).add_if_not_found(True) enc = Encounter( status='planned', auth_method='url_authenticated', user_id=TEST_USER_ID, start_time=datetime.utcnow()) db.session.add(enc) db.session.commit() enc = db.session.merge(enc) procedure.code = code procedure.user = db.session.merge(self.test_user) procedure.start_time = setdate or datetime.utcnow() procedure.end_time = datetime.utcnow() procedure.encounter = enc db.session.add(procedure) db.session.commit()
def prep_db_for_clinical(self): # First push some clinical data into the db for the test user with SessionScope(db): audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) observation = Observation() coding = Coding(system='SNOMED-CT', code='372278000', display='Gleason score') cc = CodeableConcept(codings=[ coding, ]) observation.codeable_concept = cc observation.value_quantity = ValueQuantity(value=2) performer = Performer(reference_txt=json.dumps( Reference.patient(TEST_USER_ID).as_fhir())) observation.performers.append(performer) db.session.add(observation) enc = Encounter(status='planned', auth_method='url_authenticated', user_id=TEST_USER_ID, start_time=datetime.utcnow()) db.session.add(enc) db.session.flush() db.session.add( UserObservation(user_id=int(TEST_USER_ID), observation_id=observation.id, encounter_id=enc.id, audit=audit)) db.session.commit()
def test_user_consent(self): self.shallow_org_tree() org1, org2 = [ org for org in Organization.query.filter(Organization.id > 0).limit(2) ] audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc1 = UserConsent(organization_id=org1.id, user_id=TEST_USER_ID, agreement_url=self.url, audit=audit) uc2 = UserConsent(organization_id=org2.id, user_id=TEST_USER_ID, agreement_url=self.url, audit=audit) uc1.staff_editable = True uc1.send_reminders = False uc2.staff_editable = True uc2.send_reminders = False with SessionScope(db): db.session.add(uc1) db.session.add(uc2) db.session.commit() self.test_user = db.session.merge(self.test_user) self.login() rv = self.client.get('/api/user/{}/consent'.format(TEST_USER_ID)) self.assert200(rv) self.assertEquals(len(rv.json['consent_agreements']), 2) self.assertTrue( 'send_reminders' not in rv.json['consent_agreements'][0]) self.assertTrue('staff_editable' in rv.json['consent_agreements'][0])
def test_user_consent(self): self.shallow_org_tree() org1, org2 = [ org for org in Organization.query.filter(Organization.id > 0).limit(2) ] audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc1 = UserConsent(organization_id=org1.id, user_id=TEST_USER_ID, agreement_url=self.url, audit=audit) uc2 = UserConsent(organization_id=org2.id, user_id=TEST_USER_ID, agreement_url=self.url, audit=audit) uc1.staff_editable = True uc1.send_reminders = False uc2.staff_editable = True uc2.send_reminders = False uc2.status = 'suspended' with SessionScope(db): db.session.add(uc1) db.session.add(uc2) db.session.commit() self.test_user = db.session.merge(self.test_user) self.login() response = self.client.get('/api/user/{}/consent'.format(TEST_USER_ID)) assert response.status_code == 200 assert len(response.json['consent_agreements']) == 2 assert 'send_reminders' not in response.json['consent_agreements'][0] assert 'staff_editable' in response.json['consent_agreements'][0] assert response.json['consent_agreements'][0]['status'] == 'consented' assert response.json['consent_agreements'][1]['status'] == 'suspended'
def testP3Pstrategy(self): # Prior to meeting conditions in strategy, user shouldn't have access # (provided we turn off public access) INTERVENTION.DECISION_SUPPORT_P3P.public_access = False INTERVENTION.SEXUAL_RECOVERY.public_access = False # part of strat. user = self.test_user assert not INTERVENTION.DECISION_SUPPORT_P3P.display_for_user( user).access # Fulfill conditions enc = Encounter(status='in-progress', auth_method='url_authenticated', user_id=TEST_USER_ID, start_time=datetime.utcnow()) with SessionScope(db): db.session.add(enc) db.session.commit() self.add_procedure(code='424313000', display='Started active surveillance') get_user(TEST_USER_ID).save_observation( codeable_concept=CC.PCaLocalized, value_quantity=CC.TRUE_VALUE, audit=Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID), status=None, issued=None) self.promote_user(user, role_name=ROLE.PATIENT.value) with SessionScope(db): db.session.commit() user = db.session.merge(user) # P3P strategy should now be in view for test user assert INTERVENTION.DECISION_SUPPORT_P3P.display_for_user(user).access
def test_staff_access(self): staff = self.add_user('*****@*****.**') self.promote_user(role_name=ROLE.PATIENT) self.promote_user(staff, role_name=ROLE.STAFF) self.shallow_org_tree() org = Organization.query.filter(Organization.id > 0).first() staff.organizations.append(org) self.test_user.organizations.append(org) audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID, comment='just test data') consent = UserConsent(user_id=TEST_USER_ID, organization_id=org.id, audit=audit, agreement_url='http://fake.org') with SessionScope(db): db.session.add(audit) db.session.add(consent) db.session.commit() staff = db.session.merge(staff) self.login(staff.id) rv = self.client.get('/api/user/{}/audit'.format(TEST_USER_ID)) self.assert200(rv) self.assertEquals(1, len(rv.json['audits'])) self.assertEquals( rv.json['audits'][0]['by']['reference'], Reference.patient(TEST_USER_ID).as_fhir()['reference']) self.assertEquals(rv.json['audits'][0]['on'], Reference.patient(TEST_USER_ID).as_fhir()) self.assertEquals(rv.json['audits'][0]['context'], 'other') self.assertEquals(rv.json['audits'][0]['comment'], 'just test data')
def add_required_clinical_data(self): " Add clinical data to get beyond the landing page " for cc in CC.BIOPSY, CC.PCaDIAG, CC.PCaLocalized: get_user(TEST_USER_ID).save_constrained_observation( codeable_concept=cc, value_quantity=CC.TRUE_VALUE, audit=Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID))
def test_tou_str(self): audit = Audit( user_id=TEST_USER_ID, subject_id=TEST_USER_ID, comment="Agreed to ToU", context='other') tou = ToU(audit=audit, agreement_url=tou_url, type='website terms of use') results = "{}".format(tou) self.assertTrue(tou_url in results)
def test_procedure_from_fhir(self): with open(os.path.join(os.path.dirname(__file__), 'procedure-example.json'), 'r') as fhir_data: data = json.load(fhir_data) proc = Procedure.from_fhir(data, Audit(user_id=TEST_USER_ID)) assert proc.code.codings[0].system == 'http://snomed.info/sct' assert proc.code.codings[0].code == '80146002' assert proc.start_time == dateutil.parser.parse("2013-04-05")
def test_submit_assessment_for_qb(self): swagger_spec = swagger(self.app) data = swagger_spec['definitions']['QuestionnaireResponse']['example'] rp = ResearchProtocol(name='proto') with SessionScope(db): db.session.add(rp) db.session.commit() rp = db.session.merge(rp) rp_id = rp.id qn = self.add_questionnaire(name='epic26') org = Organization(name="testorg") org.research_protocols.append(rp) with SessionScope(db): db.session.add(qn) db.session.add(org) db.session.commit() qn, org = map(db.session.merge, (qn, org)) qb = QuestionnaireBank(name='Test Questionnaire Bank', classification='baseline', research_protocol_id=rp_id, start='{"days": 0}', overdue='{"days": 7}', expired='{"days": 90}') qbq = QuestionnaireBankQuestionnaire(questionnaire=qn, rank=0) qb.questionnaires.append(qbq) test_user = get_user(TEST_USER_ID) test_user.organizations.append(org) audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc = UserConsent(user_id=TEST_USER_ID, organization=org, audit=audit, agreement_url='http://no.com') with SessionScope(db): db.session.add(qb) db.session.add(test_user) db.session.add(audit) db.session.add(uc) db.session.commit() qb = db.session.merge(qb) self.login() response = self.client.post( '/api/patient/{}/assessment'.format(TEST_USER_ID), content_type='application/json', data=json.dumps(data), ) assert response.status_code == 200 test_user = get_user(TEST_USER_ID) assert test_user.questionnaire_responses.count() == 1 assert test_user.questionnaire_responses[0].questionnaire_bank_id ==\ qb.id
def test_completed_older_rp(self): """If current qb completed on older rp, should show as done""" fourmonthsago = now - timedelta(days=120) weekago = now - timedelta(weeks=1) twoweeksago = now - timedelta(weeks=2) org = self.setup_qbs(rp_name='v2', retired_as_of=weekago) org_id = org.id self.setup_qbs(org=org, rp_name='v3') self.test_user.organizations.append(org) audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc = UserConsent(user_id=TEST_USER_ID, organization_id=org_id, audit=audit, agreement_url='http://no.com', acceptance_date=fourmonthsago) with SessionScope(db): db.session.add(audit) db.session.add(uc) db.session.commit() # Two weeks ago, still on rp v2, should be in 3mo recurrence user = db.session.merge(self.test_user) a_s = AssessmentStatus(user=user, as_of_date=twoweeksago) v2qb = a_s.qb_data.qbd.questionnaire_bank self.assertEqual('CRV_recurring_3mo_period v2', a_s.qb_data.qbd.questionnaire_bank.name) self.assertEqual('CRV_recurring_3mo_period v2', a_s.qb_name) self.assertEqual(['epic26_v2'], a_s.instruments_needing_full_assessment()) # Now, should still be rp v3, 3mo recurrence a_s = AssessmentStatus(user=user, as_of_date=now) self.assertEqual('CRV_recurring_3mo_period v3', a_s.qb_data.qbd.questionnaire_bank.name) self.assertEqual(['epic26_v3'], a_s.instruments_needing_full_assessment()) # Complete the questionnaire from the 3mo v2 QB mock_qr('epic26_v2', timestamp=twoweeksago, qb=v2qb, iteration=0) # Two weeks ago, should be completed user = db.session.merge(user) a_s = AssessmentStatus(user=user, as_of_date=twoweeksago) self.assertEqual('Completed', a_s.overall_status) # Current should also be completed, even tho protocol changed a_s = AssessmentStatus(user=user, as_of_date=now) self.assertEqual('Completed', a_s.overall_status) # Should see both as candidates qbds = QuestionnaireBank.qbs_for_user(user, classification='recurring', as_of_date=now) self.assertEqual(len(qbds), 2)
def test_qb_pre_retired(self): # Confirm backdating returns the correct QB weekago = now - timedelta(days=7) org, rpv3, rpv3_id = self.setup_org_n_rp(rp_name='v3') org, rpv2, rpv2_id = self.setup_org_n_rp(org=org, rp_name='v2', retired_as_of=weekago) qn3 = self.add_questionnaire(name='epic26-v3') qn2 = self.add_questionnaire(name='epic26-v2') qb3 = QuestionnaireBank(name='Test Questionnaire Bank v3', classification='baseline', research_protocol_id=rpv3_id, start='{"days": 0}', overdue='{"days": 7}', expired='{"days": 90}') qbq3 = QuestionnaireBankQuestionnaire(questionnaire=qn3, rank=0) qb3.questionnaires.append(qbq3) qb2 = QuestionnaireBank(name='Test Questionnaire Bank v2', classification='baseline', research_protocol_id=rpv2_id, start='{"days": 0}', overdue='{"days": 7}', expired='{"days": 90}') qbq2 = QuestionnaireBankQuestionnaire(questionnaire=qn2, rank=0) qb2.questionnaires.append(qbq2) self.test_user.organizations.append(org) audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc = UserConsent(user_id=TEST_USER_ID, organization=org, audit=audit, agreement_url='http://no.com') with SessionScope(db): map(db.session.add, (qb2, qb3)) db.session.add(audit) db.session.add(uc) db.session.commit() user, org, qb2, qb3 = map(db.session.merge, (self.test_user, org, qb2, qb3)) # w/o backdating, should get current QB self.assertEqual( qb3, QuestionnaireBank.most_current_qb( user, as_of_date=now).questionnaire_bank) # backdate prior to retirement of previous, should get the previous QB pre_retirement = weekago - timedelta(days=1) self.assertEqual( qb2, QuestionnaireBank.most_current_qb( user, as_of_date=pre_retirement).questionnaire_bank)
def test_no_start_date(self): # W/O a biopsy (i.e. event start date), no questionnaries self.promote_user(role_name=ROLE.PATIENT.value) # toggle default setup - set biopsy false for test user self.login() self.test_user = db.session.merge(self.test_user) self.test_user.save_observation( codeable_concept=CC.BIOPSY, value_quantity=CC.FALSE_VALUE, audit=Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID), status='final', issued=now) qstats = QB_Status(self.test_user, now) assert not qstats.current_qbd() assert not qstats.enrolled_in_classification("baseline")
def test_get(self): audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) tou = ToU(audit=audit, agreement_url=tou_url, type='website terms of use') with SessionScope(db): db.session.add(tou) db.session.commit() self.login() rv = self.client.get('/api/user/{}/tou'.format(TEST_USER_ID)) doc = json.loads(rv.data) self.assert200(rv) self.assertEqual(len(doc['tous']), 1)
def test_no_start_date(self): # W/O a biopsy (i.e. event start date), no questionnaries self.promote_user(role_name=ROLE.PATIENT.value) # toggle default setup - set biopsy false for test user self.login() self.test_user = db.session.merge(self.test_user) self.test_user.save_observation(codeable_concept=CC.BIOPSY, value_quantity=CC.FALSE_VALUE, audit=Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID), status='final', issued=None) assert not QuestionnaireBank.qbs_for_user( self.test_user, 'baseline', as_of_date=now)
def test_get(self): audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) tou = ToU(audit=audit, agreement_url=tou_url, type='website terms of use') with SessionScope(db): db.session.add(tou) db.session.commit() self.login() response = self.client.get('/api/user/{}/tou'.format(TEST_USER_ID)) doc = response.json assert response.status_code == 200 assert len(doc['tous']) == 1
def add_required_clinical_data(self, backdate=None, setdate=None): """Add clinical data to get beyond the landing page :param backdate: timedelta value. Define to mock Dx happening said period in the past :param setdate: datetime value. Define to mock Dx happening at given time """ audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) for cc in CC.BIOPSY, CC.PCaDIAG, CC.PCaLocalized: get_user(TEST_USER_ID).save_observation( codeable_concept=cc, value_quantity=CC.TRUE_VALUE, audit=audit, status='preliminary', issued=calc_date_params( backdate=backdate, setdate=setdate))
def test_completed_older_rp(self): """If current qb completed on older rp, should show as done""" fourmonthsago = now - timedelta(days=120) weekago = now - timedelta(weeks=1) twoweeksago = now - timedelta(weeks=2) org = self.setup_org_qbs(rp_name='v2', retired_as_of=weekago) org_id = org.id self.setup_org_qbs(org=org, rp_name='v3') self.promote_user(role_name=ROLE.PATIENT.value) self.test_user = db.session.merge(self.test_user) self.test_user.organizations.append(org) audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc = UserConsent(user_id=TEST_USER_ID, organization_id=org_id, audit=audit, agreement_url='http://no.com', acceptance_date=fourmonthsago) with SessionScope(db): db.session.add(audit) db.session.add(uc) db.session.commit() user = db.session.merge(self.test_user) # Now, should still be rp v3, 3mo recurrence a_s = QB_Status(user=user, as_of_date=now) assert (a_s.current_qbd().questionnaire_bank.name == 'CRV_recurring_3mo_period v3') assert a_s.instruments_needing_full_assessment() == [ 'epic26_v3', 'eortc_v3' ] # Complete the questionnaire from the 3mo v2 QB v2qb = QuestionnaireBank.query.filter( QuestionnaireBank.name == 'CRV_recurring_3mo_period v2').one() mock_qr('epic26_v2', timestamp=twoweeksago, qb=v2qb, iteration=0) mock_qr('eortc_v2', timestamp=twoweeksago, qb=v2qb, iteration=0) # Two weeks ago, should be completed user = db.session.merge(user) a_s = QB_Status(user=user, as_of_date=twoweeksago) assert a_s.overall_status == OverallStatus.completed # Current should also be completed, even tho protocol changed a_s = QB_Status(user=user, as_of_date=now) assert a_s.overall_status == OverallStatus.completed
def test_get_by_type(self): timestamp = datetime.utcnow() audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID, timestamp=timestamp) tou = ToU(audit=audit, agreement_url=tou_url, type='privacy policy') with SessionScope(db): db.session.add(tou) db.session.commit() self.login() rv = self.client.get( '/api/user/{}/tou/privacy-policy'.format(TEST_USER_ID)) self.assert200(rv) self.assertEquals(rv.json['accepted'], timestamp.strftime("%Y-%m-%dT%H:%M:%S")) self.assertEquals(rv.json['type'], 'privacy policy')
def upgrade(): bind = op.get_bind() session = Session(bind=bind) to_delete = set() for obs_id, audit_id in session.execute( 'SELECT id, audit_id FROM observations'): to_delete.add(audit_id) if session.execute("SELECT * FROM information_schema.table_constraints " "WHERE constraint_name='observations_audit_id_fkey'" "AND table_name='observations'").rowcount > 0: op.drop_constraint(u'observations_audit_id_fkey', 'observations', type_='foreignkey') elif session.execute("SELECT * FROM information_schema.table_constraints " "WHERE constraint_name='observations_audit_fk'" "AND table_name='observations'").rowcount > 0: op.drop_constraint(u'observations_audit_fk', 'observations', type_='foreignkey') op.drop_column('observations', 'audit_id') op.add_column('user_observations', sa.Column('audit_id', sa.Integer(), nullable=True)) op.create_foreign_key(u'user_observations_audit_id_fkey', 'user_observations', 'audit', ['audit_id'], ['id']) # delete old Observation audits if to_delete: session.execute("DELETE from audit where id in {}".format( tuple(to_delete))) # create new audits for UserObservations for uo_id, user_id in session.execute( 'SELECT id, user_id FROM user_observations'): aud = Audit( user_id=user_id, subject_id=user_id, comment="entry predates audit records for user observations") session.add(aud) session.commit() aud = session.merge(aud) session.execute('UPDATE user_observations SET audit_id = {} ' 'WHERE id = {}'.format(aud.id, uo_id)) op.alter_column('user_observations', 'audit_id', nullable=False)
def upgrade(): localized_org = current_app.config.get('LOCALIZED_AFFILIATE_ORG') if not localized_org: return bind = op.get_bind() session = Session(bind=bind) admin = User.query.filter_by(email='*****@*****.**').first() admin = admin or User.query.join(UserRoles).join(Role).filter( sa.and_(Role.id == UserRoles.role_id, UserRoles.user_id == User.id, Role.name == 'admin')).first() admin_id = admin.id # encounter needed to save_observation initiate_encounter(admin, "staff_authenticated") localized_org_id = session.query(Organization).filter( Organization.name == localized_org).one().id patient_id = session.query(Role).filter(Role.name == 'patient').one().id org_list = OrgTree().here_and_below_id(localized_org_id) query = User.query.join(UserOrganization).join(UserRoles).filter( sa.and_(User.id == UserOrganization.user_id, User.id == UserRoles.user_id, UserRoles.role_id == patient_id, UserOrganization.organization_id.in_(org_list))).with_entities( User) for user in query: if user.concept_value(CC.PCaLocalized) == 'true': # user already has positive PCaLocalized observation continue else: audit = Audit(user_id=admin_id, subject_id=patient_id, context='observation') user.save_observation(codeable_concept=CC.PCaLocalized, value_quantity=CC.TRUE_VALUE, audit=audit, status=None, issued=None) audit.comment = "set {0} {1} on user {2}".format( CC.PCaLocalized, CC.TRUE_VALUE, patient_id) session.commit()
def bless_with_basics(self, backdate=None, setdate=None): """Bless test user with basic requirements for coredata :param backdate: timedelta value. Define to mock consents happening said period in the past. See ``associative_backdate`` for issues with 'months'. :param setdate: datetime value. Define to mock consents happening at exact time in the past """ self.test_user = db.session.merge(self.test_user) self.test_user.birthdate = datetime.utcnow() # Register with a clinic self.shallow_org_tree() org = Organization.query.filter( Organization.partOf_id != None).first() assert org self.test_user.organizations.append(org) # Agree to Terms of Use and sign consent audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) tou = ToU(audit=audit, agreement_url='http://not.really.org', type='website terms of use') privacy = ToU(audit=audit, agreement_url='http://not.really.org', type='privacy policy') parent_org = OrgTree().find(org.id).top_level() options = (STAFF_EDITABLE_MASK | INCLUDE_IN_REPORTS_MASK | SEND_REMINDERS_MASK) consent = UserConsent( user_id=TEST_USER_ID, organization_id=parent_org, options=options, audit=audit, agreement_url='http://fake.org', acceptance_date=calc_date_params( backdate=backdate, setdate=setdate)) with SessionScope(db): db.session.add(tou) db.session.add(privacy) db.session.add(consent) db.session.commit() # Invalidate org tree cache, in case orgs are added by other # tests. W/o doing so, the new orgs aren't in the orgtree OrgTree.invalidate_cache()
def downgrade(): bind = op.get_bind() session = Session(bind=bind) to_delete = set() for obs_id, audit_id in session.execute( 'SELECT id, audit_id FROM user_observations'): to_delete.add(audit_id) op.drop_constraint(u'user_observations_audit_id_fkey', 'user_observations', type_='foreignkey') op.drop_column('user_observations', 'audit_id') op.add_column( 'observations', sa.Column('audit_id', sa.INTEGER(), autoincrement=False, nullable=True)) op.create_foreign_key(u'observations_audit_id_fkey', 'observations', 'audit', ['audit_id'], ['id']) # delete old UserObservation audits session.execute("DELETE from audit where id in {}".format( tuple(to_delete))) # create new audits for Observations admin = User.query.filter_by(email='*****@*****.**').first() admin = admin or User.query.join(UserRoles).join(Role).filter( sa.and_(Role.id == UserRoles.role_id, UserRoles.user_id == User.id, Role.name == 'admin')).first() admin_id = admin.id for obs_id in session.execute( 'SELECT id FROM observations where audit_id IS NULL'): aud = Audit( user_id=admin_id, subject_id=admin_id, comment="entry replaces audit records for user observations") session.add(aud) session.commit() aud = session.merge(aud) session.execute('UPDATE observations SET audit_id = {} ' 'WHERE id = {}'.format(aud.id, obs_id[0])) op.alter_column('observations', 'audit_id', nullable=False)
def test_get_by_type(self): timestamp = datetime.utcnow() audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID, timestamp=timestamp) tou = ToU(audit=audit, agreement_url=tou_url, type='privacy policy') with SessionScope(db): db.session.add(tou) db.session.commit() self.login() rv = self.client.get('/api/user/{}/tou/privacy-policy'.format( TEST_USER_ID)) self.assert200(rv) # result must be timezone aware isoformat, without microseconds tzaware = timestamp.replace(tzinfo=pytz.utc) wo_micro = tzaware.replace(microsecond=0) self.assertEqual(rv.json['accepted'], wo_micro.isoformat()) self.assertEqual(rv.json['type'], 'privacy policy')
def test_delete_user_consent(self): self.shallow_org_tree() org1, org2 = [ org for org in Organization.query.filter(Organization.id > 0).limit(2) ] org1_id, org2_id = org1.id, org2.id data = {'organization_id': org1_id} audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) uc1 = UserConsent(organization_id=org1_id, user_id=TEST_USER_ID, agreement_url=self.url, audit=audit) uc2 = UserConsent(organization_id=org2_id, user_id=TEST_USER_ID, agreement_url=self.url, audit=audit) with SessionScope(db): db.session.add(uc1) db.session.add(uc2) db.session.commit() self.test_user = db.session.merge(self.test_user) assert self.test_user.valid_consents.count() == 2 self.login() response = self.client.delete( '/api/user/{}/consent'.format(TEST_USER_ID), content_type='application/json', data=json.dumps(data)) assert response.status_code == 200 assert self.test_user.valid_consents.count() == 1 assert self.test_user.valid_consents[0].organization_id == org2_id # We no longer omit deleted consent rows, but rather, include # their audit data. response = self.client.get('/api/user/{}/consent'.format(TEST_USER_ID)) assert 'deleted' in json.dumps(response.json) # confirm deleted status dc = UserConsent.query.filter_by(user_id=TEST_USER_ID, organization_id=org1_id).first() assert dc.status == 'deleted'
def upgrade(): bind = op.get_bind() session = Session(bind=bind) admin = User.query.filter_by(email='*****@*****.**').first() admin = admin or User.query.join( UserRoles).join(Role).filter( sa.and_( Role.id == UserRoles.role_id, UserRoles.user_id == User.id, Role.name == 'admin')).first() admin_id = admin.id query = session.query(UserConsent).join( Audit, UserConsent.audit_id == Audit.id).with_entities( UserConsent, Audit.timestamp) eligible_uc_ids = {} for uc, timestamp in query: if uc.acceptance_date.microsecond != 0: # skip the honest ones, that differ by milliseconds if timestamp - uc.acceptance_date < timedelta(seconds=5): continue if timestamp - uc.acceptance_date > timedelta(days=8): raise ValueError( "too big of a jump - please review {} {} {}".format( uc.user_id, timestamp, uc.acceptance_date)) eligible_uc_ids[uc.id] = ( uc.acceptance_date, timestamp.replace(microsecond=0)) # now update each in eligible list outside of initial query for uc_id, dates in eligible_uc_ids.items(): old_acceptance_date, new_acceptance_date = dates msg = "Correct stale default acceptance_date {} to {}".format( old_acceptance_date, new_acceptance_date) uc = session.query(UserConsent).get(uc_id) audit = Audit( user_id=admin_id, subject_id=uc.user_id, context='consent', comment=msg) uc.audit = audit uc.acceptance_date = new_acceptance_date session.commit()
def test_intervention_trigger_date(self): # testing intervention-based QBs q = self.add_questionnaire('q') interv = Intervention(name='interv', description='test') with SessionScope(db): db.session.add(interv) db.session.commit() q, interv, self.test_user = map(db.session.merge, (q, interv, self.test_user)) qb = QuestionnaireBank(name='qb', intervention_id=interv.id, classification='baseline', start='{"days": 1}', expired='{"days": 2}') qbq = QuestionnaireBankQuestionnaire(rank=0, questionnaire=q) qb.questionnaires.append(qbq) # user without biopsy or TX date should return None self.assertFalse(qb.trigger_date(self.test_user)) # user with biopsy should return biopsy date self.login() self.test_user.save_observation(codeable_concept=CC.BIOPSY, value_quantity=CC.TRUE_VALUE, audit=Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID), status='', issued=None) self.test_user = db.session.merge(self.test_user) obs = self.test_user.observations.first() self.assertEqual(obs.codeable_concept.codings[0].display, 'biopsy') self.assertEqual(qb.trigger_date(self.test_user), obs.issued) # user with biopsy and TX date should return TX date tx_date = datetime.utcnow() self.add_procedure(code='7', display='Focal therapy', system=ICHOM, setdate=tx_date) self.test_user = db.session.merge(self.test_user) qb.__trigger_date = None # clear out stored trigger_date self.assertEqual(qb.trigger_date(self.test_user), tx_date)
def consent_with_org(self, org_id, user_id=TEST_USER_ID, backdate=None, setdate=None): """Bless given user with a valid consent with org :param backdate: timedelta value. Define to mock consents happening said period in the past :param setdate: datetime value. Define to mock consents happening at exact time in the past """ audit = Audit(user_id=user_id, subject_id=user_id) consent = UserConsent( user_id=user_id, organization_id=org_id, audit=audit, agreement_url='http://fake.org', acceptance_date=calc_date_params( backdate=backdate, setdate=setdate)) with SessionScope(db): db.session.add(consent) db.session.commit()
def test_content_options(self): audit = Audit(user_id=TEST_USER_ID, subject_id=TEST_USER_ID) self.shallow_org_tree() org1, _ = [ org for org in Organization.query.filter(Organization.id > 0).limit(2) ] uc = UserConsent(user_id=TEST_USER_ID, organization=org1, audit=audit, agreement_url='http://no.com') uc.include_in_reports = True with SessionScope(db): db.session.add(uc) db.session.commit() uc = UserConsent.query.first() self.assertTrue(uc.include_in_reports) self.assertFalse(uc.staff_editable) self.assertFalse(uc.send_reminders)