def test_xform_with_opening_batch(self):
     batch = QuestionSet.get(id=self.qset.id)
     batch.open_for_location(self.ea.locations.first())
     response = self._make_odk_request()
     self.assertEquals(response.status_code, 200)
     path = '<formID>%s</formID>' % batch.pk
     self.assertIn(path, response.content)
Exemple #2
0
    def __init__(self, indicator, *args, **kwargs):
        super(IndicatorVariableForm, self).__init__(*args, **kwargs)
        self.indicator = indicator
        self.order_fields(['name',
                           'description',
                           'test_question',
                           'validation_test',
                           'options',
                           'value',
                           'min',
                           'max',
                           'var_qset'])
        if self.indicator:
            self.fields['test_question'].queryset = Question.objects.filter(
                pk__in=[q.pk for q in indicator.question_set.all_questions])

        if self.data.get('test_question', []):
            options = QuestionOption.objects.filter(
                question__pk=self.data['test_question'])
            self.fields['options'].choices = [
                (opt.order, opt.text) for opt in options]

        if self.data.get('var_qset', []):
            self.fields['test_question'].queryset = Question.objects.filter(
                id__in=[q.id for q in QuestionSet.get(id=self.data['var_qset']).all_questions])
 def _get_group_next_question(question, proposed_next):
     next_question = proposed_next
     present_question_group = question.group if hasattr(question, 'group') else None
     if next_question and AnswerAccessDefinition.is_valid(access.choice_name(),
                                                          next_question.answer_type) is False:
         next_question = _get_group_next_question(question, next_question.next_question(reply))
     # I hope the next line is not so confusing!
     # Basically it means treat only if the next question belongs to a different group from the present.
     # That's if present has a group
     if hasattr(next_question, 'group') and present_question_group != next_question.group:
         question_group = next_question.group
         if question_group:
             qset = QuestionSet.get(pk=next_question.qset.pk)
             valid_group = True
             for condition in question_group.group_conditions.all():
                 # we are interested in the qset param list with same identifier name as condition.test_question
                 test_question = qset.parameter_list.questions.get(identifier=condition.test_question.identifier)
                 param_value = ''            # use answer.as value
                 if session_data[ANSWERS][-1].get(test_question.identifier, None):    # last answer entry
                     param_value = session_data[ANSWERS][-1][test_question.identifier]
                 answer_class = Answer.get_class(condition.test_question.answer_type)
                 validator = getattr(answer_class, condition.validation_test, None)
                 if validator is None:
                     raise ValueError('unsupported validator defined on listing question')
                 try:
                     slogger.debug('parm val: %s, params: %s' % (param_value, condition.test_params))
                     is_valid = validator(param_value, *condition.test_params)
                 except:
                     is_valid = True
                 if is_valid is False:
                     valid_group = False
                     break   # fail if any condition fails
             if valid_group is False:
                 next_question = _get_group_next_question(question, next_question.next_question(reply))
     return next_question
def add_logic(request, qset_id, question_id):
    question = Question.get(id=question_id)
    batch = QuestionSet.get(id=qset_id)
    QuestionForm = get_question_form(batch.question_model())
    response = None
    cancel_url = '../'
    logic_form = LogicForm(question)
    question_rules_for_batch = {}
    #     question_rules_for_batch[question] = question.rules_for_batch(batch)
    if request.method == "POST":
        logic_form = LogicForm(question, data=request.POST)
        if logic_form.is_valid():
            logic_form.save()
            messages.success(request, 'Logic successfully added.')
            response = HttpResponseRedirect(
                reverse('qset_questions_page', args=(batch.pk, )))
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)
    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
        cancel_url = breadcrumbs[-1][1]
    context = {
        'logic_form': logic_form,
        'button_label': 'Save',
        'question': question,
        'USSD_MAX_CHARS': settings.USSD_MAX_CHARS,
        'rules_for_batch': question_rules_for_batch,
        'questionform': QuestionForm(batch, parent_question=question),
        'modal_action': reverse('add_qset_subquestion_page',
                                args=(batch.pk, )),
        'class': 'question-form',
        'batch_id': qset_id,
        'batch': batch,
        'cancel_url': cancel_url
    }
    return response or render(request, "set_questions/logic.html", context)
def edit(request, question_id):
    question = Question.get(id=question_id)
    batch = QuestionSet.get(pk=question.qset.pk)
    response, context = _render_question_view(
        request, batch, instance=question)
    context['page_title '] = 'Edit Question'
    return response or render(request, 'set_questions/new.html', context)
def _remove(request, question_id):
    question = Question.get(pk=question_id)
    batch_id = question.qset.id
    batch = QuestionSet.get(pk=batch_id)
    redirect_url = reverse('qset_questions_page', args=(batch_id, ))
    if question.total_answers() > 0:
        messages.error(
            request,
            "Cannot delete question that has been answered at least once.")
    else:
        _kill_zombies(batch.zombie_questions())
        if question:
            success_message = "Question successfully deleted."
            # % ("Sub question" if question.subquestion else "Question"))
            messages.success(request, success_message)
        next_question = batch.next_inline(question)
        previous_inline = question.connecting_flows.filter(validation__isnull=True)
        if previous_inline.exists() and next_question:
            QuestionFlow.objects.create(
                question=previous_inline[0].question,
                next_question=next_question)
        elif next_question:
            # need to delete the previous flow for the next question
            batch.start_question = next_question
            batch.save()
        question.connecting_flows.all().delete()
        question.flows.all().delete()
        question.delete()
    return HttpResponseRedirect(redirect_url)
def insert(request, prev_quest_id):
    prev_question = Question.get(pk=prev_quest_id)
    batch = QuestionSet.get(pk=prev_question.qset.pk)
    response, context = _render_question_view(
        request, batch, prev_question=prev_question)
    context['prev_question'] = prev_question
    return response or render(request, 'set_questions/new.html', context)
