Пример #1
0
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)
Пример #2
0
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))
Пример #3
0
    def test_should_not_show_block_for_zero_repeats(self):
        survey = load_schema_file("test_repeating_household.json")

        # Default is to count answers, so switch to using value
        survey['groups'][-2]['routing_rules'][0]['repeat']['type'] = 'answer_value'

        expected_path = [
            Location("multiple-questions-group", 0, "introduction"),
            Location("multiple-questions-group", 0, "household-composition"),
            Location("summary-group", 0, "summary")
        ]

        answer = Answer(
            group_id="multiple-questions-group",
            group_instance=0,
            answer_id="first-name",
            block_id="household-composition",
            value="0"
        )
        answers = AnswerStore()
        answers.add(answer)

        path_finder = PathFinder(survey, answer_store=answers)

        self.assertEqual(expected_path, path_finder.get_routing_path())
Пример #4
0
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)
Пример #5
0
    def test_routing_basic_and_conditional_path(self):
        survey = load_schema_file("0_star_wars.json")

        expected_path = [
            Location("star-wars", 0, "introduction"),
            Location("star-wars", 0, "choose-your-side-block"),
            Location("star-wars", 0, "dark-side-pick-character-ship"),
            Location("star-wars", 0, "light-side-ship-type"),
            Location("star-wars", 0, "star-wars-trivia"),
            Location("star-wars", 0, "star-wars-trivia-part-2"),
            Location("star-wars", 0, "star-wars-trivia-part-3"),
            Location("star-wars", 0, "summary"),
        ]

        answer_1 = Answer(
            group_id="star-wars",
            block_id="choose-your-side-block",
            answer_id="choose-your-side-answer",
            value="Dark Side"
        )
        answer_2 = Answer(
            group_id="star-wars",
            block_id="dark-side-pick-character-ship",
            answer_id="dark-side-pick-ship-answer",
            value="Can I be a pain and have a goodies ship",
        )

        answers = AnswerStore()
        answers.add(answer_1)
        answers.add(answer_2)

        path_finder = PathFinder(survey, answer_store=answers)
        routing_path = path_finder.get_routing_path()

        self.assertEqual(routing_path, expected_path)
Пример #6
0
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))
Пример #7
0
def build_summary_rendering_context(schema_json, answer_store, metadata):
    """
    Build questionnaire summary context containing metadata and content from the answers of the questionnaire
    :param schema_json: schema of the current questionnaire
    :param answer_store: all of the answers to the questionnaire
    :param metadata: all of the metadata
    :return: questionnaire summary context
    """
    navigator = PathFinder(schema_json, answer_store, metadata)
    path = navigator.get_routing_path()
    sections = []
    for group in schema_json['groups']:
        for block in group['blocks']:
            if block['id'] in [location.block_id for location in path]:
                if "type" not in block or block['type'] != "interstitial":
                    link = url_for(
                        'questionnaire.get_block',
                        eq_id=metadata['eq_id'],
                        form_type=metadata['form_type'],
                        collection_id=metadata['collection_exercise_sid'],
                        group_id=group['id'],
                        group_instance=0,
                        block_id=block['id'])
                    sections.extend([
                        Section(section, answer_store.map(), link)
                        for section in block['sections']
                    ])
    return sections
Пример #8
0
    def test_repeating_groups_no_of_answers_minus_one(self):
        survey = load_schema_file("test_repeating_household.json")

        # Default is to count answers, so switch to using value
        survey['groups'][-1]['routing_rules'][0]['repeat'][
            'type'] = 'answer_count_minus_one'

        expected_path = [
            Location("multiple-questions-group", 0, "household-composition"),
            Location("repeating-group", 0, "repeating-block-1"),
            Location("repeating-group", 0, "repeating-block-2"),
        ]

        answer = Answer(group_id="multiple-questions-group",
                        group_instance=0,
                        answer_instance=0,
                        answer_id="first-name",
                        block_id="household-composition",
                        value="Joe Bloggs")

        answer_2 = Answer(group_id="multiple-questions-group",
                          group_instance=0,
                          answer_instance=1,
                          answer_id="first-name",
                          block_id="household-composition",
                          value="Sophie Bloggs")

        answers = AnswerStore()

        answers.add(answer)
        answers.add(answer_2)

        path_finder = PathFinder(survey, answer_store=answers)

        self.assertEqual(expected_path, path_finder.get_routing_path())
Пример #9
0
def submit_answers(eq_id, form_type, collection_id, metadata, answer_store):
    is_completed, invalid_location = is_survey_completed(
        answer_store, metadata)

    if is_completed:
        path_finder = PathFinder(g.schema_json, answer_store, metadata)

        message = convert_answers(metadata, g.schema_json, answer_store,
                                  path_finder.get_routing_path())
        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()

        current_app.eq['session_storage'].store_survey_completed_metadata(
            metadata['tx_id'], metadata['period_str'], metadata['ru_ref'])
        get_questionnaire_store(current_user.user_id,
                                current_user.user_ik).delete()
        _remove_survey_session_data()

        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))
