def test_update_multichoice_answer(self):
     qset = self.qset
     self._create_test_non_group_questions(qset)
     multichoice_question = Question.objects.filter(
         answer_type=MultiChoiceAnswer.choice_name()).first()
     options = multichoice_question.options.all()
     MultiChoiceAnswer.create(self.interview, multichoice_question,
                              options.first().text)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 1)
     multichoice_answer = MultiChoiceAnswer.objects.first()
     self.assertEquals(multichoice_answer.as_text.lower(),
                       options.first().text.lower())
     self.assertEquals(int(multichoice_answer.as_value),
                       options.first().order)
     # confirm using value instead yields ame result
     MultiChoiceAnswer.create(self.interview, multichoice_question,
                              options.first().order)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 2)
     multichoice_answer = MultiChoiceAnswer.objects.last()
     self.assertEquals(multichoice_answer.as_text.lower(),
                       options.first().text.lower())
     self.assertEquals(int(multichoice_answer.as_value),
                       options.first().order)
     # confirm update now
     multichoice_answer.update(options.last().text)
     multichoice_answer.refresh_from_db()
     self.assertEquals(int(multichoice_answer.as_value),
                       options.last().order)
     # update back to original option
     multichoice_answer.update(options.first().order)
     multichoice_answer.refresh_from_db()
     self.assertEquals(int(multichoice_answer.as_value),
                       options.first().order)
Example #2
0
 def test_answer_value_methods(self):
     value = 'me doing somthing'
     test_answer1 = 'nothing good'
     self.assertFalse(Answer.equals(test_answer1, value))
     self.assertTrue(Answer.equals(value, value))
     self.assertTrue(Answer.starts_with(value, 'me d'))
     self.assertFalse(Answer.ends_with(value, 'no thing'))
     self.assertTrue(Answer.ends_with(value, 'somthing'))
     self.assertFalse(Answer.greater_than(5, 9))
     self.assertTrue(Answer.greater_than(9, 5))
     self.assertTrue(Answer.less_than(5, 9))
     self.assertFalse(Answer.less_than(9, 5))
     self.assertFalse(Answer.between(9, 5, 7))
     self.assertTrue(Answer.between(9, 5, 11))
     self.assertTrue(Answer.passes_test('17 > 10'))
     self.assertFalse(NumericalAnswer.greater_than(5, 9))
     self.assertTrue(NumericalAnswer.greater_than(9, 5))
     self.assertTrue(NumericalAnswer.less_than(5, 9))
     self.assertFalse(NumericalAnswer.less_than(9, 5))
     self.assertFalse(NumericalAnswer.between(9, 5, 7))
     self.assertTrue(NumericalAnswer.between(9, 5, 11))
     self.assertFalse(TextAnswer.equals(test_answer1, value))
     self.assertTrue(TextAnswer.equals(value, value))
     self.assertFalse(MultiChoiceAnswer.equals(test_answer1, value))
     self.assertTrue(MultiChoiceAnswer.equals(value, value))
     self.assertFalse(MultiSelectAnswer.equals(test_answer1, value))
     self.assertTrue(MultiSelectAnswer.equals(value, value))
     self.assertFalse(DateAnswer.greater_than('12-09-2017', '12-09-2017'))
     self.assertTrue(DateAnswer.greater_than('13-09-2017', '12-09-2017'))
     self.assertFalse(DateAnswer.less_than('18-09-2017', '12-09-2017'))
     self.assertTrue(DateAnswer.less_than('13-09-2017', '17-09-2017'))
     self.assertFalse(
         DateAnswer.between('18-09-2017', '12-09-2017', '16-09-2017'))
     self.assertTrue(
         DateAnswer.between('14-09-2017', '12-09-2017', '16-09-2017'))
    def _check__multichoice_and_options_compatibility(self, answer_type, options):
        if answer_type in [MultiChoiceAnswer.choice_name(), MultiSelectAnswer.choice_name()] and not options:
            message = 'Question Options missing.'
            self._errors['answer_type'] = self.error_class([message])
            del self.cleaned_data['answer_type']

        if answer_type not in [MultiChoiceAnswer.choice_name(), MultiSelectAnswer.choice_name()] and options:
            del self.cleaned_data['options']
Example #4
0
    def _check__multichoice_and_options_compatibility(self, answer_type, options):
        if answer_type in [MultiChoiceAnswer.choice_name(), MultiSelectAnswer.choice_name()] and not options:
            message = 'Question Options missing.'
            self._errors['answer_type'] = self.error_class([message])
            del self.cleaned_data['answer_type']

        if answer_type not in [MultiChoiceAnswer.choice_name(), MultiSelectAnswer.choice_name()] and options:
            del self.cleaned_data['options']
 def test_end_interview_selection_in_form_question_creates_flow_to_with_no_next_question(self):
     '''
     :return:
     '''
     yes = 'yes'
     no = 'no'
     q1 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test1',
                                  text='test1', answer_type=DateAnswer.choice_name())
     q2 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test2',
                                  text='test2', answer_type=MultiChoiceAnswer.choice_name())
     q_o1 = QuestionOption.objects.create(question_id=q2.id, text=yes, order=1)
     QuestionOption.objects.create(question_id=q2.id, text=no, order=2)
     q3 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test3',
                                  text='test3', answer_type=DateAnswer.choice_name())
     q4 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test4',
                                  text='test4', answer_type=DateAnswer.choice_name())
     q5 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test5',
                                  text='test5', answer_type=DateAnswer.choice_name())
     self.batch.start_question = q1
     QuestionFlow.objects.create(question_id=q1.id, next_question_id=q2.id)
     QuestionFlow.objects.create(question_id=q2.id, next_question_id=q3.id)
     QuestionFlow.objects.create(question_id=q3.id, next_question_id=q4.id)
     QuestionFlow.objects.create(question_id=q4.id, next_question_id=q5.id)
     test_condition = MultiChoiceAnswer.validators()[0].__name__
     form_data = {
         'action': LogicForm.END_INTERVIEW,
         'condition': test_condition,
         'option': q_o1.order
     }
     l = LogicForm(q2, data=form_data)
     if l.is_valid():
         l.save()
         # now check if equivalent Question flow and test arguments were
         # created
         try:
             qf = QuestionFlow.objects.get(
                 question_id=q2.id, next_question_id__isnull=True)
             TextArgument.objects.get(flow=qf, position=0, param=q_o1.order)
             QuestionFlow.objects.get(
                 question_id=q1.id, next_question_id=q2.id)
             QuestionFlow.objects.get(
                 question_id=q2.id, next_question_id=q3.id)
             self.assertTrue(True)
             return
         except QuestionFlow.DoesNotExist:
             self.assertTrue(False, 'flow not existing')
             pass
         except TextArgument:
             self.assertTrue(False, 'text agrunments not saved')
             pass
     else:
         self.assertFalse(False, 'Invalid form')
Example #6
0
 def clean(self):
     validation_test = self.cleaned_data.get('validation_test', None)
     test_question = self.cleaned_data.get('test_question', None)
     if validation_test is None or test_question is None:
         return self.cleaned_data
     answer_class = Answer.get_class(test_question.answer_type)
     method = getattr(answer_class, validation_test, None)
     if method is None:
         raise forms.ValidationError(
             'unsupported validator defined on test question')
     if validation_test == 'between':
         if self.cleaned_data.get(
                 'min', False) is False or self.cleaned_data.get(
                 'max', False) is False:
             raise forms.ValidationError(
                 'min and max values required for between condition')
     elif self.cleaned_data.get('value', False) is False:
         raise forms.ValidationError(
             'Value is required for %s' %
             validation_test)
     if test_question.answer_type in [
             MultiChoiceAnswer.choice_name(),
             MultiSelectAnswer]:
         if self.cleaned_data.get('options', False) is False:
             raise forms.ValidationError(
                 'No option selected for %s' %
                 test_question.identifier)
         self.cleaned_data['value'] = self.cleaned_data['options']
     return self.cleaned_data
Example #7
0
 def clean_value(self):
     if self.cleaned_data.get('value'):
         if question.answer_type == MultiChoiceAnswer.choice_name():
             try:
                 self.cleaned_data['value'] = question.options.get(
                     order=self.cleaned_data['value'])
             except QuestionOption.DoesNotExist:
                 raise ValidationError('Please select a valid option')
         if question.answer_type == GeopointAnswer.choice_name():
             float_entries = self.cleaned_data['value'].split(' ')
             valid = False
             try:
                 map(lambda entry: float(entry), float_entries)
                 if len(float_entries) == 4:
                     valid = True
             except BaseException:
                 pass
             if not valid:
                 raise ValidationError(
                     'Please enter in format: lat[space]long[space]altitude[space]precision'
                 )
         # validate the response if the last question has validation
         if interview.last_question and interview.last_question.response_validation:
             response_validation = interview.last_question.response_validation
             if response_validation.validate(
                     self.cleaned_data['value'],
                     interview.last_question) is False:
                 raise ValidationError(
                     response_validation.dconstraint_message)
         return self.cleaned_data['value']