def _remove(request, question_id):
    question = Question.get(pk=question_id)
    batch_id = question.qset.id
    batch = QuestionSet.get(pk=batch_id)
    redirect_url = reverse('qset_questions_page', args=(batch_id, ))
    if question.total_answers() > 0:
        messages.error(
            request,
            "Cannot delete question that has been answered at least once.")
    else:
        _kill_zombies(batch.zombie_questions())
        if question:
            success_message = "Question successfully deleted."
            # % ("Sub question" if question.subquestion else "Question"))
            messages.success(request, success_message)
        next_question = batch.next_inline(question)
        previous_inline = question.connecting_flows.filter(
            validation__isnull=True)
        if previous_inline.exists() and next_question:
            QuestionFlow.objects.create(question=previous_inline[0].question,
                                        next_question=next_question)
        elif next_question:
            # need to delete the previous flow for the next question
            batch.start_question = next_question
            batch.save()
        question.connecting_flows.all().delete()
        question.flows.all().delete()
        question.delete()
    return HttpResponseRedirect(redirect_url)
Exemple #9
0
 def clean_identifier(self):
     identifier = self.cleaned_data['identifier']
     pattern = '^[a-zA-Z][0-9a-zA-Z_]+$'
     if re.match(pattern, identifier) is None:
         raise ValidationError(
             'Identifier must start with a letter, and must contain alphanumeric values or _')
     if Question.objects.filter(
             identifier__iexact=identifier,
             qset__pk=self.qset.pk).exists():
         if self.instance and self.instance.identifier == identifier:
             pass
         else:
             raise ValidationError(
                 '%s already in use for this %s' %
                 (identifier, model_class.type_name()))
     # if this is a batch question also check if there are parameter
     # questions with this name
     qset = QuestionSet.get(id=self.qset.pk)
     if hasattr(
             qset,
             'parameter_list') and qset.parameter_list and qset.parameter_list.parameters.filter(
             identifier__iexact=identifier).exists():
         raise ValidationError(
             '%s is already in captured as a group parameter for this %s' %
             (identifier, qset.verbose_name()))
     # for sampled surveys, check if this is already implemented in listing
     if hasattr(qset, 'survey') and qset.survey.listing_form and qset.survey.listing_form.questions.filter(
             identifier__iexact=identifier).exists():
         raise ValidationError(
             '%s is already in captured as a listing question for this %s' %
             (identifier, qset.verbose_name()))
     return self.cleaned_data['identifier']
Exemple #10
0
def identifiers(request):
    id = request.GET.get('id', None)
    last_question_id = request.GET.get('q_id', None)
    if last_question_id is None:
        json_dump = json.dumps(
            list(
                Question.objects.filter(
                    qset__id=id).values_list(
                    'identifier',
                    flat=True)))
    else:
        # return questions before last question
        qset = QuestionSet.get(pk=id)
        identifiers = set()
        for question in qset.flow_questions:
            if int(question.id) == int(last_question_id):
                break
            identifiers.add(question.identifier)
        # try:
        #     qset = Batch.get(pk=qset.pk)
        #     if hasattr(qset, 'parameter_list'):
        #         identifiers.union(qset.parameter_list.questions.values_list\
            #('identifier', flat=True))
        # except Batch.DoesNotExist:
        #     pass
        json_dump = json.dumps(list(identifiers))
    return HttpResponse(json_dump, content_type='application/json')
Exemple #11
0
 def clean_identifier(self):
     identifier = self.cleaned_data['identifier']
     pattern = '^[a-zA-Z][0-9a-zA-Z_]+$'
     if re.match(pattern, identifier) is None:
         raise ValidationError(
             'Identifier must start with a letter, and must contain alphanumeric values or _')
     if Question.objects.filter(
             identifier__iexact=identifier,
             qset__pk=self.qset.pk).exists():
         if self.instance and self.instance.identifier == identifier:
             pass
         else:
             raise ValidationError(
                 '%s already in use for this %s' %
                 (identifier, model_class.type_name()))
     # if this is a batch question also check if there are parameter
     # questions with this name
     qset = QuestionSet.get(id=self.qset.pk)
     if hasattr(
             qset,
             'parameter_list') and qset.parameter_list and qset.parameter_list.parameters.filter(
             identifier__iexact=identifier).exists():
         raise ValidationError(
             '%s is already in captured as a group parameter for this %s' %
             (identifier, qset.verbose_name()))
     # for sampled surveys, check if this is already implemented in listing
     if hasattr(qset, 'survey') and qset.survey.listing_form and qset.survey.listing_form.questions.filter(
             identifier__iexact=identifier).exists():
         raise ValidationError(
             '%s is already in captured as a listing question for this %s' %
             (identifier, qset.verbose_name()))
     return self.cleaned_data['identifier']
Exemple #12
0
def manage_loop(request, question_id):
    question = Question.get(id=question_id)
    batch = QuestionSet.get(pk=question.qset.pk)
    cancel_url = '../'
    existing_loop = getattr(question, 'loop_started', None)
    looping_form = LoopingForm(question, instance=existing_loop)
    if request.method == "POST":
        looping_form = LoopingForm(question,
                                   instance=existing_loop,
                                   data=request.POST)
        if looping_form.is_valid():
            looping_form.save()
            messages.success(request, 'Loop Logic successfully added.')
            return HttpResponseRedirect(
                reverse('qset_questions_page', args=(batch.pk, )))
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)

    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
        cancel_url = breadcrumbs[-1][1]
    context = {
        'loop_form': looping_form,
        'button_label': 'Save',
        'question': question,
        'cancel_url': cancel_url
    }
    return render(request, "set_questions/loop.html", context)
Exemple #13
0
def manage_loop(request, question_id):
    question = Question.get(id=question_id)
    batch = QuestionSet.get(pk=question.qset.pk)
    cancel_url = '../'
    existing_loop = getattr(question, 'loop_started', None)
    looping_form = LoopingForm(question, instance=existing_loop)
    if request.method == "POST":
        looping_form = LoopingForm(
            question,
            instance=existing_loop,
            data=request.POST)
        if looping_form.is_valid():
            looping_form.save()
            messages.success(request, 'Loop Logic successfully added.')
            return HttpResponseRedirect(
                reverse(
                    'qset_questions_page',
                    args=(
                        batch.pk,
                    )))
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)

    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
        cancel_url = breadcrumbs[-1][1]
    context = {
        'loop_form': looping_form,
        'button_label': 'Save',
        'question': question,
        'cancel_url': cancel_url}
    return render(request, "set_questions/loop.html", context)
