Beispiel #1
0
def _get_fields(connection: Connection, answer: RowProxy) -> dict:
    """
    Extract the relevant fields for an answer (from the answer or
    answer_choice table).

    :param connection: a SQLAlchemy connection
    :param answer: A record in the answer or answer_choice table
    :return: A dictionary of the fields.
    """
    tcn = answer.type_constraint_name
    question_id = answer.question_id
    question = question_select(connection, question_id)
    result_dict = {'question_id': question_id,
                   'question_title': question.question_title,
                   'sequence_number': question.sequence_number,
                   'type_constraint_name': tcn,
                   'is_type_exception': _get_is_type_exception(answer)}
    try:
        # Get the choice for a multiple choice question
        choice_id = answer.question_choice_id
        result_dict['answer'] = choice_id
        result_dict['answer_choice_metadata'] = answer.answer_choice_metadata
        result_dict['answer_id'] = answer.answer_choice_id

        choice = question_choice_select(connection, choice_id)
        result_dict['choice'] = choice.choice
        result_dict['choice_number'] = choice.choice_number
    except AttributeError:
        # The answer is not a choice
        question = question_select(connection, answer.question_id)
        if answer.is_type_exception:
            tcn = 'text'
        result_dict['answer'] = _jsonify(connection, answer, tcn)
        result_dict['answer_metadata'] = answer.answer_metadata
        result_dict['answer_id'] = answer.answer_id
        result_dict['choice'] = None
        result_dict['choice_number'] = None
    return result_dict
Beispiel #2
0
def _create_questions(connection: Connection,
                      questions: list,
                      survey_id: str,
                      submission_map: dict=None) -> Iterator:
    """
    Create the questions of a survey. If this is an update to an existing
    survey, it will also copy over answers to the questions.

    :param connection: the SQLAlchemy Connection object for the transaction
    :param questions: a list of dictionaries, each containing the values
                      associated with a question
    :param survey_id: the UUID of the survey
    :param submission_map: a dictionary mapping old submission_id to new
    :return: an iterable of the resultant question fields
    """
    for number, question in enumerate(questions, start=1):
        values = question.copy()
        values['sequence_number'] = number
        values['survey_id'] = survey_id

        existing_q_id = values.pop('question_id', None)

        executable = question_insert(**values)
        tcn = values['type_constraint_name']
        exceptions = [('question_type_constraint_name_fkey',
                       TypeConstraintDoesNotExistError(tcn)),
                      ('minimal_logic',
                       MissingMinimalLogicError(values['logic']))]
        result = execute_with_exceptions(connection, executable, exceptions)
        result_ipk = result.inserted_primary_key
        q_id = result_ipk[0]

        choices = list(_create_choices(connection,
                                       values,
                                       q_id,
                                       submission_map=submission_map,
                                       existing_question_id=existing_q_id))

        if existing_q_id is not None:
            question_fields = {'question_id': q_id,
                               'sequence_number': result_ipk[1],
                               'allow_multiple': result_ipk[2],
                               'type_constraint_name': result_ipk[3],
                               'survey_id': survey_id}
            for answer in get_answers_for_question(connection, existing_q_id):
                new_tcn = result_ipk[3]
                old_tcn = question_select(connection,
                                          existing_q_id).type_constraint_name
                if new_tcn != old_tcn:
                    continue

                answer_values = question_fields.copy()
                answer_values['answer_metadata'] = answer.answer_metadata
                new_submission_id = submission_map[answer.submission_id]

                is_type_exception = _get_is_type_exception(answer)
                answer_values['is_type_exception'] = is_type_exception
                if is_type_exception:
                    answer_values['answer'] = answer.answer_text
                else:
                    answer_values['answer'] = answer['answer_' + new_tcn]

                allow_other = values['logic']['allow_other']
                allow_dont_know = values['logic']['allow_dont_know']
                with_type_exception = allow_other or allow_dont_know

                if new_tcn == 'multiple_choice' and not with_type_exception:
                    continue
                answer_values['submission_id'] = new_submission_id
                connection.execute(answer_insert(**answer_values))

        q_to_seq_number = values['question_to_sequence_number']
        yield {'question_id': q_id,
               'type_constraint_name': tcn,
               'sequence_number': values['sequence_number'],
               'allow_multiple': values['allow_multiple'],
               'choice_ids': choices,
               'question_to_sequence_number': q_to_seq_number}