def test_disabled_if_complete(self, db_session): from occams_datastore import models as datastore from occams_forms.renderers import render_form, states from bs4 import BeautifulSoup Form = self._make_form(db_session) form = Form() form.meta.entity.state = (db_session.query( datastore.State).filter_by(name=states.COMPLETE).one()) markup = render_form(form) soup = BeautifulSoup(markup) field = soup.find(id='dummy_field') assert field.has_attr('disabled')
def test_disabled_if_complete(self, db_session): from occams_datastore import models as datastore from occams_forms.renderers import render_form, states from bs4 import BeautifulSoup Form = self._make_form(db_session) form = Form() form.meta.entity.state = ( db_session.query(datastore.State) .filter_by(name=states.COMPLETE) .one()) markup = render_form(form) soup = BeautifulSoup(markup) field = soup.find(id='dummy_field') assert field.has_attr('disabled')
def markup_ajax(context, request): """ Returns the HTML markup of a form. This usually happens when a user has requested a different version of the form that they are trying to enter. """ db_session = request.db_session version = request.GET.get('version') if not version: raise HTTPBadRequest() if version == context.schema.publish_date.isoformat(): data = entity_data(context) schema = context.schema else: schema = (db_session.query(datastore.Schema).filter_by( name=context.schema.name, publish_date=version).one()) data = None Form = make_form(db_session, schema, show_metadata=False) form = Form(request.POST, data=data) return render_form(form)
def markup_ajax(context, request): """ Returns the HTML markup of a form. This usually happens when a user has requested a different version of the form that they are trying to enter. """ db_session = request.db_session version = request.GET.get('version') if not version: raise HTTPBadRequest() if version == context.schema.publish_date.isoformat(): data = entity_data(context) schema = context.schema else: schema = ( db_session.query(datastore.Schema) .filter_by(name=context.schema.name, publish_date=version) .one()) data = None Form = make_form(db_session, schema, show_metadata=False) form = Form(request.POST, data=data) return render_form(form)
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 randomize_ajax(context, request): """ Procesess a patient's randomiation by completing randomization form Rules: * The user can only randomize one patient at a time. * If another randomization is in progress, both are restarted. * A randomization session may not "continue" from another. In order to address a single randomization at a time, the process assigns a "process id" or ``procid`` for the duration of the process, this way if a new process begins it will have a different token which will not match the current process and nullify everything. This is done by passing the ``procid`` via POST or GET depending on the phase of data entry and matching it against the session-stored ``procid``. If the they do not match, the operation is cancelled. The process goes as follows: # CHALLENGE: Upon first request the user will be issued a ``procid`` token this token will remain unchainged for the duration of the randomization process. If it changes, the process restarts. The goal of the challenge stage is to ensure the user confirms their intent to randomize. # ENTER: After passing the challenge stage, the user will then have opportunity to enter the randomization schema form data that will be used to determine assignement to the study arm. # VERIFY: The user will then have to verify the data again to ensure accurate responses. If the user fails this stage, they will have to pass the ENTER stage again. Upon sucessfull verification the ``procid`` expires and the patient is randomized. The user will not be shown the challenge/entry forms again and only the randomization information information will be rendered for future reference to the user. """ db_session = request.db_session enrollment = context if not enrollment.is_randomized: # Ensure a ``procid`` is assigned for the duration of the process # This way, if a new request mismatches, we can expire the operation if 'procid' not in request.GET and 'procid' not in request.POST: internal_procid = str(uuid.uuid4()) request.session[RAND_INFO_KEY] = { 'procid': internal_procid, 'stage': RAND_CHALLENGE, 'formdata': None } return HTTPFound( location=request.current_route_path( _query={'procid': internal_procid})) external_procid = request.GET.get('procid') or request.POST.get('procid') internal_procid = request.session.get(RAND_INFO_KEY, {}).get('procid') # compare internal and external ID to determine if a new process has # been initiated in a new tab if external_procid is not None and external_procid != internal_procid: try: del request.session[RAND_INFO_KEY] except KeyError: # pragma: no cover pass request.session.flash( _(u'You have another randomization in progress, ' u'starting over.'), 'warning') return HTTPFound(location=request.current_route_path(_query={})) if request.method == 'POST': check_csrf_token(request) if enrollment.is_randomized: request.session.flash( _(u'This patient is already randomized for this study'), 'warning') return HTTPFound(location=request.current_route_path(_query={})) if request.session[RAND_INFO_KEY]['stage'] == RAND_CHALLENGE: Form = _make_challenge_form(enrollment, request) form = Form(request.POST) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) else: request.session[RAND_INFO_KEY]['stage'] = RAND_ENTER request.session.changed() return HTTPFound(location=request.current_route_path( _query={'procid': internal_procid})) elif request.session[RAND_INFO_KEY]['stage'] == RAND_ENTER: Form = make_form( db_session, enrollment.study.randomization_schema, show_metadata=False) form = Form(request.POST) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) else: request.session[RAND_INFO_KEY]['stage'] = RAND_VERIFY request.session[RAND_INFO_KEY]['formdata'] = form.data request.session.changed() return HTTPFound(location=request.current_route_path( _query={'procid': internal_procid})) elif request.session[RAND_INFO_KEY]['stage'] == RAND_VERIFY: Form = make_form( db_session, enrollment.study.randomization_schema, show_metadata=False) form = Form(request.POST) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) else: previous_data = \ request.session[RAND_INFO_KEY].get('formdata') or {} # ensure entered values match previous values for field, value in form.data.items(): if value != previous_data.get(field): # start over request.session[RAND_INFO_KEY]['stage'] = RAND_ENTER request.session[RAND_INFO_KEY]['formdata'] = None request.session.flash( _(u'Your responses do not match previously ' u'entered responses. ' u'You will need to reenter your responses.'), 'warning') return HTTPFound(location=request.current_route_path( _query={'procid': internal_procid})) else: report = build_report( db_session, enrollment.study.randomization_schema.name) data = form.data # Get an unassigned entity that matches the input criteria query = ( db_session.query(models.Stratum) .filter(models.Stratum.study == enrollment.study) .filter(models.Stratum.patient == sa.null()) .join(models.Stratum.contexts) .join(datastore.Context.entity) .add_entity(datastore.Entity) .join(report, report.c.id == datastore.Entity.id) .filter(sa.and_( *[(getattr(report.c, k) == v) for k, v in data.items()])) .order_by(models.Stratum.id.asc()) .limit(1)) try: (stratum, entity) = query.one() except orm.exc.NoResultFound: raise HTTPBadRequest( body=_(u'Randomization numbers depleted')) # so far so good, set the contexts and complete the request stratum.patient = enrollment.patient entity.state = ( db_session.query(datastore.State) .filter_by(name=u'complete') .one()) entity.collect_date = date.today() enrollment.patient.entities.add(entity) enrollment.entities.add(entity) db_session.flush() del request.session[RAND_INFO_KEY] request.session.flash( _(u'Randomization complete'), 'success') return HTTPFound( location=request.current_route_path(_query={})) else: log.warn( u'Detected unknown randomization stage: {}'.format( str(request.session[RAND_INFO_KEY]))) request.session.flash( _(u'Unable to determine randomization state. Restarting'), 'warning') del request.session[RAND_INFO_KEY] return HTTPFound(location=request.current_route_path(_query={})) if enrollment.is_randomized: template = '../templates/enrollment/randomize-view.pt' form = _get_randomized_form(enrollment, request) elif request.session[RAND_INFO_KEY]['stage'] == RAND_CHALLENGE: template = '../templates/enrollment/randomize-challenge.pt' Form = _make_challenge_form(enrollment, request) Form.procid = wtforms.HiddenField() form = Form(procid=internal_procid) form.meta.entity = None form.meta.schema = enrollment.study.randomization_schema elif request.session[RAND_INFO_KEY]['stage'] == RAND_ENTER: template = '../templates/enrollment/randomize-enter.pt' Form = make_form( db_session, enrollment.study.randomization_schema, show_metadata=False) Form.procid = wtforms.HiddenField() form = Form(procid=internal_procid) elif request.session[RAND_INFO_KEY]['stage'] == RAND_VERIFY: template = '../templates/enrollment/randomize-verify.pt' Form = make_form( db_session, enrollment.study.randomization_schema, show_metadata=False) form = Form() Form.procid = wtforms.HiddenField() form = Form(procid=internal_procid) return { 'is_randomized': enrollment.is_randomized, 'enrollment': view_json(enrollment, request), 'content': render(template, { 'context': enrollment, 'request': request, 'form': render_form( form, disabled=enrollment.is_randomized, show_footer=False, attr={ 'id': 'enrollment-randomization', 'method': 'POST', 'action': request.current_route_path(), 'role': 'form', 'data-bind': 'formentry: {}, submit: $root.randomizeEnrollment' }) }) }
def randomize_print(context, request): form = _get_randomized_form(context, request) return {'form': render_form(form, disabled=True)}
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 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 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 randomize_ajax(context, request): """ Procesess a patient's randomiation by completing randomization form Rules: * The user can only randomize one patient at a time. * If another randomization is in progress, both are restarted. * A randomization session may not "continue" from another. In order to address a single randomization at a time, the process assigns a "process id" or ``procid`` for the duration of the process, this way if a new process begins it will have a different token which will not match the current process and nullify everything. This is done by passing the ``procid`` via POST or GET depending on the phase of data entry and matching it against the session-stored ``procid``. If the they do not match, the operation is cancelled. The process goes as follows: # CHALLENGE: Upon first request the user will be issued a ``procid`` token this token will remain unchainged for the duration of the randomization process. If it changes, the process restarts. The goal of the challenge stage is to ensure the user confirms their intent to randomize. # ENTER: After passing the challenge stage, the user will then have opportunity to enter the randomization schema form data that will be used to determine assignement to the study arm. # VERIFY: The user will then have to verify the data again to ensure accurate responses. If the user fails this stage, they will have to pass the ENTER stage again. Upon sucessfull verification the ``procid`` expires and the patient is randomized. The user will not be shown the challenge/entry forms again and only the randomization information information will be rendered for future reference to the user. """ db_session = request.db_session enrollment = context if not enrollment.is_randomized: # Ensure a ``procid`` is assigned for the duration of the process # This way, if a new request mismatches, we can expire the operation if 'procid' not in request.GET and 'procid' not in request.POST: internal_procid = str(uuid.uuid4()) request.session[RAND_INFO_KEY] = { 'procid': internal_procid, 'stage': RAND_CHALLENGE, 'formdata': None } return HTTPFound(location=request.current_route_path( _query={'procid': internal_procid})) external_procid = request.GET.get('procid') or request.POST.get( 'procid') internal_procid = request.session.get(RAND_INFO_KEY, {}).get('procid') # compare internal and external ID to determine if a new process has # been initiated in a new tab if external_procid is not None and external_procid != internal_procid: try: del request.session[RAND_INFO_KEY] except KeyError: # pragma: no cover pass request.session.flash( _(u'You have another randomization in progress, ' u'starting over.'), 'warning') return HTTPFound(location=request.current_route_path(_query={})) if request.method == 'POST': check_csrf_token(request) if enrollment.is_randomized: request.session.flash( _(u'This patient is already randomized for this study'), 'warning') return HTTPFound(location=request.current_route_path(_query={})) if request.session[RAND_INFO_KEY]['stage'] == RAND_CHALLENGE: Form = _make_challenge_form(enrollment, request) form = Form(request.POST) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) else: request.session[RAND_INFO_KEY]['stage'] = RAND_ENTER request.session.changed() return HTTPFound(location=request.current_route_path( _query={'procid': internal_procid})) elif request.session[RAND_INFO_KEY]['stage'] == RAND_ENTER: Form = make_form(db_session, enrollment.study.randomization_schema, show_metadata=False) form = Form(request.POST) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) else: request.session[RAND_INFO_KEY]['stage'] = RAND_VERIFY request.session[RAND_INFO_KEY]['formdata'] = form.data request.session.changed() return HTTPFound(location=request.current_route_path( _query={'procid': internal_procid})) elif request.session[RAND_INFO_KEY]['stage'] == RAND_VERIFY: Form = make_form(db_session, enrollment.study.randomization_schema, show_metadata=False) form = Form(request.POST) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) else: previous_data = \ request.session[RAND_INFO_KEY].get('formdata') or {} # ensure entered values match previous values for field, value in form.data.items(): if value != previous_data.get(field): # start over request.session[RAND_INFO_KEY]['stage'] = RAND_ENTER request.session[RAND_INFO_KEY]['formdata'] = None request.session.flash( _(u'Your responses do not match previously ' u'entered responses. ' u'You will need to reenter your responses.'), 'warning') return HTTPFound(location=request.current_route_path( _query={'procid': internal_procid})) else: report = build_report( db_session, enrollment.study.randomization_schema.name) data = form.data # Get an unassigned entity that matches the input criteria query = (db_session.query(models.Stratum).filter( models.Stratum.study == enrollment.study).filter( models.Stratum.patient == sa.null()).join( models.Stratum.contexts).join( datastore.Context.entity).add_entity( datastore.Entity).join( report, report.c.id == datastore.Entity.id) .filter( sa.and_( *[(getattr(report.c, k) == v) for k, v in data.items()])).order_by( models.Stratum.id.asc()).limit(1)) try: (stratum, entity) = query.one() except orm.exc.NoResultFound: raise HTTPBadRequest( body=_(u'Randomization numbers depleted')) # so far so good, set the contexts and complete the request stratum.patient = enrollment.patient entity.state = (db_session.query( datastore.State).filter_by(name=u'complete').one()) entity.collect_date = date.today() enrollment.patient.entities.add(entity) enrollment.entities.add(entity) db_session.flush() del request.session[RAND_INFO_KEY] request.session.flash(_(u'Randomization complete'), 'success') return HTTPFound(location=request.current_route_path( _query={})) else: log.warn(u'Detected unknown randomization stage: {}'.format( str(request.session[RAND_INFO_KEY]))) request.session.flash( _(u'Unable to determine randomization state. Restarting'), 'warning') del request.session[RAND_INFO_KEY] return HTTPFound(location=request.current_route_path(_query={})) if enrollment.is_randomized: template = '../templates/enrollment/randomize-view.pt' form = _get_randomized_form(enrollment, request) elif request.session[RAND_INFO_KEY]['stage'] == RAND_CHALLENGE: template = '../templates/enrollment/randomize-challenge.pt' Form = _make_challenge_form(enrollment, request) Form.procid = wtforms.HiddenField() form = Form(procid=internal_procid) form.meta.entity = None form.meta.schema = enrollment.study.randomization_schema elif request.session[RAND_INFO_KEY]['stage'] == RAND_ENTER: template = '../templates/enrollment/randomize-enter.pt' Form = make_form(db_session, enrollment.study.randomization_schema, show_metadata=False) Form.procid = wtforms.HiddenField() form = Form(procid=internal_procid) elif request.session[RAND_INFO_KEY]['stage'] == RAND_VERIFY: template = '../templates/enrollment/randomize-verify.pt' Form = make_form(db_session, enrollment.study.randomization_schema, show_metadata=False) form = Form() Form.procid = wtforms.HiddenField() form = Form(procid=internal_procid) return { 'is_randomized': enrollment.is_randomized, 'enrollment': view_json(enrollment, request), 'content': render( template, { 'context': enrollment, 'request': request, 'form': render_form( form, disabled=enrollment.is_randomized, show_footer=False, attr={ 'id': 'enrollment-randomization', 'method': 'POST', 'action': request.current_route_path(), 'role': 'form', 'data-bind': 'formentry: {}, submit: $root.randomizeEnrollment' }) }) }
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' } ), }