Exemple #14
0
def index(request, qset_id):
    # now I'm gonna call question set a batch of questions.\
        #If there's time, I'll rename them properly
    # So don't get confused :)
    try:
        batch = QuestionSet.get(pk=qset_id)
    except QuestionSet.DoesNotExist:
        raise Http404("No QuestionSet Model matches the given query.")
    questions = batch.questions_inline()
    request_data = request.GET if request.method == 'GET' else request.POST
    question_filter_form = QuestionFilterForm(data=request_data, qset=batch)
    search_fields = ['identifier', 'text', ]
    qset_questions = batch.questions.all()
    if 'q' in request_data:
        questions = get_filterset(qset_questions, request_data['q'], search_fields)
    if 'question_types' in request_data:
        relevant_ids = list(question_filter_form.filter(
            qset_questions).values_list('id', flat=True))
        questions = [q for q in questions if q.id in relevant_ids]
    # now maintain same inline other exclusing questions in
    breadcrumbs = Question.index_breadcrumbs(qset=batch)
    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
    context = {'questions': questions, 'request': request, 'batch': batch,
               'question_filter_form': question_filter_form,
               'placeholder': 'identifier, text',
               'template_file': 'interviews/answer.html',
               'is_preview': True
               # caution atleast on ODK access
               #  at least on access must exist
               }
    return render(request, 'set_questions/index.html', context)
Exemple #15
0
def identifiers(request):
    id = request.GET.get('id', None)
    last_question_id = request.GET.get('q_id', None)
    if last_question_id is None:
        json_dump = json.dumps(
            list(
                Question.objects.filter(qset__id=id).values_list('identifier',
                                                                 flat=True)))
    else:
        # return questions before last question
        qset = QuestionSet.get(pk=id)
        identifiers = set()
        for question in qset.flow_questions:
            if int(question.id) == int(last_question_id):
                break
            identifiers.add(question.identifier)
        # try:
        #     qset = Batch.get(pk=qset.pk)
        #     if hasattr(qset, 'parameter_list'):
        #         identifiers.union(qset.parameter_list.questions.values_list\
        #('identifier', flat=True))
        # except Batch.DoesNotExist:
        #     pass
        json_dump = json.dumps(list(identifiers))
    return HttpResponse(json_dump, content_type='application/json')
Exemple #16
0
 def __init__(self, qset, *args, **kwargs):
     super(QuestionSetResultsFilterForm, self).__init__(*args, **kwargs)
     self.qset = QuestionSet.get(pk=qset.pk)
     if hasattr(self.qset, 'survey') is False:
         self.fields['survey'] = forms.ModelChoiceField(
             queryset=Survey.objects.filter(listing_form__pk=self.qset.pk),
             required=False,
             empty_label='Choose Survey')
Exemple #17
0
def edit(request, question_id):
    question = Question.get(id=question_id)
    batch = QuestionSet.get(pk=question.qset.pk)
    response, context = _render_question_view(request,
                                              batch,
                                              instance=question)
    context['page_title '] = 'Edit Question'
    return response or render(request, 'set_questions/new.html', context)
Exemple #18
0
def insert(request, prev_quest_id):
    prev_question = Question.get(pk=prev_quest_id)
    batch = QuestionSet.get(pk=prev_question.qset.pk)
    response, context = _render_question_view(request,
                                              batch,
                                              prev_question=prev_question)
    context['prev_question'] = prev_question
    return response or render(request, 'set_questions/new.html', context)
Exemple #19
0
def export_batch_questions(request, qset_id):
    batch = QuestionSet.get(pk=qset_id)
    filename = '%s_questions' % batch.name
    formatted_responses = get_question_as_dump(batch.flow_questions)
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;\
        filename="%s.csv"' % filename
    response.write("\r\n".join(formatted_responses))
    return response
 def _save_answers(self, request, session_data, navigation_interview):
     answers = session_data[ANSWERS]
     reference_interview = session_data.get(REF_INTERVIEW, None)
     qset = QuestionSet.get(pk=navigation_interview.question_set.pk)
     question_map = dict([(q.identifier, q) for q in qset.all_questions])
     survey = navigation_interview.survey
     ea = navigation_interview.ea
     Interview.save_answers(qset, survey, ea, navigation_interview.interview_channel, question_map, answers,
                            reference_interview=reference_interview)
Exemple #21
0
def export_batch_questions(request, qset_id):
    batch = QuestionSet.get(pk=qset_id)
    filename = '%s_questions' % batch.name
    formatted_responses = get_question_as_dump(batch.flow_questions)
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;\
        filename="%s.csv"' % filename
    response.write("\r\n".join(formatted_responses))
    return response
Exemple #22
0
def _save_subquestion(request, batch_id, instance=None):
    # possible subquestions are questions not bound to any interviewer yet
    batch = QuestionSet.get(pk=batch_id)
    QuestionForm = get_question_form(batch.question_model())
    questionform = QuestionForm(batch, instance=instance)
    if request.method == 'POST':
        questionform = QuestionForm(
            batch, data=request.POST, instance=instance)
        if questionform.is_valid():
            if instance:
                zombify = False
            else:
                zombify = True
            question = questionform.save(zombie=zombify)
            if request.is_ajax():
                return HttpResponse(
                    json.dumps(
                        {
                            'id': question.pk,
                            'text': question.text,
                            'identifier': question.identifier}),
                    content_type='application/json')
            messages.info(request, 'Sub Question saved')
    if instance:
        heading = 'Edit Subquestion'
    else:
        heading = 'New Subquestion'
    context = {
        'questionform': questionform,
        'button_label': 'Create',
        'id': 'add-sub_question-form',
        'USSD_MAX_CHARS': settings.USSD_MAX_CHARS,
        'save_url': reverse(
            '%s_home' %
            batch.resolve_tag()),
        'cancel_url': reverse(
            'qset_questions_page',
            args=(
                batch.pk,
            )),
        'class': 'question-form',
        'heading': heading}
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)
    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
    template_name = 'set_questions/new.html'
    if request.is_ajax():
        template_name = 'set_questions/_add_question.html'
        return render(request, template_name, context)
    else:
        return HttpResponseRedirect(
            reverse(
                'qset_questions_page',
                args=(
                    batch.pk,
                )))