Example #8
0
 def clean_value(self):
     if self.cleaned_data.get('value'):
         if question.answer_type == MultiChoiceAnswer.choice_name():
             try:
                 self.cleaned_data['value'] = question.options.get(
                     order=self.cleaned_data['value'])
             except QuestionOption.DoesNotExist:
                 raise ValidationError('Please select a valid option')
         if question.answer_type == GeopointAnswer.choice_name():
             float_entries = self.cleaned_data['value'].split(' ')
             valid = False
             try:
                 map(lambda entry: float(entry), float_entries)
                 if len(float_entries) == 4:
                     valid = True
             except BaseException:
                 pass
             if not valid:
                 raise ValidationError(
                     'Please enter in format: lat[space]long[space]altitude[space]precision')
         # validate the response if the last question has validation
         if interview.last_question and interview.last_question.response_validation:
             response_validation = interview.last_question.response_validation
             if response_validation.validate(self.cleaned_data['value'], interview.last_question) is False:
                 raise ValidationError(response_validation.dconstraint_message)
         return self.cleaned_data['value']
Example #9
0
 def save(self, *args, **kwargs):
     next_question = None
     desc = self._make_desc()
     if self.cleaned_data['action'] in [
             self.ASK_SUBQUESTION, self.SKIP_TO, self.BACK_TO]:
         next_question = Question.get(pk=self.cleaned_data['next_question'])
     if self.cleaned_data['action'] == self.REANSWER:
         next_question = self.question
     validation = ResponseValidation.objects.create(validation_test=self.cleaned_data['condition'])
     flow = QuestionFlow.objects.create(question=self.question,
                                        validation=validation,
                                        next_question=next_question,
                                        desc=desc)
     if self.cleaned_data['action'] == self.ASK_SUBQUESTION:
         # connect back to next inline question of the main
         QuestionFlow.objects.create(
             question=next_question,
             desc=desc,
             next_question=self.batch.next_inline(
                 self.question))
     if self.cleaned_data['condition'] == 'between':
         TextArgument.objects.create(validation=validation, position=0, param=self.cleaned_data['min_value'])
         TextArgument.objects.create(validation=validation, position=1, param=self.cleaned_data['max_value'])
     else:
         value = self.cleaned_data.get('value', '')
         if self.question.answer_type in [
                 MultiChoiceAnswer.choice_name(),
                 MultiSelectAnswer.choice_name()]:
             value = self.cleaned_data['option']
         TextArgument.objects.create(validation=validation, position=0, param=value)
     # clean up now, remove all zombie questions
     self.question.qset.zombie_questions().delete()
Example #10
0
 def clean(self):
     validation_test = self.cleaned_data.get('validation_test', None)
     test_question = self.cleaned_data.get('test_question', None)
     if validation_test is None or test_question is None:
         return self.cleaned_data
     answer_class = Answer.get_class(test_question.answer_type)
     method = getattr(answer_class, validation_test, None)
     if method is None:
         raise forms.ValidationError(
             'unsupported validator defined on test question')
     if validation_test == 'between':
         if self.cleaned_data.get('min',
                                  None) is None or self.cleaned_data.get(
                                      'max', None) is None:
             raise forms.ValidationError(
                 'min and max values required for between condition')
     elif test_question.answer_type in [
             MultiChoiceAnswer.choice_name(), MultiSelectAnswer
     ]:
         if not self.cleaned_data.get('options', False):
             raise forms.ValidationError('No option selected for %s' %
                                         test_question.identifier)
         self.cleaned_data['value'] = self.cleaned_data['options']
     elif self.cleaned_data.get('value', False) is False:
         raise forms.ValidationError('Value is required for %s' %
                                     validation_test)
     return self.cleaned_data
Example #11
0
 def _test_create_sampling_criteria_with_multichoice(self):
     self.assertEquals(Survey.objects.count(), 1)
     survey = self.survey
     sampling_criteria_url = reverse('listing_criteria_page',
                                     args=(survey.id, ))
     listing_question = self.qset.questions.filter(
         answer_type=MultiChoiceAnswer.choice_name()).first()
     form_data = {
         'survey': survey.id,
         'validation_test': 'equals',
         'options': listing_question.options.first().text,
         'value': listing_question.options.first().text,
         'listing_question': listing_question.id,
     }
     initial_count = survey.randomization_criteria.count()
     response = self.client.post(sampling_criteria_url, data=form_data)
     self.assertRedirects(response,
                          sampling_criteria_url,
                          status_code=302,
                          target_status_code=200,
                          msg_prefix='')
     self.assertEquals(survey.randomization_criteria.count(),
                       initial_count + 1)  # confirm one criteria created
     randomization_criteria = survey.randomization_criteria.last()
     # test params display
     self.assertEquals(len(randomization_criteria.params_display()), 1)
     for param in randomization_criteria.params_display():
         self.assertTrue(param, [
             listing_question.options.first().text,
         ])
Example #12
0
    def clean(self):
        super(SamplingCriterionForm, self).clean()
        validation_test = self.cleaned_data.get('validation_test', None)
        if validation_test is None:
            raise ValidationError('This field is Required')
            return self.cleaned_data['validation_test']
        listing_question = self.cleaned_data.get('listing_question', None)
        if listing_question:
            answer_class = Answer.get_class(listing_question.answer_type)
            method = getattr(answer_class, validation_test, None)
            if method is None:
                raise ValidationError(
                    'unsupported validator defined on listing question')

        if validation_test == 'between':
            if self.cleaned_data.get(
                    'min', False) is False or self.cleaned_data.get(
                    'max', False) is False:
                raise ValidationError(
                    'min and max values required for between condition')
                return self.cleaned_data

        if validation_test == 'equals':
            if not self.cleaned_data['value']:
                raise ValidationError('Value Required')

        elif self.cleaned_data.get('value', False) is False:
            raise ValidationError('Value is required for %s' % validation_test)
        if listing_question and listing_question.answer_type == MultiChoiceAnswer.choice_name():
            if self.cleaned_data.get('options', False) is False:
                raise ValidationError(
                    'No option selected for %s' %
                    listing_question.identifier)
            self.cleaned_data['value'] = self.cleaned_data['options']
        return self.cleaned_data
Example #13
0
 def test_create_randomization_criteria_with_bad_validation_test(self):
     m_question = self.qset.questions.filter(
         answer_type=MultiChoiceAnswer.choice_name()).first()
     criteria = RandomizationCriterion.objects.create(
         listing_question=m_question,
         validation_test='less_than',
         survey=self.survey)
     self.assertRaises(ValueError, criteria.passes_test, 'Y')
 def test_logic_form_does_not_have_options_for_non_multi_type_questions(self):
     answer_types = Answer.answer_types()
     for answer_type in answer_types:
         if answer_type not in [MultiSelectAnswer.choice_name(), MultiChoiceAnswer.choice_name()]:                
             q = Question.objects.create(identifier=answer_type, text="text", answer_type=answer_type,
                                             qset_id=self.qset.id, response_validation_id=1)
             l = LogicForm(q)
             self.assertFalse(l.fields.get('option'))
Example #15
0
 def __init__(self, *args, **kwargs):
     super(AnswerForm, self).__init__(*args, **kwargs)
     # self.fields['uid'] = forms.CharField(initial=access.user_identifier, widget=forms.HiddenInput)
     if question.answer_type == DateAnswer.choice_name():
         self.fields['value'] = forms.DateField(
             label='Answer',
             input_formats=[
                 settings.DATE_FORMAT,
             ],
             widget=forms.DateInput(attrs={
                 'placeholder': 'Answer',
                 'class': 'datepicker'
             },
                                    format=settings.DATE_FORMAT))
     if question.answer_type == GeopointAnswer.choice_name():
         model_field = get_form_field_no_validation(forms.CharField)
         self.fields['value'] = model_field(
             label='Answer',
             widget=forms.TextInput(
                 attrs={
                     'placeholder':
                     'Lat[space4]Long[space4'
                     'Altitude[space4]Precision'
                 }))
     if question.answer_type == MultiChoiceAnswer.choice_name():
         self.fields['value'] = forms.ChoiceField(
             choices=[(opt.order, opt.text)
                      for opt in question.options.all()],
             widget=forms.RadioSelect)
         self.fields['value'].empty_label = None
     if access.choice_name() == USSDAccess.choice_name():
         self.fields['value'].widget = forms.NumberInput()
     if question.answer_type == MultiSelectAnswer.choice_name():
         self.fields['value'] = forms.ModelMultipleChoiceField(
             queryset=question.options.all(),
             widget=forms.CheckboxSelectMultiple)
     accept_types = {
         AudioAnswer.choice_name(): 'audio/*',
         VideoAnswer.choice_name(): 'video/*',
         ImageAnswer.choice_name(): 'image/*'
     }
     if question.answer_type in [
             AudioAnswer.choice_name(),
             VideoAnswer.choice_name(),
             ImageAnswer.choice_name()
     ]:
         self.fields['value'].widget.attrs = {
             'accept':
             accept_types.get(question.answer_type,
                              '|'.join(accept_types.values()))
         }
     if access.choice_name() == USSDAccess.choice_name():
         self.fields['value'].label = ''
     else:
         self.fields['value'].label = 'Answer'
