def post_household_composition(eq_id, form_type, collection_id, group_id): questionnaire_manager = get_questionnaire_manager(g.schema, g.schema_json) answer_store = get_answer_store(current_user) this_location = Location(group_id, group_instance=0, block_id='household-composition') if 'action[save_continue]' in request.form: _remove_repeating_on_household_answers(answer_store, group_id) valid = questionnaire_manager.process_incoming_answers(this_location, post_data=request.form) if 'action[add_answer]' in request.form: questionnaire_manager.add_answer(this_location, answer_store, question_id='household-composition-question') return get_block(eq_id, form_type, collection_id, group_id, group_instance=0, block_id='household-composition') elif 'action[remove_answer]' in request.form: index_to_remove = int(request.form.get('action[remove_answer]')) questionnaire_manager.remove_answer(this_location, answer_store, index_to_remove) return get_block(eq_id, form_type, collection_id, group_id, group_instance=0, block_id='household-composition') elif 'action[save_sign_out]' in request.form: return _save_sign_out(collection_id, eq_id, form_type, questionnaire_manager, this_location) if not valid: _render_schema(this_location) return _build_template(current_location=this_location, context=questionnaire_manager.block_state, template='questionnaire') path_finder = PathFinder(g.schema_json, get_answer_store(current_user), get_metadata(current_user)) next_location = path_finder.get_next_location(current_location=this_location) metadata = get_metadata(current_user) return redirect(next_location.url(metadata))
def post_household_composition(eq_id, form_type, collection_id, group_id): # pylint: disable=too-many-locals answer_store = get_answer_store(current_user) if _household_answers_changed(answer_store): _remove_repeating_on_household_answers(answer_store, group_id) error_messages = SchemaHelper.get_messages(g.schema_json) disable_mandatory = any(x in request.form for x in [ 'action[add_answer]', 'action[remove_answer]', 'action[save_sign_out]' ]) current_location = Location(group_id, 0, 'household-composition') block = _render_schema(current_location) form, _ = post_form_for_location(block, current_location, answer_store, request.form, error_messages, disable_mandatory=disable_mandatory) if 'action[add_answer]' in request.form: form.household.append_entry() elif 'action[remove_answer]' in request.form: index_to_remove = int(request.form.get('action[remove_answer]')) form.remove_person(index_to_remove) elif 'action[save_sign_out]' in request.form: response = _save_sign_out(collection_id, eq_id, form_type, current_location, form) remove_empty_household_members_from_answer_store( answer_store, group_id) return response if _is_invalid_form( form ) or 'action[add_answer]' in request.form or 'action[remove_answer]' in request.form: context = {'form': form, 'block': block} return _build_template(current_location, context, template='questionnaire') else: questionnaire_store = get_questionnaire_store(current_user.user_id, current_user.user_ik) update_questionnaire_store_with_answer_data( questionnaire_store, current_location, form.serialise(current_location)) metadata = get_metadata(current_user) path_finder = PathFinder(g.schema_json, get_answer_store(current_user), metadata) next_location = path_finder.get_next_location( current_location=current_location) return redirect(next_location.url(metadata))
def get_summary(eq_id, form_type, collection_id): # pylint: disable=unused-argument answer_store = get_answer_store(current_user) path_finder = PathFinder(g.schema_json, answer_store, get_metadata(current_user)) latest_location = path_finder.get_latest_location(get_completed_blocks(current_user)) metadata = get_metadata(current_user) if latest_location.block_id is 'summary': answers = get_answer_store(current_user) schema_context = build_schema_context(metadata, g.schema.aliases, answers) rendered_schema_json = renderer.render(g.schema_json, **schema_context) summary_context = build_summary_rendering_context(rendered_schema_json, answer_store, metadata) return _build_template(current_location=latest_location, context=summary_context) return redirect(latest_location.url(metadata))
def post_block(eq_id, form_type, collection_id, group_id, group_instance, block_id): path_finder = PathFinder(g.schema_json, get_answer_store(current_user), get_metadata(current_user)) q_manager = get_questionnaire_manager(g.schema, g.schema_json) this_location = Location(group_id, group_instance, block_id) if 'action[save_sign_out]' in request.form: return _save_sign_out(collection_id, eq_id, form_type, q_manager, this_location) valid_location = this_location in path_finder.get_routing_path(group_id, group_instance) valid_data = q_manager.validate(this_location, request.form) if not valid_location or not valid_data: current_location = Location(group_id, group_instance, block_id) _render_schema(current_location) return _build_template(current_location, q_manager.block_state, template='questionnaire') else: q_manager.update_questionnaire_store(this_location) next_location = path_finder.get_next_location(current_location=this_location) if next_location is None: raise NotFound metadata = get_metadata(current_user) return redirect(next_location.url(metadata))
def get_block(eq_id, form_type, collection_id, group_id, group_instance, block_id): # pylint: disable=unused-argument # Filter answers down to those we may need to render answer_store = get_answer_store(current_user) path_finder = PathFinder(g.schema_json, answer_store, get_metadata(current_user)) current_location = Location(group_id, group_instance, block_id) valid_group = group_id in SchemaHelper.get_group_ids(g.schema_json) if not valid_group or current_location not in path_finder.get_routing_path(group_id, group_instance): raise NotFound block = _render_schema(current_location) error_messages = SchemaHelper.get_messages(g.schema_json) form, template_params = get_form_for_location(block, current_location, answer_store, error_messages) content = {'form': form, 'block': block} if template_params: content.update(template_params) template = block['type'] if block and 'type' in block and block['type'] else 'questionnaire' return _build_template(current_location, content, template)
def get_block(eq_id, form_type, collection_id, group_id, group_instance, block_id): # pylint: disable=unused-argument,too-many-locals current_location = Location(group_id, group_instance, block_id) metadata = get_metadata(current_user) answer_store = get_answer_store(current_user) path_finder = PathFinder(g.schema_json, answer_store, metadata) valid_group = group_id in SchemaHelper.get_group_ids(g.schema_json) full_routing_path = path_finder.get_routing_path() is_valid_location = valid_group and current_location in path_finder.get_routing_path( group_id, group_instance) latest_location = path_finder.get_latest_location( get_completed_blocks(current_user), routing_path=full_routing_path) if not is_valid_location: return _redirect_to_location(collection_id, eq_id, form_type, latest_location) block = _render_schema(current_location) block_type = block['type'] is_skipping_to_end = block_type in [ 'Summary', 'Confirmation' ] and current_location != latest_location if is_skipping_to_end: return _redirect_to_location(collection_id, eq_id, form_type, latest_location) context = _get_context(block, current_location, answer_store) return _build_template(current_location, context, template=block_type, routing_path=full_routing_path)
def login(): """ Initial url processing - expects a token parameter and then will authenticate this token. Once authenticated it will be placed in the users session :return: a 302 redirect to the next location for the user """ logger.new() # logging in again clears any session state if session: session.clear() logger.debug("attempting token authentication") authenticator.jwt_login(request) logger.debug("token authenticated - linking to session") metadata = get_metadata(current_user) eq_id = metadata["eq_id"] form_type = metadata["form_type"] logger.bind(eq_id=eq_id, form_type=form_type) if not eq_id or not form_type: logger.error("missing eq id or form type in jwt") raise NotFound json = get_schema(metadata) navigator = PathFinder(json, get_answer_store(current_user), metadata) current_location = navigator.get_latest_location( get_completed_blocks(current_user)) return redirect(current_location.url(metadata))
def post_everyone_at_address_confirmation(eq_id, form_type, collection_id, group_id, group_instance): if request.form.get('permanent-or-family-home-answer') == 'No': _remove_repeating_on_household_answers(get_answer_store(current_user), group_id) return post_block(eq_id, form_type, collection_id, group_id, group_instance, 'permanent-or-family-home')
def _submit_data(user): answer_store = get_answer_store(user) if answer_store.answers: metadata = get_metadata(user) collection_metadata = get_collection_metadata(user) schema = load_schema_from_metadata(metadata) completed_blocks = get_completed_blocks(user) routing_path = PathFinder(schema, answer_store, metadata, completed_blocks).get_full_routing_path() message = convert_answers(metadata, collection_metadata, schema, answer_store, routing_path, flushed=True) encrypted_message = encrypt(message, current_app.eq['key_store'], KEY_PURPOSE_SUBMISSION) sent = current_app.eq['submitter'].send_message( encrypted_message, current_app.config['EQ_RABBITMQ_QUEUE_NAME'], metadata['tx_id']) if not sent: raise SubmissionFailedException() get_questionnaire_store(user.user_id, user.user_ik).delete() return True return False
def _submit_data(user): answer_store = get_answer_store(user) if answer_store.answers: metadata = get_metadata(user) schema = load_schema_from_metadata(metadata) routing_path = PathFinder(schema, answer_store, metadata).get_routing_path() message = convert_answers(metadata, schema, answer_store, routing_path, flushed=True) message = current_app.eq['encrypter'].encrypt(message) sent = current_app.eq['submitter'].send_message( message, current_app.config['EQ_RABBITMQ_QUEUE_NAME'], metadata["tx_id"]) if not sent: raise SubmissionFailedException() get_questionnaire_store(user.user_id, user.user_ik).delete() return True else: return False
def _render_schema(current_location): metadata = get_metadata(current_user) answer_store = get_answer_store(current_user) block_json = SchemaHelper.get_block_for_location(g.schema_json, current_location) block_json = _evaluate_skip_conditions(block_json, current_location, answer_store, metadata) aliases = SchemaHelper.get_aliases(g.schema_json) block_context = build_schema_context(metadata, aliases, answer_store, current_location.group_instance) return renderer.render(block_json, **block_context)
def _redirect_to_latest_location(collection_id, eq_id, form_type, schema): metadata = get_metadata(current_user) answer_store = get_answer_store(current_user) path_finder = PathFinder(schema, answer_store, metadata) routing_path = path_finder.get_routing_path() latest_location = path_finder.get_latest_location( get_completed_blocks(current_user), routing_path=routing_path) return _redirect_to_location(collection_id, eq_id, form_type, latest_location)
def _generate_wtf_form(form, block, location, schema): disable_mandatory = 'action[save_sign_out]' in form wtf_form = post_form_for_location(schema, block, location, get_answer_store(current_user), get_metadata(current_user), request.form, disable_mandatory) return wtf_form
def post_household_composition(eq_id, form_type, collection_id, group_id): path_finder = PathFinder(g.schema_json, get_answer_store(current_user), get_metadata(current_user)) answer_store = get_answer_store(current_user) questionnaire_store = get_questionnaire_store(current_user.user_id, current_user.user_ik) current_location = Location(group_id, 0, 'household-composition') block = _render_schema(current_location) if _household_answers_changed(answer_store): _remove_repeating_on_household_answers(answer_store, group_id) error_messages = SchemaHelper.get_messages(g.schema_json) if any(x in request.form for x in ['action[add_answer]', 'action[remove_answer]', 'action[save_sign_out]']): disable_mandatory = True else: disable_mandatory = False form, _ = post_form_for_location(block, current_location, answer_store, request.form, error_messages, disable_mandatory=disable_mandatory) if 'action[add_answer]' in request.form: form.household.append_entry() elif 'action[remove_answer]' in request.form: index_to_remove = int(request.form.get('action[remove_answer]')) form.remove_person(index_to_remove) elif 'action[save_sign_out]' in request.form: return _save_sign_out(collection_id, eq_id, form_type, current_location, form) if not form.validate() or 'action[add_answer]' in request.form or 'action[remove_answer]' in request.form: return _render_template({ 'form': form, 'block': block, }, current_location.block_id, current_location=current_location, template='questionnaire') update_questionnaire_store_with_answer_data(questionnaire_store, current_location, form.serialise(current_location)) next_location = path_finder.get_next_location(current_location=current_location) metadata = get_metadata(current_user) return redirect(next_location.url(metadata))
def post_block(eq_id, form_type, collection_id, group_id, group_instance, block_id): path_finder = PathFinder(g.schema_json, get_answer_store(current_user), get_metadata(current_user)) current_location = Location(group_id, group_instance, block_id) valid_location = current_location in path_finder.get_routing_path(group_id, group_instance) block = _render_schema(current_location) error_messages = SchemaHelper.get_messages(g.schema_json) disable_mandatory = 'action[save_sign_out]' in request.form form, _ = post_form_for_location(block, current_location, get_answer_store(current_user), request.form, error_messages, disable_mandatory=disable_mandatory) if 'action[save_sign_out]' in request.form: return _save_sign_out(collection_id, eq_id, form_type, current_location, form) content = { 'form': form, 'block': block, } if not valid_location or not form.validate(): return _build_template(current_location, content, template='questionnaire') else: questionnaire_store = get_questionnaire_store(current_user.user_id, current_user.user_ik) if current_location.block_id in ['relationships', 'household-relationships']: update_questionnaire_store_with_answer_data(questionnaire_store, current_location, form.serialise(current_location)) else: update_questionnaire_store_with_form_data(questionnaire_store, current_location, form.data) next_location = path_finder.get_next_location(current_location=current_location) if next_location is None: raise NotFound metadata = get_metadata(current_user) return redirect(next_location.url(metadata))
def get_path_finder(): finder = getattr(g, 'path_finder', None) if finder is None: metadata = get_metadata(current_user) answer_store = get_answer_store(current_user) completed_blocks = get_completed_blocks(current_user) finder = PathFinder(g.schema, answer_store, metadata, completed_blocks) g.path_finder = finder return finder
def dump_submission(): answer_store = get_answer_store(current_user) metadata = get_metadata(current_user) schema = load_schema_from_metadata(metadata) routing_path = PathFinder(schema, answer_store, metadata).get_routing_path() response = { 'submission': convert_answers(metadata, schema, answer_store, routing_path) } return jsonify(response), 200
def build_repeating_state(self, user_input): template_answer = self.answers.pop() group_instance = template_answer.group_instance first_name_answers = get_answer_store(current_user).filter( answer_id='first-name') last_name_answers = get_answer_store(current_user).filter( answer_id='last-name') first_names = [answer['value'] for answer in first_name_answers] last_names = [answer['value'] for answer in last_name_answers] household_members = [] for first_name, last_name in zip(first_names, last_names): household_members.append({ 'first-name': first_name, 'last-name': last_name, }) remaining_people = household_members[group_instance + 1:] if self.group_instance < len( household_members) else [] current_person_name = format_household_member_name([ household_members[group_instance]['first-name'], household_members[group_instance]['last-name'], ]) for index, remaining_person in enumerate(remaining_people): for answer_schema in self.schema_item.answers: new_answer_state = self.create_new_answer_state( answer_schema, index, group_instance) new_answer_state.schema_item.widget.current_person = current_person_name other_person_name = format_household_member_name([ remaining_person['first-name'], remaining_person['last-name'], ]) new_answer_state.schema_item.widget.other_person = other_person_name self.answers.append(new_answer_state)
def validate_all_answers(self): navigator = PathFinder(self._json, get_answer_store(current_user), get_metadata(current_user)) for location in navigator.get_location_path(): answers = get_answers(current_user) is_valid = self.validate(location, answers) if not is_valid: logger.debug("Failed validation with current location %s", str(location)) return False, location return True, None
def get_confirmation(eq_id, form_type, collection_id): # pylint: disable=unused-argument answer_store = get_answer_store(current_user) path_finder = PathFinder(g.schema_json, answer_store, get_metadata(current_user)) latest_location = path_finder.get_latest_location(get_completed_blocks(current_user)) if latest_location.block_id == 'confirmation': block = _render_schema(latest_location) return _build_template(current_location=latest_location, context={"block": block}) metadata = get_metadata(current_user) return redirect(latest_location.url(metadata))
def dump_submission(): answer_store = get_answer_store(current_user) metadata = get_metadata(current_user) session_data = get_session_store().session_data schema = load_schema_from_session_data(session_data) completed_blocks = get_completed_blocks(current_user) routing_path = PathFinder(schema, answer_store, metadata, completed_blocks).get_full_routing_path() response = { 'submission': convert_answers(metadata, schema, answer_store, routing_path) } return jsonify(response), 200
def _submit_data(user): answer_store = get_answer_store(user) if answer_store: questionnaire_store = get_questionnaire_store(user.user_id, user.user_ik) answer_store = questionnaire_store.answer_store metadata = questionnaire_store.metadata response_metadata = questionnaire_store.response_metadata progress_store = questionnaire_store.progress_store list_store = questionnaire_store.list_store submitted_at = datetime.now(timezone.utc) schema = load_schema_from_metadata(metadata) router = Router( schema, answer_store, list_store, progress_store, metadata, response_metadata, ) full_routing_path = router.full_routing_path() message = json_dumps( convert_answers( schema, questionnaire_store, full_routing_path, submitted_at, flushed=True, )) encrypted_message = encrypt(message, current_app.eq["key_store"], KEY_PURPOSE_SUBMISSION) sent = current_app.eq["submitter"].send_message( encrypted_message, tx_id=metadata.get("tx_id"), case_id=metadata["case_id"], ) if not sent: raise SubmissionFailedException() get_questionnaire_store(user.user_id, user.user_ik).delete() logger.info("successfully flushed answers") return True logger.info("no answers found to flush") return False
def post_block(eq_id, form_type, collection_id, group_id, group_instance, block_id): # pylint: disable=too-many-locals current_location = Location(group_id, group_instance, block_id) metadata = get_metadata(current_user) answer_store = get_answer_store(current_user) path_finder = PathFinder(g.schema_json, answer_store, metadata) valid_group = group_id in SchemaHelper.get_group_ids(g.schema_json) full_routing_path = path_finder.get_routing_path() is_valid_location = valid_group and current_location in path_finder.get_routing_path( group_id, group_instance) if not is_valid_location: latest_location = path_finder.get_latest_location( get_completed_blocks(current_user), routing_path=full_routing_path) return _redirect_to_location(collection_id, eq_id, form_type, latest_location) error_messages = SchemaHelper.get_messages(g.schema_json) block = _render_schema(current_location) disable_mandatory = 'action[save_sign_out]' in request.form form, _ = post_form_for_location(block, current_location, answer_store, request.form, error_messages, disable_mandatory=disable_mandatory) if 'action[save_sign_out]' in request.form: return _save_sign_out(collection_id, eq_id, form_type, current_location, form) elif _is_invalid_form(form): context = {'form': form, 'block': block} return _build_template(current_location, context, template=block['type'], routing_path=full_routing_path) else: _update_questionnaire_store(current_location, form) next_location = path_finder.get_next_location( current_location=current_location) if next_location is None and block['type'] in [ "Summary", "Confirmation" ]: return submit_answers(eq_id, form_type, collection_id, metadata, answer_store) return redirect(next_location.url(metadata))
def submit_answers(eq_id, form_type, collection_id): q_manager = get_questionnaire_manager(g.schema, g.schema_json) # check that all the answers we have are valid before submitting the data is_valid, invalid_location = q_manager.validate_all_answers() metadata = get_metadata(current_user) if is_valid: answer_store = get_answer_store(current_user) path_finder = PathFinder(g.schema_json, answer_store, metadata) submitter = SubmitterFactory.get_submitter() message = convert_answers(metadata, g.schema, answer_store, path_finder.get_routing_path()) submitter.send_answers(message, queue=settings.EQ_RABBITMQ_QUEUE_NAME) logger.info("Responses submitted tx_id=%s", metadata["tx_id"]) return redirect(url_for('.get_thank_you', eq_id=eq_id, form_type=form_type, collection_id=collection_id)) else: return redirect(invalid_location.url(metadata))
def submit_answers(eq_id, form_type, collection_id): metadata = get_metadata(current_user) answer_store = get_answer_store(current_user) is_valid, invalid_location = validate_all_answers(answer_store, metadata) if is_valid: path_finder = PathFinder(g.schema_json, answer_store, metadata) submitter = SubmitterFactory.get_submitter() message = convert_answers(metadata, g.schema_json, answer_store, path_finder.get_routing_path()) submitter.send_answers(message) return redirect(url_for('.get_thank_you', eq_id=eq_id, form_type=form_type, collection_id=collection_id)) else: return redirect(invalid_location.url(metadata))
def _generate_wtf_form(block_schema, schema, current_location): answer_store = get_answer_store(current_user) metadata = get_metadata(current_user) if request.method == "POST": disable_mandatory = "action[save_sign_out]" in request.form return post_form_for_block( schema, block_schema, answer_store, metadata, request.form, current_location, disable_mandatory, ) return get_form_for_location(schema, block_schema, current_location, answer_store, metadata)
def _build_template(current_location, context, template, routing_path=None): metadata = get_metadata(current_user) metadata_context = build_metadata_context(metadata) answer_store = get_answer_store(current_user) front_end_navigation = _get_front_end_navigation(answer_store, current_location, metadata, routing_path) path_finder = PathFinder(g.schema_json, answer_store, metadata) previous_location = path_finder.get_previous_location(current_location) previous_url = previous_location.url( metadata) if previous_location is not None else None return _render_template(context, current_location, template, front_end_navigation, metadata_context, previous_url)
def submit_answers(routing_path, eq_id, form_type, schema): metadata = get_metadata(current_user) collection_metadata = get_collection_metadata(current_user) answer_store = get_answer_store(current_user) message = json.dumps( convert_answers( metadata, collection_metadata, schema, answer_store, routing_path, )) encrypted_message = encrypt(message, current_app.eq['key_store'], KEY_PURPOSE_SUBMISSION) sent = current_app.eq['submitter'].send_message( encrypted_message, current_app.config['EQ_RABBITMQ_QUEUE_NAME'], metadata['tx_id'], ) if current_app.config['EQ_PUBSUB_ENABLED']: current_app.eq['pubsub_submitter'].send_message( encrypted_message, current_app.config['EQ_PUBSUB_TOPIC_ID'], metadata['tx_id'], ) if not sent: raise SubmissionFailedException() submitted_time = datetime.utcnow() _store_submitted_time_in_session(submitted_time) if is_view_submitted_response_enabled(schema.json): _store_viewable_submission(list(answer_store), metadata, submitted_time) get_questionnaire_store(current_user.user_id, current_user.user_ik).delete() return redirect( url_for('post_submission.get_thank_you', eq_id=eq_id, form_type=form_type))
def get_block(eq_id, form_type, collection_id, group_id, group_instance, block_id): # pylint: disable=unused-argument # Filter answers down to those we may need to render answer_store = get_answer_store(current_user) answers = answer_store.map(group_id=group_id, group_instance=group_instance, block_id=block_id) this_location = Location(group_id, group_instance, block_id) q_manager = get_questionnaire_manager(g.schema, g.schema_json) q_manager.build_block_state(this_location, answers) # Find block by id block = g.schema.get_item_by_id(block_id) # pylint: disable=maybe-no-member template = block.type if block and block.type else 'questionnaire' current_location = Location(group_id, group_instance, block_id) _render_schema(current_location) return _build_template(current_location, q_manager.block_state, template)
def _get_context(full_routing_path, block, current_location, schema, form=None): metadata = get_metadata(current_user) answer_store = get_answer_store(current_user) schema_context = _get_schema_context(full_routing_path, current_location.group_instance, metadata, answer_store, schema) rendered_block = renderer.render(block, **schema_context) return build_view_context(block['type'], metadata, schema, answer_store, schema_context, rendered_block, current_location, form=form)