Exemple #23
0
def question_validators(request):
    values = {}
    if request.GET.get('id'):
        for question in QuestionSet.get(
                id=request.GET.get('id')).all_questions:
            values['%s' % question.id] = [
                validator for validator in question.validator_names()]
    elif request.GET.get('ques_id'):
        values = Question.get(id=request.GET.get('ques_id')).validator_names()
    return HttpResponse(json.dumps(values), content_type='application/json')
Exemple #24
0
def handle_request(request, qset_id):
    qset = QuestionSet.get(id=qset_id)
    request_data = request.GET if request.method == 'GET' else request.POST
    mock_access = MockAccess(request, qset)
    if 'uid' in request_data:
        mock_access.id = str(request_data['uid'])
    handler = SimulatorView(
        mock_access,
        action_url=reverse('test_qset_flow', args=(qset_id, )))
    return handler.handle_session(request)
Exemple #25
0
def handle_request(request, qset_id):
    qset = QuestionSet.get(id=qset_id)
    request_data = request.GET if request.method == 'GET' else request.POST
    mock_access = MockAccess(request, qset)
    if 'uid' in request_data:
        mock_access.id = str(request_data['uid'])
    handler = SimulatorView(mock_access,
                            action_url=reverse('test_qset_flow',
                                               args=(qset_id, )))
    return handler.handle_session(request)
Exemple #26
0
def question_validators(request):
    values = {}
    if request.GET.get('id'):
        for question in QuestionSet.get(
                id=request.GET.get('id')).all_questions:
            values['%s' % question.id] = [
                validator for validator in question.validator_names()
            ]
    elif request.GET.get('ques_id'):
        values = Question.get(id=request.GET.get('ques_id')).validator_names()
    return HttpResponse(json.dumps(values), content_type='application/json')
def delete(request, question_id, batch_id):
    # todo: Should remove question_id from this parameters :(
    qset = QuestionSet.get(pk=batch_id)
    view = QuestionSetView(qset.__class__)
    if qset.__class__ == Batch:
        survey = qset.survey
        view.delete(request, qset)
        return HttpResponseRedirect(
            reverse('batch_index_page', args=(survey.id, )))
    else:
        return view.delete(request, qset)
Exemple #28
0
def list_questions(request):
    if request.GET.get('id'):
        values = [{
            'id': q.id,
            'identifier': q.identifier,
            'text': q.text
        } for q in QuestionSet.get(id=request.GET.get('id')).all_questions]
    else:
        values = list(Question.objects.all().values('id', 'identifier',
                                                    'text'))
    return HttpResponse(json.dumps(list(values)),
                        content_type='application/json')
Exemple #29
0
 def _is_relevant_by_group(qset):
     qset = QuestionSet.get(pk=qset.pk)
     relevant_new = []
     for condition in question_group.group_conditions.all():
         test_question = qset.parameter_list.questions.get(identifier=condition.test_question.identifier)
         answer_class = Answer.get_class(condition.test_question.answer_type)
         relevant_new.append(answer_class.print_odk_validation(get_group_question_path(qset, test_question),
                                                               condition.validation_test,  *condition.test_params))
     relevance_builder = ['false()', ]
     if relevant_new:
         relevance_builder.append('(%s)' % ' and '.join(relevant_new))
     return ' and (%s)' % ' or '.join(relevance_builder)
Exemple #30
0
def question_options(request):
    values = {}
    if request.GET.get('id'):
        for question in QuestionSet.get(
                id=request.GET.get('id')).all_questions:
            values['%s' % question.id] = dict([
                (opt.order, opt.text) for opt in question.options.all()
            ])
    elif request.GET.get('ques_id'):
        values = dict(
            Question.get(id=request.GET.get('ques_id')).options.values_list(
                'order', 'text'))
    return HttpResponse(json.dumps(values), content_type='application/json')
 def _get_group_next_question(question, proposed_next):
     next_question = proposed_next
     present_question_group = question.group if hasattr(
         question, 'group') else None
     if next_question and AnswerAccessDefinition.is_valid(
             access.choice_name(), next_question.answer_type) is False:
         next_question = _get_group_next_question(
             question, next_question.next_question(reply))
     # I hope the next line is not so confusing!
     # Basically it means treat only if the next question belongs to a different group from the present.
     # That's if present has a group
     if hasattr(
             next_question,
             'group') and present_question_group != next_question.group:
         question_group = next_question.group
         if question_group:
             qset = QuestionSet.get(pk=next_question.qset.pk)
             valid_group = True
             for condition in question_group.group_conditions.all():
                 # we are interested in the qset param list with same identifier name as condition.test_question
                 test_question = qset.parameter_list.questions.get(
                     identifier=condition.test_question.identifier)
                 param_value = ''  # use answer.as value
                 if session_data[ANSWERS][-1].get(
                         test_question.identifier,
                         None):  # last answer entry
                     param_value = session_data[ANSWERS][-1][
                         test_question.identifier]
                 answer_class = Answer.get_class(
                     condition.test_question.answer_type)
                 validator = getattr(answer_class,
                                     condition.validation_test, None)
                 if validator is None:
                     raise ValueError(
                         'unsupported validator defined on listing question'
                     )
                 try:
                     slogger.debug('parm val: %s, params: %s' %
                                   (param_value, condition.test_params))
                     is_valid = validator(param_value,
                                          *condition.test_params)
                 except:
                     is_valid = True
                 if is_valid is False:
                     valid_group = False
                     break  # fail if any condition fails
             if valid_group is False:
                 next_question = _get_group_next_question(
                     question, next_question.next_question(reply))
     return next_question
 def _save_answers(self, request, session_data, navigation_interview):
     answers = session_data[ANSWERS]
     reference_interview = session_data.get(REF_INTERVIEW, None)
     qset = QuestionSet.get(pk=navigation_interview.question_set.pk)
     question_map = dict([(q.identifier, q) for q in qset.all_questions])
     survey = navigation_interview.survey
     ea = navigation_interview.ea
     Interview.save_answers(qset,
                            survey,
                            ea,
                            navigation_interview.interview_channel,
                            question_map,
                            answers,
                            reference_interview=reference_interview)