Example #16
0
    def __init__(self, question, initial=None, *args, **kwargs):
        super(LogicForm, self).__init__(initial=initial, *args, **kwargs)
        data = kwargs.get('data', None)
        batch = question.qset
        self.question = question
        self.batch = batch
        self.fields['condition'] = forms.ChoiceField(
            label='Eligibility criteria',
            choices=[],
            widget=forms.Select,
            required=False)
        self.fields['attribute'] = forms.ChoiceField(
            label='Attribute', choices=[
                ('value', 'Value'), ], widget=forms.Select, required=False)
        self.fields['condition'].choices = [
            (validator.__name__,
             validator.__name__.upper()) for validator in Answer.get_class(
                question.answer_type).validators()]
        if question.answer_type in [
                MultiChoiceAnswer.choice_name(),
                MultiSelectAnswer.choice_name()]:
            self.fields['option'] = forms.ChoiceField(
                label='', choices=[], widget=forms.Select, required=True)
            self.fields['option'].choices = [
                (option.text, option.text) for option in question.options.all()]
        else:
            self.fields['value'] = forms.CharField(label='', required=False)
            self.fields['min_value'] = forms.CharField(
                label='', required=False, widget=forms.TextInput(
                    attrs={
                        'placeholder': 'Min Value'}))
            self.fields['max_value'] = forms.CharField(
                label='', required=False, widget=forms.TextInput(
                    attrs={
                        'placeholder': 'Max Value'}))
            if question.answer_type == DateAnswer.choice_name():
                self.fields['value'].widget.attrs['class'] = 'datepicker'
                self.fields['min_value'].widget.attrs['class'] = 'datepicker'
                self.fields['max_value'].widget.attrs['class'] = 'datepicker'
            # validate_with_question = forms.ChoiceField(label='', choices=[], widget=forms.Select, required=False)
        self.fields['action'] = forms.ChoiceField(
            label='Then', choices=[], widget=forms.Select, required=True)
        flows = self.question.flows.all()
        [f.next_question.pk for f in flows if f.next_question]
        next_q_choices = [(q.pk, q.text) for q in batch.questions_inline(
        ) if q.pk is not self.question.pk]
        # and q.pk not in existing_nexts]
        next_q_choices.extend([(q.pk, q.text)
                               for q in batch.zombie_questions()])
        self.fields['next_question'] = forms.ChoiceField(
            label='', choices=next_q_choices, widget=forms.Select, required=False)
        #self.fields['next_question'].widget.attrs['class'] = 'chzn-select'
        self.fields['action'].choices = self.ACTIONS.items()

        data.get('action', None) if data else None
Example #17
0
    def clean_value(self):

        if self.question.answer_type not in [
                MultiSelectAnswer.choice_name(),
                MultiChoiceAnswer.choice_name()] and self.cleaned_data['condition'] != 'between' and len(
                self.cleaned_data['value'].strip()) == 0:
            raise ValidationError("Field is required.")
        value = self.cleaned_data.get('value', '')
        if value:
            Answer.get_class(
                self.question.answer_type).validate_test_value(value)
        return self.cleaned_data.get('value', '')
Example #18
0
 def _prep_answers(self):
     self._create_test_non_group_questions(self.qset)
     answers = []
     n_quest = Question.objects.get(
         answer_type=NumericalAnswer.choice_name())
     t_quest = Question.objects.get(answer_type=TextAnswer.choice_name())
     m_quest = Question.objects.get(
         answer_type=MultiChoiceAnswer.choice_name())
     # first is numeric, then text, then multichioice
     answers = [{
         n_quest.id: 1,
         t_quest.id: 'Hey Man',
         m_quest.id: 'Y'
     }, {
         n_quest.id: 5,
         t_quest.id: 'Our Hey Boy',
         m_quest.id: 'Y'
     }, {
         n_quest.id: 27,
         t_quest.id: 'Hey Girl!',
         m_quest.id: 'N'
     }, {
         n_quest.id: 12,
         t_quest.id: 'Hey Raster!',
         m_quest.id: 'N'
     }, {
         n_quest.id: 19,
         t_quest.id: 'This bad boy'
     }]
     question_map = {
         n_quest.id: n_quest,
         t_quest.id: t_quest,
         m_quest.id: m_quest
     }
     interview = self.interview
     interviews = Interview.save_answers(self.qset, self.survey, self.ea,
                                         self.access_channel, question_map,
                                         answers)
     # confirm that 11 answers has been created
     self.assertEquals(NumericalAnswer.objects.count(), 5)
     self.assertEquals(TextAnswer.objects.count(), 5)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 4)
     self.assertEquals(TextAnswer.objects.first().to_text().lower(),
                       'Hey Man'.lower())
     self.assertEquals(MultiChoiceAnswer.objects.first().as_text.lower(),
                       'Y'.lower())
     multichoice = MultiChoiceAnswer.objects.first()
     self.assertEquals(
         multichoice.as_value,
         str(
             QuestionOption.objects.get(
                 text='Y', question=multichoice.question).order))
     return Interview.objects.filter(id__in=[i.id for i in interviews])
 def test_logic_form_has_options_for_multi_type_questions(self):
     for answer_type in [
             MultiSelectAnswer.choice_name(),
             MultiChoiceAnswer.choice_name()
     ]:
         q = Question.objects.create(identifier=answer_type,
                                     text="text",
                                     answer_type=answer_type,
                                     qset_id=self.qset.id,
                                     response_validation_id=1)
         l = LogicForm(q)
         self.assertTrue(l.fields.get('option'))
Example #20
0
 def test_bulk_answer_questions(self):
     self._create_ussd_non_group_questions(self.qset)
     answers = []
     n_quest = Question.objects.get(
         answer_type=NumericalAnswer.choice_name())
     t_quest = Question.objects.get(answer_type=TextAnswer.choice_name())
     m_quest = Question.objects.get(
         answer_type=MultiChoiceAnswer.choice_name())
     # first is numeric, then text, then multichioice
     answers = [{
         n_quest.id: 1,
         t_quest.id: 'Hey Man',
         m_quest.id: 'Y'
     }, {
         n_quest.id: 5,
         t_quest.id: 'Hey Boy',
         m_quest.id: 'Y'
     }, {
         n_quest.id: 15,
         t_quest.id: 'Hey Girl!',
         m_quest.id: 'N'
     }, {
         n_quest.id: 15,
         t_quest.id: 'Hey Part!'
     }]
     question_map = {
         n_quest.id: n_quest,
         t_quest.id: t_quest,
         m_quest.id: m_quest
     }
     interview = self.interview
     Interview.save_answers(self.qset, self.survey, self.ea,
                            self.access_channel, question_map, answers)
     # confirm that 11 answers has been created
     self.assertEquals(NumericalAnswer.objects.count(), 4)
     self.assertEquals(TextAnswer.objects.count(), 4)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 3)
     self.assertEquals(TextAnswer.objects.first().to_text().lower(),
                       'Hey Man'.lower())
     self.assertEquals(MultiChoiceAnswer.objects.first().as_text.lower(),
                       'Y'.lower())
     self.assertEquals(MultiChoiceAnswer.objects.first().as_value,
                       str(QuestionOption.objects.get(text='Y').order))
     # now test wipe data
     request = RequestFactory().get('.')
     request.user = self._load_other_client()
     activate_super_powers(request)
     url = reverse('wipe_survey_data', args=(self.survey.id, ))
     answer_count = Answer.objects.count()
     self.assertTrue(answer_count > 0)
     response = self.client.get(url)
     self.assertEquals(Answer.objects.count(), 0)
Example #21
0
    def clean_value(self):

        if self.question.answer_type not in  [MultiSelectAnswer.choice_name(), MultiChoiceAnswer.choice_name()] \
                            and self.cleaned_data['condition'] != 'between' and len(self.cleaned_data['value'].strip()) == 0:
            raise ValidationError("Field is required.")
        value = self.cleaned_data.get('value', '')
        if value:
            #now check if value is valid answer type
            try:
                Answer.get_class(self.question.answer_type)(self.question, value)
            except:
                raise ValidationError("Invalid value.")
        return self.cleaned_data.get('value', '')
