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_entity_force_date(dbsession): """ It should maintain a date object for date types. (Sometimes applications will blindly assign datetimes...) """ from datetime import date, datetime from occams import models schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) entity = models.Entity(schema=schema) # Do simple values simpleName = 'choicesimple' schema.attributes[simpleName] = models.Attribute(schema=schema, parent_attribute=s1, title=u'', type='date', is_required=False, order=1) now = datetime.now() today = now.date() entity[simpleName] = now dbsession.flush() assert isinstance(entity[simpleName], date) assert today == entity[simpleName]
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 test_entity_add_unpublished_schema(dbsession): """ It should not allow adding entities related to unpublished schemata """ from occams import models from occams.exc import InvalidEntitySchemaError schema = models.Schema(name=u'Foo', title=u'') entity = models.Entity(schema=schema) dbsession.add(entity) with pytest.raises(InvalidEntitySchemaError): dbsession.flush()
def test_choice_constraint(dbsession): """ It should validate against choice constraints """ from datetime import date from occams import models from occams.exc import ConstraintError schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) models.Attribute(schema=schema, parent_attribute=s1, name=u'test', title=u'', type=u'choice', is_required=False, order=0, choices={ '001': models.Choice(name=u'001', title=u'Foo', order=0), '002': models.Choice(name=u'002', title=u'Bar', order=1), '003': models.Choice(name=u'003', title=u'Baz', order=2) }) dbsession.add(schema) dbsession.flush() entity = models.Entity(schema=schema) dbsession.add(entity) entity['test'] = None entity['test'] = u'002' dbsession.flush() entry = (dbsession.query(models.ValueChoice).filter( models.ValueChoice.value.has(name=u'002')).one()) assert entry.value.name == '002' # Should not be able to set it to something outside of the specified # choice constraints with pytest.raises(ConstraintError): entity['test'] = u'999'
def test_enrollment(self, dbsession): """ It should add enrollment-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'termination', title=u'Termination', publish_date=date.today(), attributes={ 'foo': datastore.Attribute( name='foo', title=u'', type='string', order=0, ) }) entity = datastore.Entity(schema=schema, collect_date=date.today()) patient = models.Patient(site=models.Site(name='ucsd', title=u'UCSD'), pid=u'12345', entities=[entity]) study = models.Study(name=u'cooties', short_title=u'CTY', code=u'999', consent_date=date.today() - timedelta(365), title=u'Cooties') enrollment = models.Enrollment( patient=patient, study=study, consent_date=date.today() - timedelta(5), latest_consent_date=date.today() - timedelta(3), termination_date=date.today(), entities=[entity]) dbsession.add_all([schema, entity, patient, study, enrollment]) 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 == enrollment.study.name assert record.enrollment_ids == str(enrollment.id) assert record.visit_cycles is None assert record.collect_date == entity.collect_date
def test_entity_default_collect_date(dbsession): """ It should default to today's date as the collect_date if not is provided """ from datetime import date from occams import models # Make sure the system can auto-assign a collect date for the entry schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) entity = models.Entity(schema=schema) dbsession.add(entity) dbsession.flush() assert date.today() == entity.collect_date # If one is supplied by the user, don't do anything collect_date = date(2010, 9, 1) entity = models.Entity(schema=schema, collect_date=collect_date) dbsession.add(entity) dbsession.flush() assert entity.collect_date == collect_date
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_build_report_context(dbsession): """ It should be able to associate with a context. (for easier joins) """ from datetime import date from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute(name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type='string', is_private=True, order=1) }) }) dbsession.add(schema1) dbsession.flush() entity1 = models.Entity(schema=schema1) entity1['a'] = u'002' dbsession.add(entity1) dbsession.flush() dbsession.add(models.Context(external='sometable', key=123, entity=entity1)) dbsession.flush() # not specified report = reporting.build_report(dbsession, u'A') assert 'context_key' not in report.c # specified report = reporting.build_report(dbsession, u'A', context='sometable') result = dbsession.query(report).one() assert 'context_key' in report.c assert result.context_key == 123
def test_build_report_ignore_private(dbsession): """ It should be able to de-identify private data upon request """ from datetime import date from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute(name=u's1', title=u'S1', type='section', order=0, attributes={ 'name': models.Attribute( name=u'name', title=u'', type='string', is_private=True, order=1) }) }) dbsession.add(schema1) dbsession.flush() # add some entries for the schema entity1 = models.Entity(schema=schema1) entity1['name'] = u'Jane Doe' dbsession.add(entity1) dbsession.flush() # not de-identified report = reporting.build_report(dbsession, u'A', ignore_private=False) result = dbsession.query(report).one() assert entity1[u'name'] == result.name # de-identified report = reporting.build_report(dbsession, u'A', ignore_private=True) result = dbsession.query(report).one() assert '[PRIVATE]' == result.name
def check_value_min_constraint(dbsession, type_, limit, below, equal, over): """ It should validate against minimum constratins """ from datetime import date from occams import models from occams.exc import ConstraintError schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) entity = models.Entity(schema=schema) dbsession.add(entity) dbsession.flush() models.Attribute(schema=schema, parent_attribute=s1, name=type_, title=u'', type=type_, is_required=False, value_min=limit, order=0) with pytest.raises(ConstraintError): entity[type_] = below entity[type_] = None entity[type_] = equal entity[type_] = over models.Attribute(schema=schema, parent_attribute=s1, name=u'boolean', title=u'', type=u'boolean', value_min=10, order=1) with pytest.raises(NotImplementedError): entity['boolean'] = True
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])) state = (dbsession.query( models.State).filter_by(name=u'pending-entry').one()) dbsession.add( models.Entity(state=state, schema=form, collect_date=date(2015, 2, 1))) dbsession.add( models.Enrollment(patient=patient, study=study, consent_date=date(2014, 12, 22)))
def test_build_report_datetime(dbsession): """ It should be able to cast DATE/DATETIME """ from datetime import date from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute(name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type='date', order=1) }) }) dbsession.add(schema1) dbsession.flush() # add some entries for the schema entity1 = models.Entity(schema=schema1) entity1['a'] = date(1976, 7, 4) dbsession.add(entity1) dbsession.flush() report = reporting.build_report(dbsession, u'A') result = dbsession.query(report).one() assert str(result.a) == '1976-07-04' schema1.attributes['s1'].attributes['a'].type = 'datetime' dbsession.flush() report = reporting.build_report(dbsession, u'A') result = dbsession.query(report).one() assert str(result.a) == '1976-07-04 00:00:00'
def test_entity_blob_type(dbsession): """ It should be able to keep track of file uploads (will not be storing in DB) """ from occams import models from datetime import date schema = models.Schema(name='HasBlob', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) schema.attributes['theblob'] = models.Attribute(parent_attribute=s1, name=u'theblob', title=u'', type='blob', order=0) entity = models.Entity(schema=schema) dbsession.add(entity) dbsession.flush() entity_id = entity.id # Add value entity['theblob'] = models.BlobInfo(file_name=u'foo', path='bar/baz.gif') dbsession.add(entity) dbsession.flush() entity = dbsession.query(models.Entity).get(entity_id) blob = entity['theblob'] assert u'foo' == blob.file_name assert 'bar/baz.gif' == blob.path # Clear value entity['theblob'] = None dbsession.flush() entity = dbsession.query(models.Entity).get(entity_id) blob = entity['theblob'] assert blob is None
def test_list_not_include_rand(self, dbsession): """ It should not include randomization data if specified. """ 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) study = models.Study(name=u'study1', short_title=u'S1', code=u'001', consent_date=date.today() - timedelta(365), title=u'Study 1') armga = models.Arm(name=u'groupa', title=u'GROUP A', study=study) stratum = models.Stratum(study=study, arm=armga, block_number=12384, randid=u'8484', entities=[entity]) dbsession.add_all([schema, entity, stratum]) dbsession.flush() plans = SchemaPlan.list_all(dbsession, include_private=True) assert len(plans) == 1 plans = SchemaPlan.list_all(dbsession, include_rand=False) assert len(plans) == 0
def test_patient(self, dbsession): """ It should add patient-specific metadata to the report """ from datetime import date from occams import models as datastore from occams import models from occams.exports.schema import SchemaPlan schema = datastore.Schema(name=u'contact', title=u'Contact Details', publish_date=date.today(), attributes={ 'foo': datastore.Attribute( name='foo', title=u'', type='string', order=0, ) }) entity = datastore.Entity(schema=schema, collect_date=date.today()) patient = models.Patient(site=models.Site(name='ucsd', title=u'UCSD'), pid=u'12345', entities=[entity]) dbsession.add_all([schema, entity, patient]) 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 assert record.visit_cycles is None assert record.visit_date is None assert record.collect_date == entity.collect_date
def test_build_report_scalar_values(dbsession): """ It should properly report scalar values """ from datetime import date from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute(name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type='string', order=1) }) }) dbsession.add(schema1) dbsession.flush() # add some entries for the schema entity1 = models.Entity(schema=schema1) entity1['a'] = u'foovalue' dbsession.add(entity1) dbsession.flush() report = reporting.build_report(dbsession, u'A') result = dbsession.query(report).one() assert entity1[u'a'] == result.a
def test_without_state(self, req, dbsession): """ It should generate none if no state data is available """ import mock from occams import models from datetime import date myfirst = models.Schema(name=u'myfirst', title=u'My First Schema', publish_date=date.today()) mydata = models.Entity(schema=myfirst) dbsession.add(mydata) dbsession.flush() mydata.__parent__ = mock.MagicMock() mydata.__parent__.__parent__ = mock.MagicMock() req.session.changed = mock.Mock() res = self._call_fut(mydata, req) assert res['state'] is None
def test_validator_pattern_constraint(dbsession): """ It should validate against string pattern constraints """ from datetime import date from occams import models from occams.exc import ConstraintError schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) models.Attribute( schema=schema, parent_attribute=s1, name=u'test', title=u'', type=u'string', is_required=False, # Valid US phone number pattern=r'\d{3}-\d{3}-\d{4}', order=0) dbsession.add(schema) dbsession.flush() entity = models.Entity(schema=schema) dbsession.add(entity) entity['test'] = None with pytest.raises(ConstraintError): entity['test'] = u'trollol' entity['test'] = u'123-456-7890' dbsession.flush() assert '123-456-7890' == entity['test']
def test_validator_max_constraint(dbsession): """ It should validate string/number value min/max """ from datetime import date from occams import models from occams.exc import ConstraintError schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) models.Attribute(schema=schema, parent_attribute=s1, name=u'test', title=u'', type=u'string', is_required=False, value_max=3, order=0) dbsession.add(schema) dbsession.flush() entity = models.Entity(schema=schema) dbsession.add(entity) entity['test'] = None with pytest.raises(ConstraintError): entity['test'] = u'foobar' entity['test'] = u'foo' dbsession.flush() assert 'foo' == entity['test']
def test_with_state(self, req, dbsession): """ It should generate state data is available """ from datetime import date import mock from occams import models myfirst = models.Schema(name=u'myfirst', title=u'My First Schema', publish_date=date.today()) mydata = models.Entity(schema=myfirst, state=(dbsession.query(models.State).filter_by( name=u'pending-entry').one())) dbsession.add(mydata) dbsession.flush() mydata.__parent__ = mock.MagicMock() mydata.__parent__.__parent__ = mock.MagicMock() req.session.changed = mock.Mock() res = self._call_fut(mydata, req) assert res['state'] is not None
def test_state_entity_relationship(dbsession): """ It should implement state/entity relationship """ from datetime import date from occams import models schema = models.Schema(name=u'Foo', title=u'Foo', publish_date=date(2000, 1, 1)) pending_entry = \ dbsession.query(models.State).filter_by(name=u'pending-entry').one() entity = models.Entity(schema=schema) dbsession.add_all([pending_entry, entity]) dbsession.flush() assert entity.state is None assert pending_entry.entities.count() == 0 entity.state = pending_entry dbsession.flush() assert entity.state is not None assert pending_entry.entities.count() == 1
def test_cascade_entities(self, req, dbsession, check_csrf_token): """ It should delete associated entities """ from datetime import date from occams import models as datastore from occams import models schema = datastore.Schema(name=u'somepatientform', title=u'Some Patient Form', publish_date=date.today()) entity = datastore.Entity(collect_date=date.today(), schema=schema) patient = models.Patient(site=models.Site(name=u'la', title=u'LA'), pid=u'12345') patient.entities.add(entity) dbsession.add_all([patient, entity, schema]) dbsession.flush() patient = dbsession.query(models.Patient).one() self._call_fut(patient, req) assert 0 == dbsession.query(datastore.Entity).count()
def test_entity_choices(dbsession): """ It should properly handle choices """ from datetime import date from occams import models schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1)) s1 = models.Attribute(schema=schema, name='s1', title=u'Section 1', type='section', order=0) entity = models.Entity(schema=schema) dbsession.add(entity) dbsession.flush() # Do simple values simpleName = 'choicesimple' schema.attributes[simpleName] = models.Attribute( schema=schema, parent_attribute=s1, name=simpleName, title=u'', type='choice', is_required=False, order=1, choices={ '001': models.Choice(name=u'001', title=u'Foo', order=1), '002': models.Choice(name=u'002', title=u'Bar', order=2), '003': models.Choice(name=u'003', title=u'Baz', order=3), '004': models.Choice(name=u'004', title=u'Caz', order=4), '005': models.Choice(name=u'005', title=u'Jaz', order=5), }) entity[simpleName] = None dbsession.flush() assert entity[simpleName] is None entity[simpleName] = u'002' dbsession.flush() assert u'002' == entity[simpleName] # Now try collections collectionName = 'choicecollection' schema.attributes[collectionName] = models.Attribute( schema=schema, parent_attribute=s1, name=collectionName, title=u'', type='choice', is_collection=True, order=2, choices={ '001': models.Choice(name=u'001', title=u'Foo', order=1), '002': models.Choice(name=u'002', title=u'Bar', order=2), '003': models.Choice(name=u'003', title=u'Baz', order=3), '004': models.Choice(name=u'004', title=u'Caz', order=4), '005': models.Choice(name=u'005', title=u'Jaz', order=5) }) entity[collectionName] = [u'001', u'002', u'005'] dbsession.flush() assert sorted([u'001', u'002', u'005']) == \ sorted(entity['choicecollection'])
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
def test_rand(self, dbsession): """ It should add randomization-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]) study = models.Study(name=u'study1', short_title=u'S1', code=u'001', consent_date=date.today() - timedelta(365), title=u'Study 1') armga = models.Arm(name=u'groupa', title=u'GROUP A', study=study) stratum = models.Stratum(study=study, arm=armga, block_number=12384, randid=u'8484', patient=patient, entities=[entity]) enrollment = models.Enrollment( patient=patient, study=study, consent_date=date.today() - timedelta(5), latest_consent_date=date.today() - timedelta(3), termination_date=date.today(), entities=[entity]) dbsession.add_all([schema, entity, patient, enrollment, stratum]) 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 == enrollment.study.name assert record.enrollment_ids == str(enrollment.id) assert record.collect_date == entity.collect_date assert record.block_number == stratum.block_number assert record.arm_name == stratum.arm.title assert record.randid == stratum.randid
def test_build_report_choice_types(dbsession): """ It should be able to use choice labels instead of codes. (for human readibily) """ from datetime import date from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute( name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type='choice', is_collection=False, order=0, choices={ '001': models.Choice(name=u'001', title=u'Green', order=0), '002': models.Choice(name=u'002', title=u'Red', order=1), '003': models.Choice(name=u'003', title=u'Blue', order=2) }) }) }) dbsession.add(schema1) dbsession.flush() entity1 = models.Entity(schema=schema1) entity1['a'] = u'002' dbsession.add(entity1) dbsession.flush() # labels off report = reporting.build_report(dbsession, u'A', use_choice_labels=False) result = dbsession.query(report).one() assert result.a == '002' # labels on report = reporting.build_report(dbsession, u'A', use_choice_labels=True) result = dbsession.query(report).one() assert result.a == 'Red' # switch to multiple-choice schema1.attributes['a'].is_collection = True entity1['a'] = ['002', '003'] dbsession.flush() # delimited multiple-choice, labels off report = reporting.build_report(dbsession, u'A', expand_collections=False, use_choice_labels=False) result = dbsession.query(report).one() assert sorted(result.a.split(';')) == sorted(['002', '003']) # delimited multiple-choice, labels on report = reporting.build_report(dbsession, u'A', expand_collections=False, use_choice_labels=True) result = dbsession.query(report).one() assert sorted(result.a.split(';')) == sorted(['Red', 'Blue']) # expanded multiple-choice, labels off report = reporting.build_report(dbsession, u'A', expand_collections=True, use_choice_labels=False) result = dbsession.query(report).one() assert result.a_001 == 0 assert result.a_002 == 1 assert result.a_003 == 1 # expanded multiple-choice, labels on report = reporting.build_report(dbsession, u'A', expand_collections=True, use_choice_labels=True) result = dbsession.query(report).one() assert result.a_001 is None assert result.a_002 == 'Red' assert result.a_003 == 'Blue'
def test_build_report_expand_none_selected(dbsession): """ It should leave all choices blank (not zero) on if no option was selected """ from datetime import date from occams import models, reporting today = date.today() schema1 = models.Schema(name=u'A', title=u'A', publish_date=today, attributes={ 's1': models.Attribute( name=u's1', title=u'S1', type='section', order=0, attributes={ 'a': models.Attribute( name=u'a', title=u'', type='choice', is_collection=True, order=1, choices={ '001': models.Choice(name=u'001', title=u'Green', order=0), '002': models.Choice(name=u'002', title=u'Red', order=1), '003': models.Choice(name=u'003', title=u'Blue', order=2) }) }) }) dbsession.add(schema1) dbsession.flush() entity1 = models.Entity(schema=schema1) dbsession.add(entity1) dbsession.flush() # delimited multiple-choice, labels off report = reporting.build_report(dbsession, u'A', expand_collections=False, use_choice_labels=False) result = dbsession.query(report).one() assert result.a is None # delimited multiple-choice, labels on report = reporting.build_report(dbsession, u'A', expand_collections=False, use_choice_labels=True) result = dbsession.query(report).one() assert result.a is None # expanded multiple-choice, labels off report = reporting.build_report(dbsession, u'A', expand_collections=True, use_choice_labels=False) result = dbsession.query(report).one() assert result.a_001 is None assert result.a_002 is None assert result.a_003 is None # expanded multiple-choice, labels on report = reporting.build_report(dbsession, u'A', expand_collections=True, use_choice_labels=True) result = dbsession.query(report).one() assert result.a_001 is None assert result.a_002 is None assert result.a_003 is None
def check_entity_types(dbsession, type, simple, update, collection): """ It should properly handle supported types """ from datetime import date from occams import models schema = models.Schema(name=u'Foo', title=u'', publish_date=date(2000, 1, 1), attributes={ 's1': models.Attribute(name='s1', title=u'Section 1', type='section', order=1) }) entity = models.Entity(schema=schema) dbsession.add(entity) dbsession.flush() order = 1 ModelClass = models.nameModelMap[type] # Do simple values simpleName = type + 'simple' # Try null first schema.attributes['s1'].attributes[simpleName] = models.Attribute( name=simpleName, title=u'', type=type, is_required=False, order=order) assert entity[simpleName] is None entity[simpleName] = None dbsession.flush() assert entity[simpleName] is None # Update value entity[simpleName] = simple dbsession.flush() assert simple == entity[simpleName] # Double check auditing valueQuery = (dbsession.query(ModelClass).filter_by( attribute=schema.attributes[simpleName])) valueObject = valueQuery.one() assert 1 == valueObject.revision # Update again entity[simpleName] = update dbsession.flush() assert update == entity[simpleName] # Triple check auditing valueObject = valueQuery.one() assert 2 == valueObject.revision order += 1 # Now try collections collectionName = type + 'collection' schema.attributes['s1'].attributes[collectionName] = models.Attribute( name=collectionName, schema=schema, title=u'', type=type, is_collection=True, order=order) entity[collectionName] = collection dbsession.flush() assert set(collection) == set(entity[collectionName]) valueQuery = (dbsession.query(ModelClass).filter_by( attribute=schema.attributes[collectionName])) order += 1 # Make sure we can also update entity[collectionName] = collection[:2] dbsession.flush() assert set(collection[:2]) == set(entity[collectionName]) assert 2 == valueQuery.count() # Lists are not audited, they're just removed and a new one is # set assert sorted([1, 1]) == sorted([v.revision for v in valueQuery])