Exemple #33
0
def question_options(request):
    values = {}
    if request.GET.get('id'):
        for question in QuestionSet.get(
                id=request.GET.get('id')).all_questions:
            values['%s' % question.id] = dict(
                [(opt.order, opt.text) for opt in question.options.all()])
    elif request.GET.get('ques_id'):
        values = dict(
            Question.get(
                id=request.GET.get('ques_id')).options.values_list(
                'order',
                'text'))
    return HttpResponse(json.dumps(values), content_type='application/json')
Exemple #34
0
def _save_subquestion(request, batch_id, instance=None):
    # possible subquestions are questions not bound to any interviewer yet
    batch = QuestionSet.get(pk=batch_id)
    QuestionForm = get_question_form(batch.question_model())
    questionform = QuestionForm(batch, instance=instance)
    if request.method == 'POST':
        questionform = QuestionForm(batch,
                                    data=request.POST,
                                    instance=instance)
        if questionform.is_valid():
            if instance:
                zombify = False
            else:
                zombify = True
            question = questionform.save(zombie=zombify)
            if request.is_ajax():
                return HttpResponse(json.dumps({
                    'id':
                    question.pk,
                    'text':
                    question.text,
                    'identifier':
                    question.identifier
                }),
                                    content_type='application/json')
            messages.info(request, 'Sub Question saved')
    if instance:
        heading = 'Edit Subquestion'
    else:
        heading = 'New Subquestion'
    context = {
        'questionform': questionform,
        'button_label': 'Create',
        'id': 'add-sub_question-form',
        'USSD_MAX_CHARS': settings.USSD_MAX_CHARS,
        'save_url': reverse('%s_home' % batch.resolve_tag()),
        'cancel_url': reverse('qset_questions_page', args=(batch.pk, )),
        'class': 'question-form',
        'heading': heading
    }
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)
    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
    template_name = 'set_questions/new.html'
    if request.is_ajax():
        template_name = 'set_questions/_add_question.html'
        return render(request, template_name, context)
    else:
        return HttpResponseRedirect(
            reverse('qset_questions_page', args=(batch.pk, )))
Exemple #35
0
def list_questions(request):
    if request.GET.get('id'):
        values = [{
            'id': q.id,
            'identifier': q.identifier,
            'text': q.text}
            for q in QuestionSet.get(id=request.GET.get('id')).all_questions]
    else:
        values = list(
            Question.objects.all().values(
                'id', 'identifier', 'text'))
    return HttpResponse(
        json.dumps(
            list(values)),
        content_type='application/json')
Exemple #36
0
def view_data(request, qset_id):
    qset = QuestionSet.get(pk=qset_id)
    request.breadcrumbs(qset.edit_breadcrumbs(qset=qset))
    disabled_fields = []
    request.GET = request.GET.copy()
    request.GET['question_set'] = qset_id
    disabled_fields.append('question_set')
    if hasattr(qset, 'survey'):
        request.GET['survey'] = qset.survey.id
        disabled_fields.append('survey')
    title = 'View Data'
    return _view_qset_data(request,
                           qset.__class__,
                           Interview.objects.filter(question_set__id=qset_id),
                           title,
                           disabled_fields=disabled_fields)
def identifiers(request):
    id = request.GET.get('id', None)
    last_question_id = request.GET.get('q_id', None)
    if last_question_id is None:
        json_dump = json.dumps(
            list(
                Question.objects.filter(qset__id=id).values_list('identifier',
                                                                 flat=True)))
    else:
        # return questions before last question
        qset = QuestionSet.get(pk=id)
        identifiers = set()
        for question in qset.flow_questions:
            if int(question.id) == int(last_question_id):
                break
            identifiers.add(question.identifier)
        json_dump = json.dumps(list(identifiers))
    return HttpResponse(json_dump, content_type='application/json')
Exemple #38
0
def view_data(request, qset_id):
    qset = QuestionSet.get(pk=qset_id)
    request.breadcrumbs(qset.edit_breadcrumbs(qset=qset))
    disabled_fields = []
    request.GET = request.GET.copy()
    request.GET['question_set'] = qset_id
    disabled_fields.append('question_set')
    if hasattr(qset, 'survey'):
        request.GET['survey'] = qset.survey.id
        disabled_fields.append('survey')
    title = 'View Data'
    return _view_qset_data(
        request,
        qset.__class__,
        Interview.objects.filter(
            question_set__id=qset_id),
        title,
        disabled_fields=disabled_fields)
Exemple #39
0
def update_orders(request, qset_id):
    batch = QuestionSet.get(id=qset_id)
    new_orders = request.POST.getlist('order_information', None)
    if len(new_orders) > 0:
        # wipe off present inline flows
        inlines = batch.questions_inline()
        if inlines:
            start_question = inlines[0]
            question = start_question
            while len(inlines) > 0:
                question = inlines.pop(0)
                QuestionFlow.objects.filter(question=question).delete()
            order_details = []
            map(lambda order: order_details.append(order.split('-')), new_orders)
            order_details = sorted(
                order_details, key=lambda detail: int(detail[0]))
            # recreate the flows
            questions = batch.questions.all()
            if questions:  # so all questions can be fetched once and cached
                question_id = order_details.pop(0)[1]
                start_question = questions.get(pk=question_id)
                for order, next_question_id in order_details:
                    QuestionFlow.objects.create(
                        question=questions.get(
                            pk=question_id), next_question=questions.get(
                            pk=next_question_id))
                    question_id = next_question_id
                batch.start_question = start_question
                batch.save()
            # better to clear all loops tied to this qset for now
            QuestionLoop.objects.filter(loop_starter__qset__pk=batch.pk).delete()
            success_message = "Question orders successfully updated for batch:\
                 %s." % batch.name.capitalize()
            messages.success(request, success_message)
    else:
        messages.error(request, 'No questions orders were updated.')
    return HttpResponseRedirect(
        reverse(
            'qset_questions_page',
            args=(
                batch.pk,
            )))