Example #22
0
    def clean_value(self):

        if self.question.answer_type not in [
                MultiSelectAnswer.choice_name(),
                MultiChoiceAnswer.choice_name()
        ] and self.cleaned_data['condition'] != 'between' and len(
                self.cleaned_data['value'].strip()) == 0:
            raise ValidationError("Field is required.")
        value = self.cleaned_data.get('value', '')
        if value:
            Answer.get_class(
                self.question.answer_type).validate_test_value(value)
        return self.cleaned_data.get('value', '')
Example #23
0
    def clean_value(self):

        if self.question.answer_type not in  [MultiSelectAnswer.choice_name(), MultiChoiceAnswer.choice_name()] \
                            and self.cleaned_data['condition'] != 'between' and len(self.cleaned_data['value'].strip()) == 0:
            raise ValidationError("Field is required.")
        value = self.cleaned_data.get('value', '')
        if value:
            #now check if value is valid answer type
            try:
                Answer.get_class(self.question.answer_type)(self.question,
                                                            value)
            except:
                raise ValidationError("Invalid value.")
        return self.cleaned_data.get('value', '')
 def _bulk_answer_questions(self):
     answers = []
     n_quest = Question.objects.filter(
         answer_type=NumericalAnswer.choice_name()).last()
     t_quest = Question.objects.filter(
         answer_type=TextAnswer.choice_name()).last()
     m_quest = Question.objects.filter(
         answer_type=MultiChoiceAnswer.choice_name()).last()
     # first is numeric, then text, then multichioice
     answers = [
         {
             n_quest.id: 5,
             t_quest.id: 'Hey Boy',
             m_quest.id: 'Y'
         },
         {
             n_quest.id: 15,
             t_quest.id: 'Hey Girl!',
             m_quest.id: 'N'
         },
         {
             n_quest.id: 15,
             t_quest.id: 'Hey Part!'
         },
         {
             n_quest.id: 1,
             t_quest.id: 'Privet malishka, kach di la',
             m_quest.id: 'Y'
         },
     ]
     question_map = {
         n_quest.id: n_quest,
         t_quest.id: t_quest,
         m_quest.id: m_quest
     }
     Interview.save_answers(self.qset, self.survey, self.ea,
                            self.access_channel, question_map, answers)
     # confirm that 11 answers has been created
     self.assertEquals(NumericalAnswer.objects.count(), 4)
     self.assertEquals(TextAnswer.objects.count(), 4)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 3)
     self.assertEquals(TextAnswer.objects.last().to_text().lower(),
                       'Privet malishka, kach di la'.lower())
     m_answer = MultiChoiceAnswer.objects.last()
     self.assertEquals(m_answer.as_text.lower(), 'Y'.lower())
     self.assertEquals(
         m_answer.as_value,
         str(
             QuestionOption.objects.get(text='Y',
                                        question__id=m_quest.id).order))
 def get_summarised_answers(self):
     data = []
     q_opts = {}
     if self.specific_households is None:
         all_households = Household.objects.filter(
             listing__survey_houselistings__survey=self.survey)
     else:
         all_households = Household.objects.filter(
             pk__in=self.specific_households,
             listing__survey_houselistings__survey=self.survey)
     locations = list(
         set(all_households.values_list('listing__ea__locations',
                                        flat=True)))
     for location_id in locations:
         households_in_location = all_households.filter(
             listing__ea__locations=location_id)
         household_location = Location.objects.get(id=location_id)
         location_ancestors = household_location.get_ancestors(include_self=True).\
             exclude(parent__isnull='country').values_list('name', flat=True)
         answers = []
         for household in households_in_location:
             for member in household.members.all():
                 try:
                     answers = list(location_ancestors)
                     member_gender = 'Male' if member.gender == HouseholdMember.MALE else 'Female'
                     answers.extend([
                         household.listing.ea.name, household.house_number,
                         '%s-%s' % (member.surname, member.first_name),
                         str(member.age),
                         member.date_of_birth.strftime(
                             settings.DATE_FORMAT), member_gender
                     ])
                     for question in self.questions:
                         reply = member.reply(question)
                         if question.answer_type in [MultiChoiceAnswer.choice_name(),
                                                     MultiSelectAnswer.choice_name()]\
                                 and self.multi_display == self.AS_LABEL:
                             label = q_opts.get((question.pk, reply), None)
                             if label is None:
                                 try:
                                     label = question.options.get(
                                         text__iexact=reply).order
                                 except QuestionOption.DoesNotExist:
                                     label = reply
                                 q_opts[(question.pk, reply)] = label
                             reply = str(label)
                         answers.append(reply.encode('utf8'))
                     data.append(answers)
                 except Exception, ex:
                     print 'Error ', str(ex)
Example #26
0
 def test_update_multichoice_answer(self):
     qset = self.qset
     self._create_test_non_group_questions(qset)
     multichoice_question = Question.objects.filter(answer_type=MultiChoiceAnswer.choice_name()).first()
     options = multichoice_question.options.all()
     MultiChoiceAnswer.create(self.interview, multichoice_question, options.first().text)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 1)
     multichoice_answer = MultiChoiceAnswer.objects.first()
     self.assertEquals(multichoice_answer.as_text.lower(), options.first().text.lower())
     self.assertEquals(int(multichoice_answer.as_value), options.first().order)
     # confirm using value instead yields ame result
     MultiChoiceAnswer.create(self.interview, multichoice_question, options.first().order)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 2)
     multichoice_answer = MultiChoiceAnswer.objects.last()
     self.assertEquals(multichoice_answer.as_text.lower(), options.first().text.lower())
     self.assertEquals(int(multichoice_answer.as_value), options.first().order)
     # confirm update now
     multichoice_answer.update(options.last().text)
     multichoice_answer.refresh_from_db()
     self.assertEquals(int(multichoice_answer.as_value), options.last().order)
     # update back to original option
     multichoice_answer.update(options.first().order)
     multichoice_answer.refresh_from_db()
     self.assertEquals(int(multichoice_answer.as_value), options.first().order)
 def test_logic_form_does_not_have_options_for_non_multi_type_questions(
         self):
     answer_types = Answer.answer_types()
     for answer_type in answer_types:
         if answer_type not in [
                 MultiSelectAnswer.choice_name(),
                 MultiChoiceAnswer.choice_name()
         ]:
             q = Question.objects.create(identifier=answer_type,
                                         text="text",
                                         answer_type=answer_type,
                                         qset_id=self.qset.id,
                                         response_validation_id=1)
             l = LogicForm(q)
             self.assertFalse(l.fields.get('option'))
Example #28
0
 def __init__(self, *args, **kwargs):
     super(AnswerForm, self).__init__(*args, **kwargs)
     # self.fields['uid'] = forms.CharField(initial=access.user_identifier, widget=forms.HiddenInput)
     if question.answer_type == DateAnswer.choice_name():
         self.fields['value'] = forms.DateField(
             label='Answer',
             input_formats=[
                 settings.DATE_FORMAT,
             ],
             widget=forms.DateInput(
                 attrs={
                     'placeholder': 'Answer',
                     'class': 'datepicker'},
                 format=settings.DATE_FORMAT))
     if question.answer_type == GeopointAnswer.choice_name():
         model_field = get_form_field_no_validation(forms.CharField)
         self.fields['value'] = model_field(label='Answer', widget=forms.TextInput(
             attrs={'placeholder': 'Lat[space4]Long[space4' 'Altitude[space4]Precision'}))
     if question.answer_type == MultiChoiceAnswer.choice_name():
         self.fields['value'] = forms.ChoiceField(choices=[(opt.order, opt.text) for opt
                                                           in question.options.all()], widget=forms.RadioSelect)
         self.fields['value'].empty_label = None
     if access.choice_name() == USSDAccess.choice_name():
         self.fields['value'].widget = forms.NumberInput()
     if question.answer_type == MultiSelectAnswer.choice_name():
         self.fields['value'] = forms.ModelMultipleChoiceField(
             queryset=question.options.all(), widget=forms.CheckboxSelectMultiple)
     accept_types = {AudioAnswer.choice_name(): 'audio/*',
                     VideoAnswer.choice_name(): 'video/*',
                     ImageAnswer.choice_name(): 'image/*'
                     }
     if question.answer_type in [
             AudioAnswer.choice_name(),
             VideoAnswer.choice_name(),
             ImageAnswer.choice_name()]:
         self.fields['value'].widget.attrs = {
             'accept': accept_types.get(
                 question.answer_type, '|'.join(
                     accept_types.values()))}
     if access.choice_name() == USSDAccess.choice_name():
         self.fields['value'].label = ''
     else:
         self.fields['value'].label = 'Answer'