Пример #10
0
    def test_get_routing_path_when_first_block_in_group_skipped(self):
        # Given
        survey = load_schema_file('test_skip_condition_group.json')
        answer_store = AnswerStore()
        answer_store.add(
            Answer(group_id='do-you-want-to-skip-group',
                   block_id='do-you-want-to-skip',
                   answer_id='do-you-want-to-skip-answer',
                   value='Yes'))

        # When
        path_finder = PathFinder(survey, answer_store=answer_store)

        # Then
        expected_route = [{
            'block_id': 'do-you-want-to-skip-block',
            'group_id': 'do-you-want-to-skip-group',
            'group_instance': 0
        }, {
            'block_id': 'summary',
            'group_id': 'should-skip-group',
            'group_instance': 0
        }]
        self.assertEqual(path_finder.get_routing_path('should-skip-group'),
                         expected_route)
    def test_get_routing_path_when_first_block_in_group_skipped(self):
        # Given
        schema = load_schema_from_params('test', 'skip_condition_group')
        answer_store = AnswerStore()
        answer_store.add(Answer(answer_id='do-you-want-to-skip-answer',
                                value='Yes'))

        # When
        path_finder = PathFinder(schema, answer_store=answer_store, metadata={}, completed_blocks=[])

        # Then
        expected_route = [
            {
                'block_id': 'do-you-want-to-skip-block',
                'group_id': 'do-you-want-to-skip-group',
                'group_instance': 0
            },
            {
                'block_id': 'summary',
                'group_id': 'should-skip-group',
                'group_instance': 0
            }
        ]

        pytest.xfail(reason='Known bug when skipping last group due to summary bundled into it')
        self.assertEqual(path_finder.get_routing_path('should-skip-group'), expected_route)
Пример #12
0
    def test_introduction_not_in_path_when_not_in_schema(self):
        survey = load_schema_file("census_individual.json")

        path_finder = PathFinder(survey)

        blocks = [b.block_id for b in path_finder.get_routing_path()]

        self.assertNotIn('introduction', blocks)
Пример #13
0
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)
Пример #14
0
def is_survey_completed(answer_store, metadata):
    path_finder = PathFinder(g.schema_json, answer_store, metadata)
    completed_blocks = get_completed_blocks(current_user)

    for location in path_finder.get_routing_path():
        if location.block_id in ['thank-you', 'summary', 'confirmation']:
            continue

        if location not in completed_blocks:
            return False, location

    return True, None
Пример #15
0
    def test_repeating_groups_no_of_answers(self):
        survey = load_schema_file("test_repeating_household.json")

        expected_path = [
            Location("multiple-questions-group", 0, "introduction"),
            Location("multiple-questions-group", 0, "household-composition"),
            Location("repeating-group", 0, "repeating-block-1"),
            Location("repeating-group", 0, "repeating-block-2"),
            Location("repeating-group", 1, "repeating-block-1"),
            Location("repeating-group", 1, "repeating-block-2"),
            Location("repeating-group", 2, "repeating-block-1"),
            Location("repeating-group", 2, "repeating-block-2"),
            Location("summary-group", 0, "summary"),
        ]

        answer = Answer(
            group_id="multiple-questions-group",
            group_instance=0,
            answer_instance=0,
            answer_id="first-name",
            block_id="household-composition",
            value="Joe Bloggs"
        )

        answer_2 = Answer(
            group_id="multiple-questions-group",
            group_instance=0,
            answer_instance=1,
            answer_id="first-name",
            block_id="household-composition",
            value="Sophie Bloggs"
        )

        answer_3 = Answer(
            group_id="multiple-questions-group",
            group_instance=0,
            answer_instance=2,
            answer_id="first-name",
            block_id="household-composition",
            value="Gregg Bloggs"
        )

        answers = AnswerStore()

        answers.add(answer)
        answers.add(answer_2)
        answers.add(answer_3)

        path_finder = PathFinder(survey, answer_store=answers)

        self.assertEqual(expected_path, path_finder.get_routing_path())
Пример #16
0
    def test_routing_basic_path(self):
        survey = load_schema_file("1_0112.json")

        expected_path = [
            Location("rsi", 0, "reporting-period"),
            Location("rsi", 0, "total-retail-turnover"),
            Location("rsi", 0, "internet-sales"),
            Location("rsi", 0, "changes-in-retail-turnover"),
            Location("rsi", 0, "number-of-employees"),
            Location("rsi", 0, "changes-in-employees")
        ]

        path_finder = PathFinder(survey)
        routing_path = path_finder.get_routing_path()

        self.assertEqual(routing_path, expected_path)
Пример #17
0
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))
Пример #18
0
    def test_interstitial_post_blocks(self):
        survey = load_schema_file("0_star_wars.json")

        answer = Answer(
            group_id="star-wars",
            block_id="choose-your-side-block",
            answer_id="choose-your-side-answer",
            value="Light Side"
        )

        answers = AnswerStore()
        answers.add(answer)

        path_finder = PathFinder(survey, answer_store=answers)

        self.assertFalse(Location("star-wars", 0, 'summary') in path_finder.get_routing_path())