Exemple #40
0
def index(request, qset_id):
    # now I'm gonna call question set a batch of questions.\
    #If there's time, I'll rename them properly
    # So don't get confused :)
    try:
        batch = QuestionSet.get(pk=qset_id)
    except QuestionSet.DoesNotExist:
        raise Http404("No QuestionSet Model matches the given query.")
    questions = batch.questions_inline()
    request_data = request.GET if request.method == 'GET' else request.POST
    question_filter_form = QuestionFilterForm(data=request_data, qset=batch)
    search_fields = [
        'identifier',
        'text',
    ]
    qset_questions = batch.questions.all()
    if 'q' in request_data:
        questions = get_filterset(qset_questions, request_data['q'],
                                  search_fields)
    if 'question_types' in request_data:
        relevant_ids = list(
            question_filter_form.filter(qset_questions).values_list('id',
                                                                    flat=True))
        questions = [q for q in questions if q.id in relevant_ids]
    # now maintain same inline other exclusing questions in
    breadcrumbs = Question.index_breadcrumbs(qset=batch)
    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
    context = {
        'questions': questions,
        'request': request,
        'batch': batch,
        'question_filter_form': question_filter_form,
        'placeholder': 'identifier, text',
        'template_file': 'interviews/answer.html',
        'is_preview': True
        # caution atleast on ODK access
        #  at least on access must exist
    }
    return render(request, 'set_questions/index.html', context)
Exemple #41
0
def update_orders(request, qset_id):
    batch = QuestionSet.get(id=qset_id)
    new_orders = request.POST.getlist('order_information', None)
    if len(new_orders) > 0:
        # wipe off present inline flows
        inlines = batch.questions_inline()
        if inlines:
            start_question = inlines[0]
            question = start_question
            while len(inlines) > 0:
                question = inlines.pop(0)
                QuestionFlow.objects.filter(question=question).delete()
            order_details = []
            map(lambda order: order_details.append(order.split('-')),
                new_orders)
            order_details = sorted(order_details,
                                   key=lambda detail: int(detail[0]))
            # recreate the flows
            questions = batch.questions.all()
            if questions:  # so all questions can be fetched once and cached
                question_id = order_details.pop(0)[1]
                start_question = questions.get(pk=question_id)
                for order, next_question_id in order_details:
                    QuestionFlow.objects.create(
                        question=questions.get(pk=question_id),
                        next_question=questions.get(pk=next_question_id))
                    question_id = next_question_id
                batch.start_question = start_question
                batch.save()
            # better to clear all loops tied to this qset for now
            QuestionLoop.objects.filter(
                loop_starter__qset__pk=batch.pk).delete()
            success_message = "Question orders successfully updated for batch:\
                 %s." % batch.name.capitalize()
            messages.success(request, success_message)
    else:
        messages.error(request, 'No questions orders were updated.')
    return HttpResponseRedirect(
        reverse('qset_questions_page', args=(batch.pk, )))
Exemple #42
0
def download_data(request, qset_id):
    qset = QuestionSet.get(pk=qset_id)
    params = request.GET if request.method == 'GET' else request.POST
    survey_filter = QuestionSetResultsFilterForm(qset, data=params)
    locations_filter = LocationsFilterForm(data=request.GET, include_ea=True)
    interviews = survey_filter.get_interviews()
    if locations_filter.is_valid():
        interviews = interviews.filter(
            ea__in=locations_filter.get_enumerations()).order_by('created')
    last_selected_loc = locations_filter.last_location_selected
    download_service = ResultsDownloadService(qset, interviews=interviews)
    file_name = '%s%s' % ('%s-%s-' %
                          (last_selected_loc.type.name, last_selected_loc.name)
                          if last_selected_loc else '', qset.name)
    reports_df = download_service.generate_interview_reports()
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;\
        filename="%s.csv"' % file_name
    reports_df.to_csv(response,
                      date_format='%Y-%m-%d %H:%M:%S',
                      encoding='utf-8')  # exclude interview id
    return response
Exemple #43
0
def add_logic(request, qset_id, question_id):
    question = Question.get(id=question_id)
    batch = QuestionSet.get(id=qset_id)
    QuestionForm = get_question_form(batch.question_model())
    response = None
    cancel_url = '../'
    logic_form = LogicForm(question)
    question_rules_for_batch = {}
#     question_rules_for_batch[question] = question.rules_for_batch(batch)
    if request.method == "POST":
        logic_form = LogicForm(question, data=request.POST)
        if logic_form.is_valid():
            logic_form.save()
            messages.success(request, 'Logic successfully added.')
            response = HttpResponseRedirect(
                reverse('qset_questions_page', args=(batch.pk, )))
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)
    if breadcrumbs:
        request.breadcrumbs(breadcrumbs)
        cancel_url = breadcrumbs[-1][1]
    context = {
        'logic_form': logic_form,
        'button_label': 'Save',
        'question': question,
        'USSD_MAX_CHARS': settings.USSD_MAX_CHARS,
        'rules_for_batch': question_rules_for_batch,
        'questionform': QuestionForm(
            batch,
            parent_question=question),
        'modal_action': reverse(
            'add_qset_subquestion_page',
            args=(
                batch.pk,
            )),
        'class': 'question-form',
        'batch_id': qset_id,
        'batch': batch,
        'cancel_url': cancel_url}
    return response or render(request, "set_questions/logic.html", context)