Example #29
0
 def test_bulk_answer_questions(self):
     self._create_ussd_non_group_questions(self.qset)
     answers = []
     n_quest = Question.objects.get(
         answer_type=NumericalAnswer.choice_name())
     t_quest = Question.objects.get(answer_type=TextAnswer.choice_name())
     m_quest = Question.objects.get(
         answer_type=MultiChoiceAnswer.choice_name())
     # first is numeric, then text, then multichioice
     answers = [{
         n_quest.id: 1,
         t_quest.id: 'Hey Man',
         m_quest.id: 'Y'
     }, {
         n_quest.id: 5,
         t_quest.id: 'Hey Boy',
         m_quest.id: 'Y'
     }, {
         n_quest.id: 15,
         t_quest.id: 'Hey Girl!',
         m_quest.id: 'N'
     }, {
         n_quest.id: 15,
         t_quest.id: 'Hey Part!'
     }]
     question_map = {
         n_quest.id: n_quest,
         t_quest.id: t_quest,
         m_quest.id: m_quest
     }
     interview = self.interview
     Interview.save_answers(self.qset, self.survey, self.ea,
                            self.access_channel, question_map, answers)
     # confirm that 11 answers has been created
     self.assertEquals(NumericalAnswer.objects.count(), 4)
     self.assertEquals(TextAnswer.objects.count(), 4)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 3)
     self.assertEquals(TextAnswer.objects.first().to_text().lower(),
                       'Hey Man'.lower())
     self.assertEquals(MultiChoiceAnswer.objects.first().as_text.lower(),
                       'Y'.lower())
     self.assertEquals(MultiChoiceAnswer.objects.first().as_value,
                       str(QuestionOption.objects.get(text='Y').order))
Example #30
0
 def _create_ussd_non_group_questions(self, qset=None):
     if qset is None:
         qset = self.qset
     # numeric answer
     data = {
         'answer_type': NumericalAnswer.choice_name(),
         'text': 'num text',
         'identifier': 'num1_identifier_%s' % random.randint(1, 100),
         'qset': qset.id
     }
     question = self._save_question(qset, data)
     qset.refresh_from_db(
     )  # qset is updated by question (start_question attribute is updated)
     # since it's the first question saved it must reflect as first question of the question set
     self.assertEquals(qset.start_question.id, question.id)
     # text answer
     data = {
         'answer_type': TextAnswer.choice_name(),
         'text': 'texts text',
         'identifier': 'text1_identifier_%s' % random.randint(1, 100),
         'qset': qset.id
     }
     self._save_question(qset, data)
     # Multichoice questions
     data = {
         'answer_type': MultiChoiceAnswer.choice_name(),
         'text': 'multichoice answer text',
         'identifier':
         'multi1_choice_identifier_%s' % random.randint(1, 100),
         'qset': qset.id,
         'options': ['Y', 'N']
     }
     self._save_question(qset, data)
     # Auto questions
     data = {
         'answer_type': AutoResponse.choice_name(),
         'text': 'auto answer text',
         'identifier': 'auto1_identifier_%s' % random.randint(1, 100),
         'qset': qset.id,
     }
     self._save_question(qset, data)
     self.qset.refresh_from_db()
Example #31
0
 def _create_ussd_non_group_questions(self, qset=None):
     if qset is None:
         qset = self.qset
     # numeric answer
     data = {
         'answer_type': NumericalAnswer.choice_name(),
         'text': 'num text',
         'identifier': 'num1_identifier_%s' % random.randint(1, 100),
         'qset': qset.id
     }
     question = self._save_question(qset, data)
     qset.refresh_from_db()  # qset is updated by question (start_question attribute is updated)
     # since it's the first question saved it must reflect as first question of the question set
     self.assertEquals(qset.start_question.id, question.id)
     # text answer
     data = {
         'answer_type': TextAnswer.choice_name(),
         'text': 'texts text',
         'identifier': 'text1_identifier_%s' % random.randint(1, 100),
         'qset': qset.id
     }
     self._save_question(qset, data)
     # Multichoice questions
     data = {
         'answer_type': MultiChoiceAnswer.choice_name(),
         'text': 'multichoice answer text',
         'identifier': 'multi1_choice_identifier_%s' % random.randint(1, 100),
         'qset': qset.id,
         'options': ['Y', 'N']
     }
     self._save_question(qset, data)
     # Auto questions
     data = {
         'answer_type': AutoResponse.choice_name(),
         'text': 'auto answer text',
         'identifier': 'auto1_identifier_%s' % random.randint(1, 100),
         'qset': qset.id,
     }
     self._save_question(qset, data)
     self.qset.refresh_from_db()
