def test_success(self, req, dbsession, check_csrf_token): """ It should allow removal of entities from a visit. """ from datetime import date, timedelta from pyramid.httpexceptions import HTTPOk from occams import models as datastore from occams import models cycle = models.Cycle(name='week-1', title=u'', week=1) schema = datastore.Schema( name=u'sample', title=u'', publish_date=date.today()) study = models.Study( name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle], schemata=set([schema])) site = models.Site(name=u'ucsd', title=u'UCSD') default_state = ( dbsession.query(datastore.State) .filter_by(name=u'pending-entry') .one()) t_a = date.today() + timedelta(days=5) patient_a = models.Patient(site=site, pid=u'12345') visit_a = models.Visit( patient=patient_a, cycles=[cycle], visit_date=t_a) entity_a_1 = datastore.Entity( schema=schema, collect_date=t_a, state=default_state) entity_a_2 = datastore.Entity( schema=schema, collect_date=t_a, state=default_state) entity_a_3 = datastore.Entity( schema=schema, collect_date=t_a, state=default_state) list(map(visit_a.entities.add, [entity_a_1, entity_a_2, entity_a_3])) dbsession.add_all([visit_a, study]) dbsession.flush() req.json_body = { 'forms': [entity_a_2.id, entity_a_3.id] } res = self._call_fut(visit_a['forms'], req) # refresh the session so we can get a correct listing dbsession.expunge_all() visit_a = dbsession.query(models.Visit).get(visit_a.id) assert isinstance(res, HTTPOk) assert sorted([e.id for e in [entity_a_1]]) == \ sorted([e.id for e in visit_a.entities])
def test_cascade_forms(self, req, dbsession, check_csrf_token): """ It should remove all visit-associated forms. """ from datetime import date from occams import models as datastore from occams import models schema = datastore.Schema( name=u'sample', title=u'Some Sample', publish_date=date.today()) study = models.Study( name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) cycle = models.Cycle( name=u'week-10', title=u'Week 10', week=10) study.cycles.append(cycle) patient = models.Patient( site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') enrollment = models.Enrollment( study=study, patient=patient, consent_date=date.today()) visit = models.Visit( patient=patient, cycles=[cycle], visit_date=date.today()) visit.entities.add(datastore.Entity( schema=schema, collect_date=date.today())) dbsession.add_all([patient, enrollment, study, visit]) dbsession.flush() visit_id = visit.id self._call_fut(visit, req) assert dbsession.query(models.Visit).get(visit_id) is None assert 0 == dbsession.query(datastore.Entity).count()
def populate(self, app, dbsession): import transaction from occams import models from datetime import date # Any view-dependent data goes here # Webtests will use a different scope for its transaction with transaction.manager: user = models.User(key=USERID) dbsession.info['blame'] = user dbsession.add(user) dbsession.flush() site = models.Site(name=u'UCSD', title=u'UCSD', description=u'UCSD Campus', create_date=date.today()) patient = models.Patient(initials=u'ian', nurse=u'*****@*****.**', site=site, pid=u'123') form = models.Schema(name=u'test_schema', title=u'test_title', publish_date=date(2015, 1, 1)) study = models.Study(name=u'test_study', code=u'test_code', consent_date=date(2014, 12, 23), is_randomized=False, title=u'test_title', short_title=u'test_short', schemata=set([form])) cycle = models.Cycle(name=u'TestCycle', title=u'TestCycle', week=39, study=study) visit = models.Visit(patient=patient, cycles=[cycle], visit_date='2015-01-01') entity = models.Entity(schema=form, collect_date=date(2015, 1, 1)) dbsession.add(study) dbsession.add(patient) dbsession.add(visit) dbsession.add(entity) patient.entities.add(entity)
def test_unique_visit_date(self, req, dbsession, check_csrf_token): """ It should not allow duplicate visit dates """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams import models study = models.Study( name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) cycle1 = models.Cycle(name='week-1', title=u'', week=1) cycle2 = models.Cycle(name='week-2', title=u'', week=2) study.cycles.append(cycle1) study.cycles.append(cycle2) patient = models.Patient( site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') visit = models.Visit( patient=patient, cycles=[cycle1], visit_date=date.today()) dbsession.add_all([patient, study, visit]) dbsession.flush() req.json_body = { 'cycles': [cycle2.id], 'visit_date': str(date.today()) } # Update the visit, should allow to update the date self._call_fut(visit, req) # New visits cannot share dates with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(patient['visits'], req) assert 'already exists' in \ excinfo.value.json['errors']['visit_date']
def test_unique_cycle(self, req, dbsession, check_csrf_token): """ It should not allow repeat cycles (unless it's interim) """ from datetime import date, timedelta from pyramid.httpexceptions import HTTPBadRequest from occams import models study = models.Study( name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) cycle = models.Cycle(name='week-1', title=u'', week=1) study.cycles.append(cycle) patient = models.Patient( site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') visit = models.Visit( patient=patient, cycles=[cycle], visit_date=date.today()) dbsession.add_all([patient, study, visit]) dbsession.flush() req.json_body = { 'cycles': [cycle.id], 'visit_date': str(date.today() + timedelta(days=1)) } with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(patient['visits'], req) assert 'already in use' in \ excinfo.value.json['errors']['cycles-0'].lower() # The exception is interims cycle.is_interim = True dbsession.flush() res = self._call_fut(patient['visits'], req) assert res is not None
def test_not_in_study(self, req, dbsession): """ It should fail if the form is not part of the study """ from datetime import date, timedelta from pyramid.httpexceptions import HTTPBadRequest from occams import models cycle = models.Cycle(name='week-1', title=u'', week=1) schema = models.Schema(name=u'sample', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle]) site = models.Site(name=u'ucsd', title=u'UCSD') t_a = date.today() + timedelta(days=5) patient_a = models.Patient(site=site, pid=u'12345') visit_a = models.Visit(patient=patient_a, cycles=[cycle], visit_date=t_a) dbsession.add_all([schema, visit_a, study]) dbsession.flush() req.json_body = { 'schema': schema.id, } with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(visit_a['forms'], req) assert 'is not part of the studies' in \ excinfo.value.json['errors']['schema']
def test_add_to_visit(self, req, dbsession): from datetime import date from occams import models schema = models.Schema(name=u'schema', title=u'Schema', publish_date=date.today()) study = models.Study(name='some-study', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([schema])) cycle = models.Cycle(study=study, name=u'cycle-1', title=u'Cycle') site = models.Site(name=u'somewhere', title=u'Somewhere') patient = models.Patient(pid=u'12345', site=site) visit = models.Visit(patient=patient, visit_date=date.today(), cycles=[cycle]) dbsession.add_all([study, patient, visit]) dbsession.flush() req.matchdict = {'patient': patient, 'visit': visit} req.json_body = { 'schema': schema.id, 'collect_date': str(date.today()), } factory = models.FormFactory(req) factory.__parent__ = visit self._call_fut(factory, req) contexts = dbsession.query(models.Context).all() assert len(contexts) == 2 assert sorted(['patient', 'visit']) == \ sorted([c.external for c in contexts])
def test_update_patient(self, req, dbsession, check_csrf_token): """ It should also mark the patient as modified """ from datetime import date from occams import models patient = models.Patient( site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') visit = models.Visit( patient=patient, visit_date=date.today()) dbsession.add_all([patient, visit]) dbsession.flush() old_modify_date = patient.modify_date self._call_fut(visit, req) assert old_modify_date < patient.modify_date
def test_has_visits(self, req, dbsession, config): """ It should not allow deletion of a cycle if it has visit (unless administrator) """ from datetime import date from pyramid.httpexceptions import HTTPForbidden from occams import models cycle = models.Cycle(name='week-1', title=u'Week 1', week=1) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle]) patient = models.Patient(site=models.Site(name='ucsd', title=u'UCSD'), pid=u'12345') enrollment = models.Enrollment(study=study, consent_date=date.today(), patient=patient) visit = models.Visit(patient=patient, visit_date=date.today(), cycles=[cycle]) dbsession.add_all([study, enrollment, visit]) dbsession.flush() # Should not be able to delete if not an admin config.testing_securitypolicy(permissive=False) with pytest.raises(HTTPForbidden): self._call_fut(cycle, req) config.testing_securitypolicy(permissive=True) self._call_fut(cycle, req) assert 0 == study.cycles.count()
def test_visit(self, dbsession): """ It should add visit-specific metadata to the report """ from datetime import date, timedelta from occams import models as datastore from occams import models from occams.exports.schema import SchemaPlan schema = datastore.Schema(name=u'vitals', title=u'Vitals', publish_date=date.today(), attributes={ 'foo': datastore.Attribute( name='foo', title=u'', type='string', order=0, ) }) entity = datastore.Entity(collect_date=date.today(), schema=schema) patient = models.Patient(site=models.Site(name='ucsd', title=u'UCSD'), pid=u'12345', entities=[entity]) visit = models.Visit( visit_date=date.today(), patient=patient, cycles=[ models.Cycle(name=u'study1-scr', title=u'Study 1 Screening', week=123, study=models.Study(name=u'study1', short_title=u'S1', code=u'001', consent_date=date.today() - timedelta(365), title=u'Study 1')), models.Cycle(name=u'study2-wk1', title=u'Study 2 Week 1', week=5858, study=models.Study(name=u'study21', short_title=u'S2', code=u'002', consent_date=date.today() - timedelta(365), title=u'Study 2')) ], entities=[entity]) dbsession.add_all([schema, entity, patient, visit]) dbsession.flush() plan = SchemaPlan.from_schema(dbsession, schema.name) codebook = list(plan.codebook()) query = plan.data() codebook_columns = [c['field'] for c in codebook] data_columns = [c['name'] for c in query.column_descriptions] record = query.one() assert sorted(codebook_columns) == sorted(data_columns) assert record.site == patient.site.name assert record.pid == patient.pid assert record.enrollment is None cyclefmt = '{cycle.study.title}({cycle.week})' assert sorted(record.visit_cycles.split(';')) == \ sorted([cyclefmt.format(cycle=c) for c in visit.cycles]) assert str(record.visit_id) == str(visit.id) assert record.collect_date == entity.collect_date