Exemple #44
0
 def clean_group(self):
     group = self.cleaned_data['group']
     if group:
         qset = QuestionSet.get(id=self.qset.pk)
         identifiers = group.parameter_questions().values_list('identifier', flat=True)
         existing_identifiers = Question.objects.filter(identifier__in=identifiers,
                                                        qset__pk=self.qset.pk).values_list('identifier', flat=True)
         if existing_identifiers.exists():
             raise ValidationError(
                 '%s already exist in this %s. '
                 'Consider creating a question with modified identifier name and using skip logic in your %s' %
                 (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name()))
         if hasattr(qset, 'survey') and qset.survey.listing_form:
             existing_identifiers = qset.survey.listing_form.questions.filter(identifier__in=identifiers
                                                                              ).values_list('identifier',
                                                                                            flat=True)
             if existing_identifiers.exists():
                 raise ValidationError(
                     '%s already exist as a listing question for this %s. '
                     'Consider creating a question with modified identifier name and using skip logic in your %s' %
                     (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name()))
     return group
 def handle(self, *args, **kwargs):
     """Basically loads each line of the csv as9 responses to the question set
     each row is seen as a seperate interview.9
     first field would be the ea ID, subsequent fields would be the answers9
     :param args:
     :param kwargs:
     :return:
     """
     self.stdout.write('Starting...')
     delimiter = kwargs.get('delim', ',')
     df = pd.read_csv(args[0], delimiter=delimiter)
     interviewer = Interviewer.get(pk=args[1])
     survey = Survey.get(pk=args[2])
     qset = QuestionSet.get(pk=int(args[3]))
     odk_access = interviewer.odk_access[0]
     all_questions = qset.all_questions
     eas = {}
     #>with transaction.atomic():
     df.apply(save_interview,
              axis=1,
              args=(interviewer, odk_access, survey, qset, all_questions,
                    eas))
     self.stdout.write('Successfully imported!')
Exemple #46
0
    def __init__(self, indicator, *args, **kwargs):
        super(IndicatorVariableForm, self).__init__(*args, **kwargs)
        self.indicator = indicator
        self.order_fields([
            'name', 'description', 'test_question', 'validation_test',
            'options', 'value', 'min', 'max', 'var_qset'
        ])
        if self.indicator:
            self.fields['test_question'].queryset = Question.objects.filter(
                pk__in=[q.pk for q in indicator.question_set.all_questions])

        if self.data.get('test_question', []):
            options = QuestionOption.objects.filter(
                question__pk=self.data['test_question'])
            self.fields['options'].choices = [(opt.order, opt.text)
                                              for opt in options]

        if self.data.get('var_qset', []):
            self.fields['test_question'].queryset = Question.objects.filter(
                id__in=[
                    q.id for q in QuestionSet.get(
                        id=self.data['var_qset']).all_questions
                ])
Exemple #47
0
 def clean_group(self):
     group = self.cleaned_data['group']
     if group:
         qset = QuestionSet.get(id=self.qset.pk)
         identifiers = group.parameter_questions().values_list('identifier', flat=True)
         existing_identifiers = Question.objects.filter(identifier__in=identifiers,
                                                        qset__pk=self.qset.pk).values_list('identifier',
                                                                                           flat=True)
         if existing_identifiers.exists():
             raise ValidationError(
                 '%s already exist in this %s. '
                 'Consider creating a question with modified identifier name and using skip logic in your %s' %
                 (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name()))
         if hasattr(qset, 'survey') and qset.survey.listing_form:
             existing_identifiers = qset.survey.listing_form.questions.filter(identifier__in=identifiers
                                                                              ).values_list('identifier',
                                                                                            flat=True)
             if existing_identifiers.exists():
                 raise ValidationError(
                     '%s already exist as a listing question for this %s. '
                     'Consider creating a question with modified identifier name '
                     'and using skip logic in your %s' %
                     (','.join(existing_identifiers), qset.verbose_name(), qset.verbose_name()))
     return group
Exemple #48
0
def download_data(request, qset_id):
    qset = QuestionSet.get(pk=qset_id)
    params = request.GET if request.method == 'GET' else request.POST
    survey_filter = QuestionSetResultsFilterForm(qset, data=params)
    locations_filter = LocationsFilterForm(data=request.GET, include_ea=True)
    interviews = survey_filter.get_interviews()
    if locations_filter.is_valid():
        interviews = interviews.filter(
            ea__in=locations_filter.get_enumerations()).order_by('created')
    last_selected_loc = locations_filter.last_location_selected
    download_service = ResultsDownloadService(qset, interviews=interviews)
    file_name = '%s%s' % ('%s-%s-' % (
        last_selected_loc.type.name,
        last_selected_loc.name) if last_selected_loc else '',
        qset.name)
    reports_df = download_service.generate_interview_reports()
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;\
        filename="%s.csv"' % file_name
    reports_df.to_csv(
        response,
        date_format='%Y-%m-%d %H:%M:%S',
        encoding='utf-8')  # exclude interview id
    return response
Exemple #49
0
def get_questions_for_batch(request, batch_id, question_id):
    batch = QuestionSet.get(id=batch_id)
    questions = batch.questions_inline()
    questions = [q for q in questions if int(q.pk) is not int(question_id)]
    return _create_question_hash_response(questions)
Exemple #50
0
 def __init__(self, request, qset, access_type=ODKAccess.choice_name()):
     self.id = 'test: %s, %s' % (request.user.username, qset.id)
     self.question_set = QuestionSet.get(id=qset.id)
     self.user_identifier = self.id
     self.access_type = access_type
Exemple #51
0
def new(request, qset_id):
    batch = QuestionSet.get(pk=qset_id)             # can be listng or actual batch
    response, context = _render_question_view(request, batch)
    context['page_title '] = 'Add Question'
    return response or render(request, 'set_questions/new.html', context)
Exemple #52
0
def clone_qset(request, qset_id):
    qset = QuestionSet.get(pk=qset_id)
    qset.deep_clone()
    messages.info(request, 'Successfully cloned %s' % qset.name)
    return HttpResponseRedirect(reverse('%s_home' % qset.resolve_tag()))
Exemple #53
0
 def __init__(self, request, qset, access_type=ODKAccess.choice_name()):
     self.id = 'test: %s, %s' % (request.user.username, qset.id)
     self.question_set = QuestionSet.get(id=qset.id)
     self.user_identifier = self.id
     self.access_type = access_type