Example #32
0
 def save(self, *args, **kwargs):
     next_question = None
     desc = self._make_desc()
     if self.cleaned_data['action'] in [
             self.ASK_SUBQUESTION, self.SKIP_TO, self.BACK_TO
     ]:
         next_question = Question.get(pk=self.cleaned_data['next_question'])
     if self.cleaned_data['action'] == self.REANSWER:
         next_question = self.question
     validation = ResponseValidation.objects.create(
         validation_test=self.cleaned_data['condition'])
     flow = QuestionFlow.objects.create(question=self.question,
                                        validation=validation,
                                        next_question=next_question,
                                        desc=desc)
     if self.cleaned_data['action'] == self.ASK_SUBQUESTION:
         # connect back to next inline question of the main
         QuestionFlow.objects.create(question=next_question,
                                     desc=desc,
                                     next_question=self.batch.next_inline(
                                         self.question))
     if self.cleaned_data['condition'] == 'between':
         TextArgument.objects.create(validation=validation,
                                     position=0,
                                     param=self.cleaned_data['min_value'])
         TextArgument.objects.create(validation=validation,
                                     position=1,
                                     param=self.cleaned_data['max_value'])
     else:
         value = self.cleaned_data.get('value', '')
         if self.question.answer_type in [
                 MultiChoiceAnswer.choice_name(),
                 MultiSelectAnswer.choice_name()
         ]:
             value = self.cleaned_data['option']
         TextArgument.objects.create(validation=validation,
                                     position=0,
                                     param=value)
     # clean up now, remove all zombie questions
     self.question.qset.zombie_questions().delete()
 def get_summarised_answers(self):
     data = []
     q_opts = {}
     if self.specific_households is None:
         all_households = Household.objects.filter(listing__survey_houselistings__survey=self.survey)
     else:
         all_households = Household.objects.filter(pk__in=self.specific_households,
                                                   listing__survey_houselistings__survey=self.survey)
     locations = list(set(all_households.values_list('listing__ea__locations', flat=True)))
     for location_id in locations:
         households_in_location = all_households.filter(listing__ea__locations=location_id)
         household_location = Location.objects.get(id=location_id)
         location_ancestors = household_location.get_ancestors(include_self=True).\
             exclude(parent__isnull='country').values_list('name', flat=True)
         answers = []
         for household in households_in_location:
             for member in household.members.all():
                 try:
                     answers = list(location_ancestors)
                     member_gender = 'Male' if member.gender == HouseholdMember.MALE else 'Female'
                     answers.extend([household.listing.ea.name, household.house_number, '%s-%s' % (member.surname, member.first_name), str(member.age),
                                          member.date_of_birth.strftime(settings.DATE_FORMAT),
                                          member_gender])
                     for question in self.questions:
                         reply = member.reply(question)
                         if question.answer_type in [MultiChoiceAnswer.choice_name(), MultiSelectAnswer.choice_name()]\
                                 and self.multi_display == self.AS_LABEL:
                             label = q_opts.get((question.pk, reply), None)
                             if label is None:
                                 try:
                                     label = question.options.get(text__iexact=reply).order
                                 except QuestionOption.DoesNotExist:
                                     label = reply
                                 q_opts[(question.pk, reply)] = label
                             reply = str(label)
                         answers.append(reply.encode('utf8'))
                     data.append(answers)
                 except Exception, ex:
                     print 'Error ', str(ex)
 def test_bulk_answer_questions(self):
     self._create_ussd_non_group_questions(self.qset)
     answers = []
     n_quest = Question.objects.get(answer_type=NumericalAnswer.choice_name())
     t_quest = Question.objects.get(answer_type=TextAnswer.choice_name())
     m_quest = Question.objects.get(answer_type=MultiChoiceAnswer.choice_name())
     # first is numeric, then text, then multichioice
     answers = [{n_quest.id: 1, t_quest.id: 'Hey Man', m_quest.id: 'Y'},
                {n_quest.id: 5, t_quest.id: 'Hey Boy', m_quest.id: 'Y'},
                {n_quest.id: 15, t_quest.id: 'Hey Girl!', m_quest.id: 'N'},
                {n_quest.id: 15, t_quest.id: 'Hey Part!'}
                ]
     question_map = {n_quest.id: n_quest, t_quest.id: t_quest, m_quest.id: m_quest}
     interview = self.interview
     Interview.save_answers(self.qset, self.survey, self.ea,
                            self.access_channel, question_map, answers)
     # confirm that 11 answers has been created
     self.assertEquals(NumericalAnswer.objects.count(), 4)
     self.assertEquals(TextAnswer.objects.count(), 4)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 3)
     self.assertEquals(TextAnswer.objects.first().to_text().lower(), 'Hey Man'.lower())
     self.assertEquals(MultiChoiceAnswer.objects.first().as_text.lower(), 'Y'.lower())
     self.assertEquals(MultiChoiceAnswer.objects.first().as_value, str(QuestionOption.objects.get(text='Y').order))
 def _bulk_answer_questions(self):
     answers = []
     n_quest = Question.objects.filter(answer_type=NumericalAnswer.choice_name()).first()
     t_quest = Question.objects.filter(answer_type=TextAnswer.choice_name()).first()
     m_quest = Question.objects.filter(answer_type=MultiChoiceAnswer.choice_name()).first()
     # first is numeric, then text, then multichioice
     answers = [{n_quest.id: 1, t_quest.id: 'Privet malishka, kach di la',  m_quest.id: 'Y'},
                {n_quest.id: 5, t_quest.id: 'Hey Boy', m_quest.id: 'Y'},
                {n_quest.id: 15, t_quest.id: 'Hey Girl!', m_quest.id: 'N'},
                {n_quest.id: 15, t_quest.id: 'Hey Part!'}
                ]
     question_map = {n_quest.id: n_quest, t_quest.id: t_quest, m_quest.id: m_quest}
     interview = self.interview
     Interview.save_answers(self.qset, self.survey, self.ea,
                            self.access_channel, question_map, answers)
     # confirm that 11 answers has been created
     self.assertEquals(NumericalAnswer.objects.count(), 4)
     self.assertEquals(TextAnswer.objects.count(), 4)
     self.assertEquals(MultiChoiceAnswer.objects.count(), 3)
     self.assertEquals(TextAnswer.objects.first().to_text().lower(), 'Privet malishka, kach di la'.lower())
     m_answer = MultiChoiceAnswer.objects.first()
     self.assertEquals(m_answer.as_text.lower(), 'Y'.lower())
     self.assertEquals(m_answer.as_value,
                       str(QuestionOption.objects.get(text='Y', question__id=m_quest.id).order))
 def test_answer_validators(self):
     validators = [  # supported validators
         'starts_with',
         'ends_with',
         'equals',
         'between',
         'less_than',
         'greater_than',
         'contains',
     ]
     for func in Answer.validators():
         self.assertIn(func.__name__, validators)
     # test Numeric Answer Validators
     validators = [  # supported validators
         'equals',
         'between',
         'less_than',
         'greater_than',
     ]
     for func in NumericalAnswer.validators():
         self.assertIn(func.__name__, validators)
     # test Text Answer Validators
     validators = [  # supported validators
         'starts_with',
         'ends_with',
         'equals',
         'contains',
     ]
     for func in TextAnswer.validators():
         self.assertIn(func.__name__, validators)
     # Multichoice
     validators = [  # supported validators
         'equals',
     ]
     for func in MultiChoiceAnswer.validators():
         self.assertIn(func.__name__, validators)
     # test Multiselect Answer Validators
     validators = [  # supported validators
         'equals',
         'contains',
     ]
     for func in MultiSelectAnswer.validators():
         self.assertIn(func.__name__, validators)
     # test Date Answer Validators
     validators = [  # supported validators
         'equals',
         'between',
         'less_than',
         'greater_than',
     ]
     for func in DateAnswer.validators():
         self.assertIn(func.__name__, validators)
     # GeoPoint Answer
     validators = [  # supported validators
         'equals',
     ]
     for func in GeopointAnswer.validators():
         self.assertIn(func.__name__, validators)
     # file answers should return no validators
     for answer_class in [VideoAnswer, AudioAnswer, ImageAnswer]:
         self.assertEquals(len(answer_class.validators()), 0)
 def test_end_interview_selection_in_form_question_creates_flow_to_with_no_next_question(
         self):
     '''
     :return:
     '''
     yes = 'yes'
     no = 'no'
     q1 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test1',
                                  text='test1',
                                  answer_type=DateAnswer.choice_name())
     q2 = Question.objects.create(
         qset_id=self.qset.id,
         response_validation_id=1,
         identifier='test2',
         text='test2',
         answer_type=MultiChoiceAnswer.choice_name())
     q_o1 = QuestionOption.objects.create(question_id=q2.id,
                                          text=yes,
                                          order=1)
     QuestionOption.objects.create(question_id=q2.id, text=no, order=2)
     q3 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test3',
                                  text='test3',
                                  answer_type=DateAnswer.choice_name())
     q4 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test4',
                                  text='test4',
                                  answer_type=DateAnswer.choice_name())
     q5 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test5',
                                  text='test5',
                                  answer_type=DateAnswer.choice_name())
     self.batch.start_question = q1
     QuestionFlow.objects.create(question_id=q1.id, next_question_id=q2.id)
     QuestionFlow.objects.create(question_id=q2.id, next_question_id=q3.id)
     QuestionFlow.objects.create(question_id=q3.id, next_question_id=q4.id)
     QuestionFlow.objects.create(question_id=q4.id, next_question_id=q5.id)
     test_condition = MultiChoiceAnswer.validators()[0].__name__
     form_data = {
         'action': LogicForm.END_INTERVIEW,
         'condition': test_condition,
         'option': q_o1.order
     }
     l = LogicForm(q2, data=form_data)
     if l.is_valid():
         l.save()
         # now check if equivalent Question flow and test arguments were
         # created
         try:
             qf = QuestionFlow.objects.get(question_id=q2.id,
                                           next_question_id__isnull=True)
             TextArgument.objects.get(flow=qf, position=0, param=q_o1.order)
             QuestionFlow.objects.get(question_id=q1.id,
                                      next_question_id=q2.id)
             QuestionFlow.objects.get(question_id=q2.id,
                                      next_question_id=q3.id)
             self.assertTrue(True)
             return
         except QuestionFlow.DoesNotExist:
             self.assertTrue(False, 'flow not existing')
             pass
         except TextArgument:
             self.assertTrue(False, 'text agrunments not saved')
             pass
     else:
         self.assertFalse(False, 'Invalid form')
    def get_interview_answers(self):
        report = []
        member_reports = OrderedDict()
        val_list_args = [
            'interview__ea__locations__name',
            'interview__ea__name',
            'interview__householdmember__household__house_number',
            'interview__householdmember__surname',
            'interview__householdmember__first_name',
            'interview__householdmember__date_of_birth',
            'interview__householdmember__gender',
        ]
        parent_loc = 'interview__ea__locations'
        for i in range(LocationType.objects.count() - 2):
            parent_loc = '%s__parent' % parent_loc
            val_list_args.insert(0, '%s__name' % parent_loc)
        filter_args = {}
        if self.locations:
            filter_args['interview__ea__locations__in'] = self.locations
        if self.specific_households:
            filter_args[
                'interview__householdmember__household__in'] = self.specific_households
        for answer_type in Answer.answer_types():
            query_args = list(val_list_args)
            value = 'value'
            if answer_type in [
                    MultiChoiceAnswer.choice_name(),
                    MultiSelectAnswer.choice_name()
            ]:
                value = 'value__text'
                if self.multi_display == self.AS_LABEL:
                    value = 'value__order'
            query_args.append(value)
            answer_class = Answer.get_class(answer_type)
            # print 'using query_args ', query_args
            answer_data = answer_class.objects.filter(interview__batch=self.batch, **filter_args).\
                values_list('interview__householdmember__pk', 'question__pk', *query_args).\
                        order_by('interview__ea__locations', 'interview__ea',
                                 'interview__householdmember__household', 'interview__householdmember__pk',
                                 'pk', 'loop_id')
            # .distinct(
            #                         'interview__ea__locations',
            #                         'interview__ea',
            #                         'interview__householdmember__household',
            #                         #'interview__householdmember__pk',
            #                         #'question__pk'
            #                        )

            answer_data = list(answer_data)
            # print 'answer data ', len(answer_data)
            #now grab member reports
            for data in answer_data:
                hm_pk, question_pk = data[:2]
                report_data = list(data[2:])
                hm_data = member_reports.get(hm_pk, None)
                if hm_data is None:
                    report_data.insert(
                        -3,
                        str(
                            dateutils.relativedelta(datetime.utcnow().date(),
                                                    report_data[-3]).years))
                    report_data[-3] = report_data[-3].strftime(
                        settings.DATE_FORMAT)
                    report_data[-2] = 'M' if report_data[-2] else 'F'
                    member_details = [
                        unicode(md).encode('utf8') for md in report_data[:-1]
                    ]
                    hm_data = OrderedDict([
                        ('mem_details', member_details),
                    ])
                hm_question_data = hm_data.get(question_pk, [])
                hm_question_data.append(
                    unicode(report_data[-1]).encode('utf8'))
                hm_data[question_pk] = hm_question_data
                member_reports[hm_pk] = hm_data

        for hm in member_reports.values():
            answers = hm.pop('mem_details', [])
            #for question_pk, response_data in hm.items():
            loop_starters = self.batch.loop_starters()
            loop_enders = self.batch.loop_enders()
            started = False
            dept = 0
            for question in self.questions:
                # loop_extras = []
                # boundary = question.loop_boundary()
                # if question in loop_starters:
                #     loop_extras = []
                #     loop_questions = self.batch.loop_backs_questions()[boundary]
                #     for i in range(1, settings.LOOP_QUESTION_REPORT_DEPT):
                #         for q in loop_questions:
                #             question_responses = hm.get(question.pk, [])
                #             if len(question_responses) > i:
                #                 resp = question_responses[i]
                #             else:
                #                 resp = ''
                #             loop_extras.append(resp)
                #     import pdb; pdb.set_trace()
                # if question in loop_enders:
                #     answers.extend(loop_extras)
                answers.append(' > '.join(hm.get(question.pk, [
                    '',
                ])))
            report.append(answers)
        return report
