def _call_fut(self, *args, **kw): from occams_forms.renderers import apply_data return apply_data(*args, **kw)
def form(context, request): """ XXX: Cannot merge into single view because of the way patient forms are handled """ db_session = request.db_session patient = context.__parent__.__parent__ schema = context.schema (is_phi, ) = (db_session.query( db_session.query(models.patient_schema_table).filter_by( schema_id=schema.id).exists()).one()) if not is_phi: previous_url = request.current_route_path( _route_name='studies.patient_forms') show_metadata = True # We cannot determine which study this form will be applied to # so just use any version from active studies available_schemata = (db_session.query(datastore.Schema).join( models.study_schema_table).join(models.Study).filter( datastore.Schema.name == context.schema.name).filter( datastore.Schema.publish_date != sa.null()).filter( datastore.Schema.retract_date == sa.null())) allowed_versions = sorted( set(s.publish_date for s in available_schemata)) else: previous_url = request.current_route_path( _route_name='studies.patient') show_metadata = False allowed_versions = None if request.has_permission('retract'): transition = modes.ALL elif request.has_permission('transition'): transition = modes.AVAILABLE else: transition = modes.AUTO Form = make_form( db_session, context.schema, entity=context, show_metadata=show_metadata, transition=transition, allowed_versions=allowed_versions, ) form = Form(request.POST, data=entity_data(context)) if request.method == 'POST': if not request.has_permission('edit', context): raise HTTPForbidden() if form.validate(): upload_dir = request.registry.settings['studies.blob.dir'] apply_data(db_session, context, form.data, upload_dir) db_session.flush() request.session.flash( _(u'Changes saved to: %s' % context.schema.title), 'success') return HTTPFound(location=previous_url) return { 'phi': get_phi_entities(patient, request), 'patient': view_json(patient, request), 'form': render_form(form, disabled=not request.has_permission('edit'), cancel_url=previous_url, attr={ 'method': 'POST', 'action': request.current_route_path(), 'role': 'form' }), }
def terminate_ajax(context, request): db_session = request.db_session try: entity = ( db_session.query(datastore.Entity) .join(datastore.Entity.schema) .filter(datastore.Schema.name.in_( # Only search for forms being used as temrination forms db_session.query(datastore.Schema.name) .join(models.Study.termination_schema) .subquery())) .join(datastore.Context) .filter_by(external='enrollment', key=context.id) .one()) except orm.exc.MultipleResultsFound: raise Exception('Should only have one...') except orm.exc.NoResultFound: schema = context.study.termination_schema entity = datastore.Entity(schema=schema) # XXX: This is really bad form as we're applying # side-effects to a GET request, but there is no time # to make this look prety... # If you remove this line you will be creating random termination # entries... context.entities.add(entity) else: schema = entity.schema if not entity.state: entity.state = ( db_session.query(datastore.State) .filter_by(name='pending-entry') .one()) if 'termination_date' not in schema.attributes: msg = 'There is no "termination_date" configured on: {}' log.warn(msg.format(schema.name)) if request.has_permission('retract'): transition = modes.ALL elif request.has_permission('transition'): transition = modes.AVAILABLE else: transition = modes.AUTO Form = make_form( db_session, schema, entity=entity, transition=transition, show_metadata=False) form = Form(request.POST, data=entity_data(entity)) def validate_termination_date(form, field): if not (field.data >= context.latest_consent_date): raise wtforms.ValidationError(request.localizer.translate( _(u'Termination must be on or after latest consent (${date})'), mapping={'date': context.latest_consent_date} )) # Inject a validator into the termination form so that we # ensure that the termination date provided is valid form.termination_date.validators.append(validate_termination_date) if request.method == 'POST': check_csrf_token(request) if form.validate(): if not entity.id: # changing termination version *should* not be # allowed, just assign the schema that's already being used context.entities.add(entity) upload_dir = request.registry.settings['studies.blob.dir'] apply_data(db_session, entity, form.data, upload_dir) context.termination_date = form.termination_date.data db_session.flush() return HTTPOk(json=view_json(context, request)) else: return HTTPBadRequest(json={'errors': wtferrors(form)}) return render_form( form, cancel_url=request.current_route_path(_route_name='studies.patient'), attr={ 'method': 'POST', 'action': request.current_route_path(), 'role': 'form', 'data-bind': 'formentry: {}, submit: $root.terminateEnrollment' } )
def apply_direct_mappings(task): # get all the direct mappings for processing mappings = ( Session.query(models.Mapping) .filter_by(type=u'direct').all() ) default_state = ( Session.query(datastore.State) .filter_by(name='pending-entry') .one() ) redis = app.redis total_mappings = len(mappings) count = 0 mappings_id = six.text_type(str(uuid.uuid4())) redis.hmset(mappings_id, { 'count': count, 'total': total_mappings }) for mapping in mappings: source_schema_name = mapping.logic['source_schema'] source_schema_publish_date = mapping.logic['source_schema_publish_date'] source_variable = mapping.logic['source_variable'] target_schema_name = mapping.logic['target_schema'] target_schema_publish_date = mapping.logic['target_schema_publish_date'] target_variable = mapping.logic['target_variable'] # get records that have a matching schema for source schema records = ( Session.query(models.SiteData) .filter( models.SiteData.data['form_name'].astext == source_schema_name ) .filter( models.SiteData.data['form_publish_date'].astext == source_schema_publish_date ).all() ) for record in records: pid = record.data['pid'] collect_date = record.data['collect_date'] patient = ( Session.query(studies.Patient) .filter_by(pid=pid) .one() ) target_schema = ( Session.query(datastore.Schema) .filter_by(name=target_schema_name) .filter_by(publish_date=target_schema_publish_date) ).one() # if the target schema already exists we want to add data # to the schema rather than creating a new entity entity_exists = False for item in patient.entities: if item.schema.name == target_schema_name and \ item.schema.publish_date.isoformat() == \ target_schema_publish_date: entity = item entity_exists = True break if not entity_exists: entity = datastore.Entity( schema=target_schema, collect_date=collect_date, state=default_state ) patient.entities.add(entity) if mapping.logic['choices_mapping']: # add handling if there is no value to map source_key = record.data.get(source_variable) payload = {target_variable: source_key} upload_dir = tempfile.mkdtemp() apply_data(Session, entity, payload, upload_dir) shutil.rmtree(upload_dir) else: # non-choices processing source_key = record.data.get(source_variable) payload = {target_variable: source_key} upload_dir = tempfile.mkdtemp() apply_data(Session, entity, payload, upload_dir) shutil.rmtree(upload_dir) redis.hincrby(mappings_id, 'count') data = redis.hgetall(mappings_id) # redis-py returns everything as string, so we need to clean it for key in ('count', 'total'): data[key] = int(data[key]) redis.publish('direct', json.dumps(data))
def populate_project( db_session, project_name, consolidated_frame, pid_column=DEFAULT_PID_COLUMN, visit_column=DEFAULT_VISIT_COLUMN, collect_date_column=DEFAULT_COLLECT_DATE_COLUMN, ): """ Processes a final dataframe (i.e. a frame after mappings have been applied) and creates entities for the target project. :param db_session: Current database transaction session :type db_session: sqlalchemy.orm.session.Session :param project_name: study where entities will be applied :type project_name: str :param consolidated_frame: dataframe populated with mapped variables :type consolidated_frame: pandas.DataFrame :returns: none """ site = db_session.query(studies.Site).filter_by(name=project_name).one() project = (db_session.query( studies.Study).filter_by(name=project_name).one()) default_state = (db_session.query( datastore.State).filter_by(name='pending-entry').one()) for index, row in consolidated_frame.iterrows(): pid = row['pid'] try: patient = (db_session.query( studies.Patient).filter_by(pid=pid).one()) except orm.exc.NoResultFound: patient = studies.Patient(site=site, pid=pid) db_session.add(patient) db_session.flush() for schema in project.schemata: payload = {} for attribute in schema.iterleafs(): column_name = '_'.join( [project.name, schema.name, attribute.name]) if column_name not in row: continue value = row[column_name] if isinstance(value, numbers.Number) and math.isnan(value): continue payload[attribute.name] = value # Avoid creating empty records if not payload: continue calculated_collect_date_column = '_'.join( [project.name, schema.name, collect_date_column]) collect_date = row[calculated_collect_date_column] entity = datastore.Entity(schema=schema, collect_date=collect_date, state=default_state) patient.entities.add(entity) upload_dir = tempfile.mkdtemp() apply_data(db_session, entity, payload, upload_dir) shutil.rmtree(upload_dir) db_session.flush()
def form(context, request): """ XXX: Cannot merge into single view because of the way patient forms are handled """ db_session = request.db_session patient = context.__parent__.__parent__ schema = context.schema (is_phi,) = ( db_session.query( db_session.query(models.patient_schema_table) .filter_by(schema_id=schema.id) .exists()) .one()) if not is_phi: previous_url = request.current_route_path( _route_name='studies.patient_forms') show_metadata = True # We cannot determine which study this form will be applied to # so just use any version from active studies available_schemata = ( db_session.query(datastore.Schema) .join(models.study_schema_table) .join(models.Study) .filter(datastore.Schema.name == context.schema.name) .filter(datastore.Schema.publish_date != sa.null()) .filter(datastore.Schema.retract_date == sa.null())) allowed_versions = sorted(set( s.publish_date for s in available_schemata)) else: previous_url = request.current_route_path( _route_name='studies.patient') show_metadata = False allowed_versions = None if request.has_permission('retract'): transition = modes.ALL elif request.has_permission('transition'): transition = modes.AVAILABLE else: transition = modes.AUTO Form = make_form( db_session, context.schema, entity=context, show_metadata=show_metadata, transition=transition, allowed_versions=allowed_versions, ) form = Form(request.POST, data=entity_data(context)) if request.method == 'POST': if not request.has_permission('edit', context): raise HTTPForbidden() if form.validate(): upload_dir = request.registry.settings['studies.blob.dir'] apply_data(db_session, context, form.data, upload_dir) db_session.flush() request.session.flash( _(u'Changes saved to: %s' % context.schema.title), 'success') return HTTPFound(location=previous_url) return { 'phi': get_phi_entities(patient, request), 'patient': view_json(patient, request), 'form': render_form( form, disabled=not request.has_permission('edit'), cancel_url=previous_url, attr={ 'method': 'POST', 'action': request.current_route_path(), 'role': 'form' } ), }
def populate_project( db_session, project_name, consolidated_frame, pid_column=DEFAULT_PID_COLUMN, visit_column=DEFAULT_VISIT_COLUMN, collect_date_column=DEFAULT_COLLECT_DATE_COLUMN, ): """ Processes a final dataframe (i.e. a frame after mappings have been applied) and creates entities for the target project. :param db_session: Current database transaction session :type db_session: sqlalchemy.orm.session.Session :param project_name: study where entities will be applied :type project_name: str :param consolidated_frame: dataframe populated with mapped variables :type consolidated_frame: pandas.DataFrame :returns: none """ site = db_session.query(studies.Site).filter_by(name=project_name).one() project = ( db_session.query(studies.Study) .filter_by(name=project_name) .one() ) default_state = ( db_session.query(datastore.State) .filter_by(name='pending-entry') .one() ) for index, row in consolidated_frame.iterrows(): pid = row['pid'] try: patient = ( db_session.query(studies.Patient) .filter_by(pid=pid) .one() ) except orm.exc.NoResultFound: patient = studies.Patient(site=site, pid=pid) db_session.add(patient) db_session.flush() for schema in project.schemata: payload = {} for attribute in schema.iterleafs(): column_name = '_'.join([ project.name, schema.name, attribute.name ]) if column_name not in row: continue value = row[column_name] if isinstance(value, numbers.Number) and math.isnan(value): continue payload[attribute.name] = value # Avoid creating empty records if not payload: continue calculated_collect_date_column = '_'.join([ project.name, schema.name, collect_date_column ]) collect_date = row[calculated_collect_date_column] entity = datastore.Entity( schema=schema, collect_date=collect_date, state=default_state ) patient.entities.add(entity) upload_dir = tempfile.mkdtemp() apply_data(db_session, entity, payload, upload_dir) shutil.rmtree(upload_dir) db_session.flush()
def form(context, request): """ XXX: Cannot merge into single view because of the way patient forms are handled """ db_session = request.db_session visit = context.__parent__.__parent__ allowed_schemata = (db_session.query(datastore.Schema).join( models.study_schema_table).join(models.Study).join( models.Cycle).filter( datastore.Schema.name == context.schema.name).filter( models.Cycle.id.in_([cycle.id for cycle in visit.cycles]))) allowed_versions = [s.publish_date for s in allowed_schemata] if request.has_permission('retract'): transition = modes.ALL elif request.has_permission('transition'): transition = modes.AVAILABLE else: transition = modes.AUTO Form = make_form( db_session, context.schema, entity=context, show_metadata=True, transition=transition, allowed_versions=allowed_versions, ) form = Form(request.POST, data=entity_data(context)) if request.method == 'POST': if not request.has_permission('edit', context): raise HTTPForbidden() if form.validate(): upload_dir = request.registry.settings['studies.blob.dir'] apply_data(db_session, context, form.data, upload_dir) db_session.flush() request.session.flash( _(u'Changes saved for: ${form}', mapping={'form': context.schema.title}), 'success') return HTTPFound(location=request.current_route_path( _route_name='studies.visit')) return { 'visit': view_json(visit, request), 'form': render_form( form, disabled=not request.has_permission('edit'), cancel_url=request.current_route_path(_route_name='studies.visit'), attr={ 'method': 'POST', 'action': request.current_route_path(), 'role': 'form' }), }
def terminate_ajax(context, request): db_session = request.db_session try: entity = ( db_session.query(datastore.Entity).join( datastore.Entity.schema).filter( datastore.Schema.name.in_( # Only search for forms being used as temrination forms db_session.query(datastore.Schema.name).join( models.Study.termination_schema ).subquery())).join(datastore.Context).filter_by( external='enrollment', key=context.id).one()) except orm.exc.MultipleResultsFound: raise Exception('Should only have one...') except orm.exc.NoResultFound: schema = context.study.termination_schema entity = datastore.Entity(schema=schema) # XXX: This is really bad form as we're applying # side-effects to a GET request, but there is no time # to make this look prety... # If you remove this line you will be creating random termination # entries... context.entities.add(entity) context.patient.entities.add(entity) else: schema = entity.schema if not entity.state: entity.state = (db_session.query( datastore.State).filter_by(name='pending-entry').one()) if 'termination_date' not in schema.attributes: msg = 'There is no "termination_date" configured on: {}' log.warn(msg.format(schema.name)) if request.has_permission('retract'): transition = modes.ALL elif request.has_permission('transition'): transition = modes.AVAILABLE else: transition = modes.AUTO Form = make_form(db_session, schema, entity=entity, transition=transition, show_metadata=False) form = Form(request.POST, data=entity_data(entity)) def validate_termination_date(form, field): if not (field.data >= context.latest_consent_date): raise wtforms.ValidationError( request.localizer.translate(_( u'Termination must be on or after latest consent (${date})' ), mapping={ 'date': context.latest_consent_date })) # Inject a validator into the termination form so that we # ensure that the termination date provided is valid form.termination_date.validators.append(validate_termination_date) if request.method == 'POST': check_csrf_token(request) if form.validate(): if not entity.id: # changing termination version *should* not be # allowed, just assign the schema that's already being used context.entities.add(entity) upload_dir = request.registry.settings['studies.blob.dir'] apply_data(db_session, entity, form.data, upload_dir) context.termination_date = form.termination_date.data db_session.flush() return HTTPOk(json=view_json(context, request)) else: return HTTPBadRequest(json={'errors': wtferrors(form)}) return render_form( form, cancel_url=request.current_route_path(_route_name='studies.patient'), attr={ 'method': 'POST', 'action': request.current_route_path(), 'role': 'form', 'data-bind': 'formentry: {}, submit: $root.terminateEnrollment' })
def form(context, request): """ XXX: Cannot merge into single view because of the way patient forms are handled """ db_session = request.db_session visit = context.__parent__.__parent__ allowed_schemata = ( db_session.query(datastore.Schema) .join(models.study_schema_table) .join(models.Study) .join(models.Cycle) .filter(models.Cycle.id.in_([cycle.id for cycle in visit.cycles]))) allowed_versions = [s.publish_date for s in allowed_schemata] if request.has_permission('retract'): transition = modes.ALL elif request.has_permission('transition'): transition = modes.AVAILABLE else: transition = modes.AUTO Form = make_form( db_session, context.schema, entity=context, show_metadata=True, transition=transition, allowed_versions=allowed_versions, ) form = Form(request.POST, data=entity_data(context)) if request.method == 'POST': if not request.has_permission('edit', context): raise HTTPForbidden() if form.validate(): upload_dir = request.registry.settings['studies.blob.dir'] apply_data(db_session, context, form.data, upload_dir) db_session.flush() request.session.flash( _(u'Changes saved for: ${form}', mapping={ 'form': context.schema.title}), 'success') return HTTPFound(location=request.current_route_path( _route_name='studies.visit')) return { 'visit': view_json(visit, request), 'form': render_form( form, disabled=not request.has_permission('edit'), cancel_url=request.current_route_path(_route_name='studies.visit'), attr={ 'method': 'POST', 'action': request.current_route_path(), 'role': 'form' } ), }