Exemple #54
0
def new(request, qset_id):
    batch = QuestionSet.get(pk=qset_id)  # can be listng or actual batch
    response, context = _render_question_view(request, batch)
    context['page_title '] = 'Add Question'
    return response or render(request, 'set_questions/new.html', context)
Exemple #55
0
def _get_qset(survey_tree):
    pk = _get_nodes(FORM_ID_PATH, tree=survey_tree)[0]
    return QuestionSet.get(pk=pk)
Exemple #56
0
 def __init__(self, qset, *args, **kwargs):
     super(QuestionSetResultsFilterForm, self).__init__(*args, **kwargs)
     self.qset = QuestionSet.get(pk=qset.pk)
     if hasattr(self.qset, 'survey') is False:
         self.fields['survey'] = forms.ModelChoiceField(queryset=Survey.objects.filter(
             listing_form__pk=self.qset.pk), required=False, empty_label='Choose Survey')
Exemple #57
0
def get_questions_for_batch(request, batch_id, question_id):
    batch = QuestionSet.get(id=batch_id)
    questions = batch.questions_inline()
    questions = [q for q in questions if int(q.pk) is not int(question_id)]
    return _create_question_hash_response(questions)
Exemple #58
0
def assign(request, qset_id):
    batch = QuestionSet.get(id=qset_id)
    if batch.interviews.count():
        error_message = "Questions cannot be assigned \
            interviews has already been conducted: %s."                                                        % \
                        batch.name.capitalize()
        messages.error(request, error_message)
        return HttpResponseRedirect(
            reverse('qset_questions_page', args=(batch.pk, )))
    if request.method == 'POST':
        data = dict(request.POST)
        last_question = batch.last_question_inline()
        lib_questions = QuestionTemplate.objects.filter(
            identifier__in=data.get('identifier', ''))
        if lib_questions:
            for lib_question in lib_questions:
                question = Question.objects.create(
                    identifier=lib_question.identifier,
                    text=lib_question.text,
                    answer_type=lib_question.answer_type,
                    qset=batch,
                )
                # assign the options
                for option in lib_question.options.all():
                    QuestionOption.objects.create(question=question,
                                                  text=option.text,
                                                  order=option.order)
                if last_question:
                    QuestionFlow.objects.create(question=last_question,
                                                next_question=question)
                else:
                    batch.start_question = question
                    batch.save()
                last_question = question
            #batch_questions_form = BatchQuestionsForm(batch=batch,\
            #\data=request.POST, instance=batch)
        success_message = "Questions successfully assigned to %s: %s." % (
            batch.verbose_name(), batch.name.capitalize())
        messages.success(request, success_message)
        return HttpResponseRedirect(
            reverse('qset_questions_page', args=(batch.pk, )))
    used_identifiers = [
        question.identifier for question in batch.questions.all()
    ]
    library_questions = QuestionTemplate.objects.exclude(
        identifier__in=used_identifiers).order_by('identifier')
    question_filter_form = QuestionFilterForm()
    #     library_questions =  question_filter_form.filter(library_questions)
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)
    page_name = ''
    if breadcrumbs:
        if breadcrumbs[0][0] == 'Listing Form':
            page_name = 'Listing'
        else:
            page_name = 'Batch'
        request.breadcrumbs(breadcrumbs)
    context = {
        'batch_questions_form': unicode(BatchQuestionsForm()),
        'batch': batch,
        'button_label': 'Save',
        'id': 'assign-question-to-batch-form',
        'library_questions': library_questions,
        'question_filter_form': question_filter_form,
        'page_name': page_name,
        'redirect_url': '/qsets/%s/questions/' % qset_id
    }
    return render(request, 'set_questions/assign.html', context)
Exemple #59
0
def assign(request, qset_id):
    batch = QuestionSet.get(id=qset_id)
    if batch.interviews.count():
        error_message = "Questions cannot be assigned \
            interviews has already been conducted: %s." % \
                        batch.name.capitalize()
        messages.error(request, error_message)
        return HttpResponseRedirect(
            reverse(
                'qset_questions_page',
                args=(
                    batch.pk,
                )))
    if request.method == 'POST':
        data = dict(request.POST)
        last_question = batch.last_question_inline()
        lib_questions = QuestionTemplate.objects.filter(
            identifier__in=data.get('identifier', ''))
        if lib_questions:
            for lib_question in lib_questions:
                question = Question.objects.create(
                    identifier=lib_question.identifier,
                    text=lib_question.text,
                    answer_type=lib_question.answer_type,
                    qset=batch,
                )
                # assign the options
                for option in lib_question.options.all():
                    QuestionOption.objects.create(
                        question=question,
                        text=option.text,
                        order=option.order)
                if last_question:
                    QuestionFlow.objects.create(
                        question=last_question, next_question=question)
                else:
                    batch.start_question = question
                    batch.save()
                last_question = question
            #batch_questions_form = BatchQuestionsForm(batch=batch,\
                #\data=request.POST, instance=batch)
        success_message = "Questions successfully assigned to %s: %s." % (
            batch.verbose_name(), batch.name.capitalize())
        messages.success(request, success_message)
        return HttpResponseRedirect(
            reverse(
                'qset_questions_page',
                args=(
                    batch.pk,
                )))
    used_identifiers = [
        question.identifier for question in batch.questions.all()]
    library_questions = QuestionTemplate.objects.exclude(
        identifier__in=used_identifiers).order_by('identifier')
    question_filter_form = QuestionFilterForm()
#     library_questions =  question_filter_form.filter(library_questions)
    breadcrumbs = Question.edit_breadcrumbs(qset=batch)
    page_name = ''
    if breadcrumbs:
        if breadcrumbs[0][0] == 'Listing Form':
            page_name = 'Listing'
        else:
            page_name = 'Batch'
        request.breadcrumbs(breadcrumbs)
    context = {
        'batch_questions_form': unicode(
            BatchQuestionsForm()),
        'batch': batch,
        'button_label': 'Save',
        'id': 'assign-question-to-batch-form',
        'library_questions': library_questions,
        'question_filter_form': question_filter_form,
        'page_name': page_name,
        'redirect_url': '/qsets/%s/questions/' % qset_id}
    return render(request, 'set_questions/assign.html',
                  context)