Example #39
0
    def __init__(self, initial=None, question=None, *args, **kwargs):
        super(LogicForm, self).__init__(initial=initial, *args, **kwargs)
        data = kwargs.get('data', None)
        batch = question.batch
        self.question = question
        self.batch = batch
        self.fields['condition'] = forms.ChoiceField(
            label='Eligibility criteria',
            choices=[],
            widget=forms.Select,
            required=False)
        self.fields['attribute'] = forms.ChoiceField(label='Attribute',
                                                     choices=[
                                                         ('value', 'Value'),
                                                     ],
                                                     widget=forms.Select,
                                                     required=False)
        self.fields['condition'].choices = [(validator.__name__, validator.__name__.upper()) \
                                           for validator in Answer.get_class(question.answer_type).validators()]
        if question.answer_type in [
                MultiChoiceAnswer.choice_name(),
                MultiSelectAnswer.choice_name()
        ]:
            self.fields['option'] = forms.ChoiceField(label='',
                                                      choices=[],
                                                      widget=forms.Select,
                                                      required=True)
            self.fields['option'].choices = [
                (option.order, option.text)
                for option in question.options.all()
            ]
        else:
            self.fields['value'] = forms.CharField(label='', required=False)
            self.fields['min_value'] = forms.CharField(
                label='',
                required=False,
                widget=forms.TextInput(attrs={'placeholder': 'Min Value'}))
            self.fields['max_value'] = forms.CharField(
                label='',
                required=False,
                widget=forms.TextInput(attrs={'placeholder': 'Max Value'}))
            if question.answer_type == DateAnswer.choice_name():
                self.fields['value'].widget.attrs['class'] = 'datepicker'
                self.fields['min_value'].widget.attrs['class'] = 'datepicker'
                self.fields['max_value'].widget.attrs['class'] = 'datepicker'
            # validate_with_question = forms.ChoiceField(label='', choices=[], widget=forms.Select, required=False)
        self.fields['action'] = forms.ChoiceField(label='Then',
                                                  choices=[],
                                                  widget=forms.Select,
                                                  required=True)
        flows = self.question.flows.all()
        existing_nexts = [f.next_question.pk for f in flows if f.next_question]
        next_q_choices = [(q.pk, q.text) for q in batch.questions_inline()
                          if q.pk is not self.question.pk]
        # and q.pk not in existing_nexts]
        next_q_choices.extend([(q.pk, q.text)
                               for q in batch.zombie_questions()])
        self.fields['next_question'] = forms.ChoiceField(
            label='',
            choices=next_q_choices,
            widget=forms.Select,
            required=False)
        self.fields['next_question'].widget.attrs['class'] = 'chzn-select'
        self.fields['action'].choices = self.ACTIONS.items()

        action_sent = data.get('action', None) if data else None
Example #40
0
    def handle(self, *args, **kwargs):
        self.stdout.write('Creating permissions....')
        content_type = ContentType.objects.get_for_model(User)
        Permission.objects.get_or_create(codename='can_enter_data', name='Can enter data', content_type=content_type)
        Permission.objects.get_or_create(codename='can_view_batches', name='Can view Batches', content_type=content_type)
        Permission.objects.get_or_create(codename='can_view_interviewers', name='Can view Interviewers', content_type=content_type)
        Permission.objects.get_or_create(codename='can_view_aggregates', name='Can view Aggregates', content_type=content_type)
        Permission.objects.get_or_create(codename='view_completed_survey', name='Can view Completed Surveys', content_type=content_type)
        Permission.objects.get_or_create(codename='can_view_households', name='Can view Households', content_type=content_type)
        Permission.objects.get_or_create(codename='can_view_locations', name='Can view Locations', content_type=content_type)
        Permission.objects.get_or_create(codename='can_view_users', name='Can view Users', content_type=content_type)
        Permission.objects.get_or_create(codename='can_view_household_groups', name='Can view Household Groups', content_type=content_type)

        self.stdout.write('Permissions.')
        self.stdout.write('Creating answer definition... ')
        #ussd definition
        AnswerAccessDefinition.objects.get_or_create(channel=USSDAccess.choice_name(),
                                                     answer_type=NumericalAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=USSDAccess.choice_name(),
                                                     answer_type=TextAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=USSDAccess.choice_name(),
                                                     answer_type=MultiChoiceAnswer.choice_name())

        #ODK definition
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=NumericalAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=TextAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=MultiChoiceAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=MultiSelectAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=ImageAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=GeopointAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=DateAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=AudioAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=ODKAccess.choice_name(),
                                                     answer_type=VideoAnswer.choice_name())

        #web form definition
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=NumericalAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=TextAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=MultiChoiceAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=MultiSelectAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=ImageAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=GeopointAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=DateAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=AudioAnswer.choice_name())
        AnswerAccessDefinition.objects.get_or_create(channel=WebAccess.choice_name(),
                                                     answer_type=VideoAnswer.choice_name())
        self.stdout.write('Successfully imported!')
Example #41
0
 def test_answer_validators(self):
     validators = [                  # supported validators
         'starts_with',
         'ends_with',
         'equals',
         'between',
         'less_than',
         'greater_than',
         'contains',
     ]
     for func in Answer.validators():
         self.assertIn(func.__name__, validators)
     # test Numeric Answer Validators
     validators = [                  # supported validators
         'equals',
         'between',
         'less_than',
         'greater_than',
     ]
     for func in NumericalAnswer.validators():
         self.assertIn(func.__name__, validators)
     # test Text Answer Validators
     validators = [                  # supported validators
         'starts_with',
         'ends_with',
         'equals',
         'contains',
     ]
     for func in TextAnswer.validators():
         self.assertIn(func.__name__, validators)
     # Multichoice
     validators = [                  # supported validators
         'equals',
     ]
     for func in MultiChoiceAnswer.validators():
         self.assertIn(func.__name__, validators)
     # test Multiselect Answer Validators
     validators = [                  # supported validators
         'equals',
         'contains',
     ]
     for func in MultiSelectAnswer.validators():
         self.assertIn(func.__name__, validators)
     # test Date Answer Validators
     validators = [                  # supported validators
         'equals',
         'between',
         'less_than',
         'greater_than',
     ]
     for func in DateAnswer.validators():
         self.assertIn(func.__name__, validators)
     # GeoPoint Answer
     validators = [  # supported validators
         'equals',
     ]
     for func in GeopointAnswer.validators():
         self.assertIn(func.__name__, validators)
     # file answers should return no validators
     for answer_class in [VideoAnswer, AudioAnswer, ImageAnswer]:
         self.assertEquals(len(answer_class.validators()), 0)
 def test_logic_form_has_options_for_multi_type_questions(self):
     for answer_type in [MultiSelectAnswer.choice_name(), MultiChoiceAnswer.choice_name()]:            
         q = Question.objects.create(identifier=answer_type, text="text", answer_type=answer_type,
                                             qset_id=self.qset.id, response_validation_id=1)
         l = LogicForm(q)
         self.assertTrue(l.fields.get('option'))