Пример #19
0
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))
Пример #20
0
    def test_repeating_groups_conditional_location_path(self):
        survey = load_schema_file("test_repeating_and_conditional_routing.json")

        expected_path = [
            Location("repeat-value-group", 0, "introduction"),
            Location("repeat-value-group", 0, "no-of-repeats"),
            Location("repeated-group", 0, "repeated-block"),
            Location("repeated-group", 0, "age-block"),
            Location("repeated-group", 0, "shoe-size-block"),
            Location("repeated-group", 1, "repeated-block"),
            Location("repeated-group", 1, "shoe-size-block"),
            Location("summary-group", 0, "summary")
        ]

        answer_1 = Answer(
            group_id="repeat-value-group",
            block_id="no-of-repeats",
            answer_id="no-of-repeats-answer",
            value="2"
        )

        answer_2 = Answer(
            group_id="repeated-group",
            group_instance=0,
            block_id="repeated-block",
            answer_id="conditional-answer",
            value="Age and Shoe Size"
        )

        answer_3 = Answer(
            group_id="repeated-group",
            group_instance=1,
            block_id="repeated-block",
            answer_id="conditional-answer",
            value="Shoe Size Only"
        )

        answers = AnswerStore()
        answers.add(answer_1)
        answers.add(answer_2)
        answers.add(answer_3)

        path_finder = PathFinder(survey, answer_store=answers)

        self.assertEqual(expected_path, path_finder.get_routing_path())
Пример #21
0
def build_summary_rendering_context(schema_json, answer_store, metadata):
    """
    Build questionnaire summary context containing metadata and content from the answers of the questionnaire
    :param schema_json: schema of the current questionnaire
    :param answer_store: all of the answers to the questionnaire
    :param metadata: all of the metadata
    :return: questionnaire summary context
    """
    navigator = PathFinder(schema_json, answer_store, metadata)
    path = navigator.get_routing_path()
    groups = []

    for group in schema_json['groups']:
        if SchemaHelper.group_has_questions(group) \
                and group['id'] in [location.group_id for location in path]:
            groups.extend(
                [Group(group, answer_store.map(), path, metadata, url_for)])

    return groups
Пример #22
0
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))
Пример #23
0
    def test_routing_basic_and_conditional_path(self):
        survey = load_schema_file("0_star_wars.json")

        expected_path = [
            Location("14ba4707-321d-441d-8d21-b8367366e766", 0,
                     "choose-your-side-block"),
            Location("14ba4707-321d-441d-8d21-b8367366e766", 0,
                     "923ccc84-9d47-4a02-8ebc-1e9d14fcf10b"),
            Location("14ba4707-321d-441d-8d21-b8367366e766", 0,
                     "26f2c4b3-28ac-4072-9f18-a6a6c6f660db"),
            Location("14ba4707-321d-441d-8d21-b8367366e766", 0,
                     "cd3b74d1-b687-4051-9634-a8f9ce10a27d"),
            Location("14ba4707-321d-441d-8d21-b8367366e766", 0,
                     "an3b74d1-b687-4051-9634-a8f9ce10ard"),
            Location("14ba4707-321d-441d-8d21-b8367366e766", 0,
                     "846f8514-fed2-4bd7-8fb2-4b5fcb1622b1"),
        ]

        answer_1 = Answer(group_id="14ba4707-321d-441d-8d21-b8367366e766",
                          block_id="choose-your-side-block",
                          answer_id="ca3ce3a3-ae44-4e30-8f85-5b6a7a2fb23c",
                          value="Dark Side")
        answer_2 = Answer(
            group_id="14ba4707-321d-441d-8d21-b8367366e766",
            block_id="923ccc84-9d47-4a02-8ebc-1e9d14fcf10b",
            answer_id="pel989b8-5185-4ba6-b73f-c126e3a06ba7",
            value="Can I be a pain and have a goodies ship",
        )

        answers = AnswerStore()
        answers.add(answer_1)
        answers.add(answer_2)

        path_finder = PathFinder(survey, answer_store=answers)
        routing_path = path_finder.get_routing_path()

        self.assertEqual(routing_path, expected_path)
Пример #24
0
    def test_excessive_repeating_groups_conditional_location_path(self):
        survey = load_schema_file("test_repeating_and_conditional_routing.json")

        answers = AnswerStore()

        answers.add(Answer(
            group_id="repeat-value-group",
            block_id="no-of-repeats",
            answer_id="no-of-repeats-answer",
            value="10000"
        ))

        for i in range(50):
            answers.add(Answer(
                group_id="repeated-group",
                group_instance=i,
                block_id="repeated-block",
                answer_id="conditional-answer",
                value="Shoe Size Only"
            ))

        path_finder = PathFinder(survey, answer_store=answers)

        self.assertEqual("summary", path_finder.get_routing_path().pop().block_id)