Example #43
0
 def test_create_listing_sample(self):
     # create two conditions
     self._test_create_sampling_criteria()
     self._test_create_sampling_criteria_with_multichoice()
     # now answers to test listing sample
     listing_question = self.qset.questions.filter(
         answer_type=MultiChoiceAnswer.choice_name()).first()
     n_quest = Question.objects.get(
         answer_type=NumericalAnswer.choice_name())
     t_quest = Question.objects.get(answer_type=TextAnswer.choice_name())
     m_quest = Question.objects.get(
         answer_type=MultiChoiceAnswer.choice_name())
     first_option = listing_question.options.first().text
     second_option = listing_question.options.last().text
     # first is numeric, then text, then multichioice
     answers = [
         {
             n_quest.id: 1,
             t_quest.id: 'Hey Man',
             m_quest.id: first_option
         },
         {
             n_quest.id: 5,
             t_quest.id: 'Hey Boy',
             m_quest.id: second_option
         },
         {
             n_quest.id: 15,
             m_quest.id: first_option
         },
         {
             n_quest.id: 18,
             t_quest.id: 'Hey Part!'
         },
         {
             n_quest.id: 12,
             t_quest.id: 'Hey Gerry!',
             m_quest.id: first_option
         },
         {
             n_quest.id: 10,
             t_quest.id: 'Hey My guy!',
             m_quest.id: second_option
         },
         {
             n_quest.id: 17,
             t_quest.id: 'Hey my Girl!',
             m_quest.id: second_option
         },
         {
             n_quest.id: 6,
             m_quest.id: first_option
         },
         {
             n_quest.id: 133,
             m_quest.id: first_option
         },
         {
             n_quest.id: 4,
             m_quest.id: first_option
         },
         {
             n_quest.id: 9,
             m_quest.id: first_option
         },
     ]
     question_map = {
         n_quest.id: n_quest,
         t_quest.id: t_quest,
         m_quest.id: m_quest
     }
     Interview.save_answers(self.qset, self.survey, self.ea,
                            self.access_channel, question_map, answers)
     survey = self.survey
     self.assertEquals(Interview.objects.count(), len(answers))
     ListingSample.get_or_create_samples(survey, self.ea)
     # This should create samples with interviews where numeric answers are btween 1 and 10
     self.assertEquals(ListingSample.objects.count(), survey.sample_size)
     for sample in ListingSample.objects.all():
         answers = sample.interview.answer.all()
         self.assertTrue(
             int(answers.get(question__id=n_quest.id).as_value) >=
             1)  # from first criteria creation
         self.assertTrue(
             int(answers.get(question__id=n_quest.id).as_value) <
             10)  # from second criteria creation
         self.assertTrue(
             answers.get(question__id=m_quest.id).as_text.upper(),
             first_option.upper())
         # since we did not define any random_sample_label for the survey
         # and since the questonset is not empty, the label should be the very first question
         self.assertEquals(sample.interview.answer.first().as_text,
                           sample.get_display_label())
     # now test the case where some questions have no response for the random label
     self.survey.random_sample_label = '{{%s}}' % t_quest.identifier
     self.survey.save()
     self.survey.refresh_from_db()
     for sample in ListingSample.samples(self.survey, self.ea):
         answers = sample.interview.answer.all()
         first_text = sample.interview.answer.first().as_text
         try:
             expected_label = '%s' % answers.get(
                 question__id=t_quest.id).as_text
         except Answer.DoesNotExist:
             expected_label = '%s' % first_text
         self.assertEquals(string.capwords(expected_label),
                           sample.get_display_label())
         self.assertEquals(get_sample_data_display(sample),
                           sample.get_display_label())
 def test_create_group(self):
     group_params = {
         'text': 'age 1',
         'answer_type': NumericalAnswer.choice_name(),
         'identifier': 'age'
     }
     # check if you can reach the show params to add one
     show_param_url = reverse('show_%s' % ParameterTemplate.resolve_tag())
     response = self.client.post(show_param_url)
     self.assertEquals(response.status_code, 200)
     self.assertEquals(ParameterTemplate.objects.count(), 0)
     create_params_url = reverse('new_%s' % ParameterTemplate.resolve_tag())
     response = self.client.post(create_params_url, data=group_params)
     self.assertEquals(response.status_code, 302)
     self.assertEquals(ParameterTemplate.objects.count(), 1)
     # check if grou
     group_params = {
         'text': 'Choose',
         'answer_type': MultiChoiceAnswer.choice_name(),
         'identifier': 'choice',
         'options': ['Yes', 'No']
     }
     # check if you can reach the show params to add one
     response = self.client.post(create_params_url, data=group_params)
     self.assertEquals(response.status_code, 302)
     self.assertEquals(ParameterTemplate.objects.count(), 2)
     show_groups_url = reverse('respondent_groups_page')
     response = self.client.get(show_groups_url)
     self.assertEquals(
         response.status_code,
         302)  # only users with 'auth.can_view_household_groups' can access
     self.assign_permission_to(
         User.objects.create_user('user1', '*****@*****.**', 'demo123'),
         'can_view_household_groups')
     client = Client()
     client.login(username='******', password='******')
     response = client.get(show_groups_url)
     self.assertEquals(response.status_code, 200)
     create_group_url = reverse('new_respondent_groups_page')
     group_data = {
         'name':
         'group1',
         'description':
         'etc',
         'test_question':
         ParameterTemplate.objects.order_by('created').first().id,
         'validation_test':
         'between',
         'min':
         3,
         'max':
         5
     }
     response = client.post(create_group_url, data=group_data)
     self.assertEquals(response.status_code, 302)
     self.assertEquals(RespondentGroup.objects.count(), 1)
     group = RespondentGroup.objects.first()
     edit_group_url = reverse('respondent_groups_edit', args=(group.id, ))
     self.assertIn(edit_group_url, response.url)
     group_data = {
         'name': 'group1',
         'description': 'etc',
         'validation_test': 'equals',
         'test_question':
         ParameterTemplate.objects.order_by('created').last().id,
         'value': 1
     }
     response = client.post(edit_group_url,
                            data=group_data)  #just post to same url
     self.assertEquals(
         RespondentGroup.objects.first().group_conditions.count(), 2)
     self.assertEquals(response.status_code, 302)
     self.assertIn(edit_group_url, response.url)
    def get_interview_answers(self):
        report = []
        member_reports = OrderedDict()
        val_list_args = [  'interview__ea__locations__name',
                         'interview__ea__name', 'interview__householdmember__household__house_number',
                         'interview__householdmember__surname', 'interview__householdmember__first_name',
                         'interview__householdmember__date_of_birth', 'interview__householdmember__gender', ]
        parent_loc = 'interview__ea__locations'
        for i in range(LocationType.objects.count() - 2):
            parent_loc = '%s__parent' % parent_loc
            val_list_args.insert(0, '%s__name'%parent_loc)
        filter_args = {}
        if self.locations:
            filter_args['interview__ea__locations__in'] = self.locations
        if self.specific_households:
            filter_args['interview__householdmember__household__in'] = self.specific_households
        for answer_type in Answer.answer_types():
            query_args = list(val_list_args)
            value = 'value'
            if answer_type in [MultiChoiceAnswer.choice_name(), ]:
                value = 'value__order'
                if  self.multi_display == self.AS_LABEL:
                    value = 'value__order'
                else:
                    value = 'value__text'
            query_args.append(value)
            answer_class = Answer.get_class(answer_type)
            # print 'using query_args ', query_args
            answer_data = answer_class.objects.filter(interview__batch=self.batch, **filter_args).\
                values_list('interview__householdmember__pk', 'question__pk', *query_args).\
                        order_by('interview__ea__locations', 'interview__ea',
                                 'interview__householdmember__household').distinct(
                                                                            'interview__ea__locations',
                                                                            'interview__ea',
                                                                            'interview__householdmember__household',
                                                                            'interview__householdmember__pk',
                                                                            'question__pk'
                                                                            )
            answer_data = list(answer_data)
            # print 'answer data ', len(answer_data)
            #now grab member reports
            for data in answer_data:
                hm_pk, question_pk = data[:2]
                report_data = list(data[2:])
                hm_data = member_reports.get(hm_pk, None)
                if hm_data is None:
                    report_data.insert(-3, str(dateutils.relativedelta(datetime.utcnow().date(),
                                                                       report_data[-3]).years))
                    report_data[-3] = report_data[-3].strftime(settings.DATE_FORMAT)
                    report_data[-2] = 'M' if report_data[-2] else 'F'
                    member_details = [ unicode(md).encode('utf8') for md in report_data[:-1]]
                    hm_data = OrderedDict([('mem_details' , member_details), ])
                hm_data[question_pk] =  unicode(report_data[-1]).encode('utf8')
                member_reports[hm_pk] = hm_data

        for hm in member_reports.values():
            answers = hm['mem_details']
            for question in self.questions:
                answers.append(hm.get(question.pk, ''))
            report.append(answers)
        return report